/* * Copyright (c) 2023-2024, Liav A. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include namespace Kernel { static Atomic s_scoped_process_list_id = 0; static Singleton> s_all_instances {}; ErrorOr> ScopedProcessList::scoped_process_list_for_id(int id) { if (id < 0) return Error::from_errno(EINVAL); auto index = static_cast(id); return s_all_instances->with([&](auto& list) -> ErrorOr> { for (auto& scoped_process_list : list) { if (scoped_process_list.id() == index) return scoped_process_list; } return Error::from_errno(ESRCNOTFOUND); }); } ErrorOr> ScopedProcessList::create() { return s_all_instances->with([&](auto& list) -> ErrorOr> { auto scoped_process_list = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ScopedProcessList())); list.append(scoped_process_list); return scoped_process_list; }); } ScopedProcessList::ScopedProcessList() : m_id(s_scoped_process_list_id.fetch_add(1)) { } void ScopedProcessList::attach(Process& process) { m_attach_count.with([&](auto& my_attach_count) { m_attached_processes.with([&](auto& attached_processes_list) { attached_processes_list.append(process); }); my_attach_count++; s_all_instances->with([&](auto& list) { // NOTE: It could happen that we have been detached from the // global list but a Process got a reference and wants to // attach so now re-attach this context. if (!list.contains(*this)) list.append(*this); }); }); } void ScopedProcessList::detach(Badge) { VERIFY(ref_count() > 0); m_attach_count.with([&](auto& my_attach_count) { VERIFY(my_attach_count > 0); my_attach_count--; s_all_instances->with([&](auto&) { if (my_attach_count == 0) m_list_node.remove(); }); }); } }