Browse Source

Kernel: Avoid allocating under spinlock in ProcessGroup::find_or_create

Avoid allocating while holding the g_process_groups_lock spinlock, it's
a pattern that has a negative effect on performance and scalability,
especially given that it is a global lock, reachable by all processes.
Brian Gianforcaro 4 năm trước cách đây
mục cha
commit
e95eb7a51d
2 tập tin đã thay đổi với 17 bổ sung2 xóa
  1. 15 2
      Kernel/ProcessGroup.cpp
  2. 2 0
      Kernel/ProcessGroup.h

+ 15 - 2
Kernel/ProcessGroup.cpp

@@ -30,18 +30,31 @@ RefPtr<ProcessGroup> ProcessGroup::create(ProcessGroupID pgid)
 
 RefPtr<ProcessGroup> ProcessGroup::find_or_create(ProcessGroupID pgid)
 {
+    // Avoid allocating under spinlock, this compromises by wasting the
+    // allocation when we race with another process to see if they have
+    // already created a process group.
+    auto process_group = adopt_ref_if_nonnull(new ProcessGroup(pgid));
     ScopedSpinLock lock(g_process_groups_lock);
 
-    if (auto existing = from_pgid(pgid))
+    if (auto existing = from_pgid_nolock(pgid))
         return existing.release_nonnull();
 
-    return create(pgid);
+    if (!process_group)
+        return {};
+
+    g_process_groups->prepend(process_group);
+    return process_group;
 }
 
 RefPtr<ProcessGroup> ProcessGroup::from_pgid(ProcessGroupID pgid)
 {
     ScopedSpinLock lock(g_process_groups_lock);
+    return from_pgid_nolock(pgid);
+}
 
+RefPtr<ProcessGroup> ProcessGroup::from_pgid_nolock(ProcessGroupID pgid)
+{
+    VERIFY(g_process_groups_lock.own_lock());
     for (auto& group : *g_process_groups) {
         if (group.pgid() == pgid)
             return &group;

+ 2 - 0
Kernel/ProcessGroup.h

@@ -40,6 +40,8 @@ private:
     {
     }
 
+    static RefPtr<ProcessGroup> from_pgid_nolock(ProcessGroupID);
+
     ProcessGroup* m_prev { nullptr };
     ProcessGroup* m_next { nullptr };