diff options
author | Brian Gianforcaro <bgianf@serenityos.org> | 2021-05-19 22:16:41 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-20 08:10:07 +0200 |
commit | e95eb7a51d8295c96cddf20f116139deecbb69d4 (patch) | |
tree | 56f0044de24a372c1afbcc96009b878ac78e3116 /Kernel | |
parent | bb91bed576f244bb1ddf2faee64c36b18f644901 (diff) | |
download | serenity-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.cpp | 17 | ||||
-rw-r--r-- | Kernel/ProcessGroup.h | 2 |
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 }; |