summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorBrian Gianforcaro <bgianf@serenityos.org>2021-05-19 22:16:41 -0700
committerAndreas Kling <kling@serenityos.org>2021-05-20 08:10:07 +0200
commite95eb7a51d8295c96cddf20f116139deecbb69d4 (patch)
tree56f0044de24a372c1afbcc96009b878ac78e3116 /Kernel
parentbb91bed576f244bb1ddf2faee64c36b18f644901 (diff)
downloadserenity-e95eb7a51d8295c96cddf20f116139deecbb69d4.zip
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.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/ProcessGroup.cpp17
-rw-r--r--Kernel/ProcessGroup.h2
2 files changed, 17 insertions, 2 deletions
diff --git a/Kernel/ProcessGroup.cpp b/Kernel/ProcessGroup.cpp
index 3a92151e51..23c429815b 100644
--- a/Kernel/ProcessGroup.cpp
+++ b/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;
diff --git a/Kernel/ProcessGroup.h b/Kernel/ProcessGroup.h
index 8ae5f295f5..fac329f1ec 100644
--- a/Kernel/ProcessGroup.h
+++ b/Kernel/ProcessGroup.h
@@ -40,6 +40,8 @@ private:
{
}
+ static RefPtr<ProcessGroup> from_pgid_nolock(ProcessGroupID);
+
ProcessGroup* m_prev { nullptr };
ProcessGroup* m_next { nullptr };