From 3fd4997fc266044805573c320dd2a2769ea64bd4 Mon Sep 17 00:00:00 2001 From: Liav A Date: Mon, 17 Jul 2023 18:34:19 +0300 Subject: [PATCH] Kernel: Don't allocate memory for names of processes and threads Instead, use the FixedCharBuffer class to ensure we always use a static buffer storage for these names. This ensures that if a Process or a Thread were created, there's a guarantee that setting a new name will never fail, as only copying of strings should be done to that static storage. The limits which are set are 32 characters for processes' names and 64 characters for thread names - this is because threads' names could be more verbose than processes' names. --- AK/Format.cpp | 6 +-- Kernel/Arch/init.cpp | 2 +- Kernel/Bus/USB/UHCI/UHCIController.cpp | 4 +- Kernel/FileSystem/Plan9FS/FileSystem.cpp | 5 +- .../SysFS/Subsystems/Kernel/Processes.cpp | 4 +- Kernel/Memory/MemoryManager.cpp | 2 +- Kernel/Net/NetworkTask.cpp | 5 +- Kernel/Syscalls/execve.cpp | 8 ++- Kernel/Syscalls/fork.cpp | 3 +- Kernel/Syscalls/kill.cpp | 2 +- Kernel/Syscalls/prctl.cpp | 14 +++--- Kernel/Syscalls/thread.cpp | 25 ++++------ Kernel/Tasks/FinalizerTask.cpp | 2 +- Kernel/Tasks/PerformanceEventBuffer.cpp | 2 +- Kernel/Tasks/PowerStateSwitchTask.cpp | 9 +--- Kernel/Tasks/Process.cpp | 50 +++++++++++-------- Kernel/Tasks/Process.h | 23 +++++---- Kernel/Tasks/Scheduler.cpp | 6 +-- Kernel/Tasks/SyncTask.cpp | 2 +- Kernel/Tasks/Thread.cpp | 22 ++++---- Kernel/Tasks/Thread.h | 11 ++-- Kernel/Tasks/WorkQueue.cpp | 5 +- 22 files changed, 102 insertions(+), 110 deletions(-) diff --git a/AK/Format.cpp b/AK/Format.cpp index 9835b3ef4e..757b3f5406 100644 --- a/AK/Format.cpp +++ b/AK/Format.cpp @@ -920,7 +920,7 @@ void vdbg(StringView fmtstr, TypeErasedFormatParams& params, bool newline) if (Kernel::Thread::current()) { auto& thread = *Kernel::Thread::current(); thread.process().name().with([&](auto& process_name) { - builder.appendff("{}.{:03} \033[34;1m[#{} {}({}:{})]\033[0m: ", time.truncated_seconds(), time.nanoseconds_within_second() / 1000000, Kernel::Processor::current_id(), process_name->view(), thread.pid().value(), thread.tid().value()); + builder.appendff("{}.{:03} \033[34;1m[#{} {}({}:{})]\033[0m: ", time.truncated_seconds(), time.nanoseconds_within_second() / 1000000, Kernel::Processor::current_id(), process_name.representable_view(), thread.pid().value(), thread.tid().value()); }); } else { builder.appendff("{}.{:03} \033[34;1m[#{} Kernel]\033[0m: ", time.truncated_seconds(), time.nanoseconds_within_second() / 1000000, Kernel::Processor::current_id()); @@ -974,7 +974,7 @@ void vdmesgln(StringView fmtstr, TypeErasedFormatParams& params) if (Kernel::Processor::is_initialized() && Kernel::Thread::current()) { auto& thread = *Kernel::Thread::current(); thread.process().name().with([&](auto& process_name) { - builder.appendff("{}.{:03} \033[34;1m[{}({}:{})]\033[0m: ", time.truncated_seconds(), time.nanoseconds_within_second() / 1000000, process_name->view(), thread.pid().value(), thread.tid().value()); + builder.appendff("{}.{:03} \033[34;1m[{}({}:{})]\033[0m: ", time.truncated_seconds(), time.nanoseconds_within_second() / 1000000, process_name.representable_view(), thread.pid().value(), thread.tid().value()); }); } else { builder.appendff("{}.{:03} \033[34;1m[Kernel]\033[0m: ", time.truncated_seconds(), time.nanoseconds_within_second() / 1000000); @@ -1001,7 +1001,7 @@ void v_critical_dmesgln(StringView fmtstr, TypeErasedFormatParams& params) if (Kernel::Processor::is_initialized() && Kernel::Thread::current()) { auto& thread = *Kernel::Thread::current(); thread.process().name().with([&](auto& process_name) { - builder.appendff("[{}({}:{})]: ", process_name->view(), thread.pid().value(), thread.tid().value()); + builder.appendff("[{}({}:{})]: ", process_name.representable_view(), thread.pid().value(), thread.tid().value()); }); } else { builder.appendff("[Kernel]: "); diff --git a/Kernel/Arch/init.cpp b/Kernel/Arch/init.cpp index 0f73c0ef9b..91ff95862d 100644 --- a/Kernel/Arch/init.cpp +++ b/Kernel/Arch/init.cpp @@ -298,7 +298,7 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init([[maybe_unused]] BootInfo con } #endif - MUST(Process::create_kernel_process(KString::must_create("init_stage2"sv), init_stage2, nullptr, THREAD_AFFINITY_DEFAULT, Process::RegisterProcess::No)); + MUST(Process::create_kernel_process("init_stage2"sv, init_stage2, nullptr, THREAD_AFFINITY_DEFAULT, Process::RegisterProcess::No)); Scheduler::start(); VERIFY_NOT_REACHED(); diff --git a/Kernel/Bus/USB/UHCI/UHCIController.cpp b/Kernel/Bus/USB/UHCI/UHCIController.cpp index a98bdab23a..e3d38a8f3c 100644 --- a/Kernel/Bus/USB/UHCI/UHCIController.cpp +++ b/Kernel/Bus/USB/UHCI/UHCIController.cpp @@ -585,7 +585,7 @@ size_t UHCIController::poll_transfer_queue(QueueHead& transfer_queue) ErrorOr UHCIController::spawn_port_process() { - TRY(Process::create_kernel_process(TRY(KString::try_create("UHCI Hot Plug Task"sv)), [&] { + TRY(Process::create_kernel_process("UHCI Hot Plug Task"sv, [&] { while (!Process::current().is_dying()) { if (m_root_hub) m_root_hub->check_for_port_updates(); @@ -600,7 +600,7 @@ ErrorOr UHCIController::spawn_port_process() ErrorOr UHCIController::spawn_async_poll_process() { - TRY(Process::create_kernel_process(TRY(KString::try_create("UHCI Async Poll Task"sv)), [&] { + TRY(Process::create_kernel_process("UHCI Async Poll Task"sv, [&] { u16 poll_interval_ms = 1024; while (!Process::current().is_dying()) { { diff --git a/Kernel/FileSystem/Plan9FS/FileSystem.cpp b/Kernel/FileSystem/Plan9FS/FileSystem.cpp index 8a6796344d..6adfa69a2b 100644 --- a/Kernel/FileSystem/Plan9FS/FileSystem.cpp +++ b/Kernel/FileSystem/Plan9FS/FileSystem.cpp @@ -350,10 +350,7 @@ void Plan9FS::ensure_thread() { SpinlockLocker lock(m_thread_lock); if (!m_thread_running.exchange(true, AK::MemoryOrder::memory_order_acq_rel)) { - auto process_name = KString::try_create("Plan9FS"sv); - if (process_name.is_error()) - TODO(); - auto [_, thread] = Process::create_kernel_process(process_name.release_value(), [&]() { + auto [_, thread] = Process::create_kernel_process("Plan9FS"sv, [&]() { thread_main(); m_thread_running.store(false, AK::MemoryOrder::memory_order_release); Process::current().sys$exit(0); diff --git a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp index c07618cb8c..a9f33351b1 100644 --- a/Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp +++ b/Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.cpp @@ -81,7 +81,7 @@ ErrorOr SysFSOverallProcesses::try_generate(KBufferBuilder& builder) } else { TRY(process_object.add("tty"sv, "")); } - TRY(process.name().with([&](auto& process_name) { return process_object.add("name"sv, process_name->view()); })); + TRY(process.name().with([&](auto& process_name) { return process_object.add("name"sv, process_name.representable_view()); })); TRY(process_object.add("executable"sv, process.executable() ? TRY(process.executable()->try_serialize_absolute_path())->view() : ""sv)); TRY(process_object.add("creation_time"sv, process.creation_time().nanoseconds_since_epoch())); @@ -121,7 +121,7 @@ ErrorOr SysFSOverallProcesses::try_generate(KBufferBuilder& builder) TRY(thread_object.add("lock_count"sv, thread.lock_count())); #endif TRY(thread_object.add("tid"sv, thread.tid().value())); - TRY(thread.name().with([&](auto& thread_name) { return thread_object.add("name"sv, thread_name->view()); })); + TRY(thread.name().with([&](auto& thread_name) { return thread_object.add("name"sv, thread_name.representable_view()); })); TRY(thread_object.add("times_scheduled"sv, thread.times_scheduled())); TRY(thread_object.add("time_user"sv, thread.time_in_user())); TRY(thread_object.add("time_kernel"sv, thread.time_in_kernel())); diff --git a/Kernel/Memory/MemoryManager.cpp b/Kernel/Memory/MemoryManager.cpp index 6c1469b84f..40f29eccd6 100644 --- a/Kernel/Memory/MemoryManager.cpp +++ b/Kernel/Memory/MemoryManager.cpp @@ -904,7 +904,7 @@ ErrorOr MemoryManager::commit_physical_pages(size_t pa }); process.name().with([&](auto& process_name) { dbgln("{}({}) resident:{}, shared:{}, virtual:{}", - process_name->view(), + process_name.representable_view(), process.pid(), amount_resident / PAGE_SIZE, amount_shared / PAGE_SIZE, diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index cf5636b780..66b6498220 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -42,10 +42,7 @@ static HashTable>* delayed_ack_sockets; void NetworkTask::spawn() { - auto name = KString::try_create("Network Task"sv); - if (name.is_error()) - TODO(); - auto [_, first_thread] = MUST(Process::create_kernel_process(name.release_value(), NetworkTask_main, nullptr)); + auto [_, first_thread] = MUST(Process::create_kernel_process("Network Task"sv, NetworkTask_main, nullptr)); network_task = first_thread; } diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp index e818c0df74..7e0b434094 100644 --- a/Kernel/Syscalls/execve.cpp +++ b/Kernel/Syscalls/execve.cpp @@ -480,9 +480,6 @@ ErrorOr Process::do_exec(NonnullRefPtr main_program_d auto last_part = path->view().find_last_split_view('/'); - auto new_process_name = TRY(KString::try_create(last_part)); - auto new_main_thread_name = TRY(new_process_name->try_clone()); - auto allocated_space = TRY(Memory::AddressSpace::try_create(*this, nullptr)); OwnPtr old_space; auto old_master_tls_region = m_master_tls_region; @@ -659,8 +656,9 @@ ErrorOr Process::do_exec(NonnullRefPtr main_program_d // and we don't want to deal with faults after this point. auto new_userspace_sp = TRY(make_userspace_context_for_main_thread(new_main_thread->regs(), *load_result.stack_region.unsafe_ptr(), m_arguments, m_environment, move(auxv))); - set_name(move(new_process_name)); - new_main_thread->set_name(move(new_main_thread_name)); + // NOTE: The Process and its first thread share the same name. + set_name(last_part); + new_main_thread->set_name(last_part); if (wait_for_tracer_at_next_execve()) { // Make sure we release the ptrace lock here or the tracer will block forever. diff --git a/Kernel/Syscalls/fork.cpp b/Kernel/Syscalls/fork.cpp index a148132007..219c0726a7 100644 --- a/Kernel/Syscalls/fork.cpp +++ b/Kernel/Syscalls/fork.cpp @@ -20,9 +20,8 @@ ErrorOr Process::sys$fork(RegisterState& regs) VERIFY_NO_PROCESS_BIG_LOCK(this); TRY(require_promise(Pledge::proc)); - auto child_name = TRY(name().with([](auto& name) { return name->try_clone(); })); auto credentials = this->credentials(); - auto child_and_first_thread = TRY(Process::create(move(child_name), credentials->uid(), credentials->gid(), pid(), m_is_kernel_process, current_directory(), executable(), tty(), this)); + auto child_and_first_thread = TRY(Process::create_with_forked_name(credentials->uid(), credentials->gid(), pid(), m_is_kernel_process, current_directory(), executable(), tty(), this)); auto& child = child_and_first_thread.process; auto& child_first_thread = child_and_first_thread.first_thread; diff --git a/Kernel/Syscalls/kill.cpp b/Kernel/Syscalls/kill.cpp index 7cbcaa6843..84491f6a66 100644 --- a/Kernel/Syscalls/kill.cpp +++ b/Kernel/Syscalls/kill.cpp @@ -22,7 +22,7 @@ ErrorOr Process::do_kill(Process& process, int signal) return EPERM; if (process.is_kernel_process()) { process.name().with([&](auto& process_name) { - dbgln("Attempted to send signal {} to kernel process {} ({})", signal, process_name->view(), process.pid()); + dbgln("Attempted to send signal {} to kernel process {} ({})", signal, process_name.representable_view(), process.pid()); }); return EPERM; } diff --git a/Kernel/Syscalls/prctl.cpp b/Kernel/Syscalls/prctl.cpp index 4eeabe2d14..5fdd60d9e7 100644 --- a/Kernel/Syscalls/prctl.cpp +++ b/Kernel/Syscalls/prctl.cpp @@ -55,14 +55,13 @@ ErrorOr Process::sys$prctl(int option, FlatPtr arg1, FlatPtr arg2) int user_buffer_size = static_cast(arg2); if (user_buffer_size < 0) return EINVAL; - if (user_buffer_size > 256) - return ENAMETOOLONG; size_t buffer_size = static_cast(user_buffer_size); - auto name = TRY(try_copy_kstring_from_user(buffer, buffer_size)); + Process::Name process_name {}; + TRY(try_copy_name_from_user_into_fixed_string_buffer<32>(buffer, process_name, buffer_size)); // NOTE: Reject empty and whitespace-only names, as they only confuse users. - if (name->view().is_whitespace()) + if (process_name.representable_view().is_whitespace()) return EINVAL; - set_name(move(name)); + set_name(process_name.representable_view()); return 0; } case PR_GET_PROCESS_NAME: { @@ -73,9 +72,10 @@ ErrorOr Process::sys$prctl(int option, FlatPtr arg1, FlatPtr arg2) return EINVAL; size_t buffer_size = static_cast(arg2); TRY(m_name.with([&buffer, buffer_size](auto& name) -> ErrorOr { - if (name->length() + 1 > buffer_size) + auto view = name.representable_view(); + if (view.length() + 1 > buffer_size) return ENAMETOOLONG; - return copy_to_user(buffer, name->characters(), name->length() + 1); + return copy_to_user(buffer, view.characters_without_null_termination(), view.length() + 1); })); return 0; } diff --git a/Kernel/Syscalls/thread.cpp b/Kernel/Syscalls/thread.cpp index 7017012f85..7c6f2ae317 100644 --- a/Kernel/Syscalls/thread.cpp +++ b/Kernel/Syscalls/thread.cpp @@ -48,9 +48,9 @@ ErrorOr Process::sys$create_thread(void* (*entry)(void*), Userspaceview(), thread->tid().value()); + return KString::formatted("{} [{}]", process_name.representable_view(), thread->tid().value()); })); - thread->set_name(move(new_thread_name)); + thread->set_name(new_thread_name->view()); if (!is_thread_joinable) thread->detach(); @@ -194,17 +194,14 @@ ErrorOr Process::sys$set_thread_name(pid_t tid, Userspace VERIFY_NO_PROCESS_BIG_LOCK(this); TRY(require_promise(Pledge::stdio)); - auto name = TRY(try_copy_kstring_from_user(user_name, user_name_length)); - - const size_t max_thread_name_size = 64; - if (name->length() > max_thread_name_size) - return ENAMETOOLONG; + Thread::Name thread_name {}; + TRY(try_copy_name_from_user_into_fixed_string_buffer<64>(user_name, thread_name, user_name_length)); auto thread = Thread::from_tid(tid); if (!thread || thread->pid() != pid()) return ESRCH; - thread->set_name(move(name)); + thread->set_name(thread_name.representable_view()); return 0; } @@ -220,16 +217,12 @@ ErrorOr Process::sys$get_thread_name(pid_t tid, Userspace buffer return ESRCH; TRY(thread->name().with([&](auto& thread_name) -> ErrorOr { - if (thread_name->view().is_null()) { - char null_terminator = '\0'; - TRY(copy_to_user(buffer, &null_terminator, sizeof(null_terminator))); - return {}; - } - - if (thread_name->length() + 1 > buffer_size) + VERIFY(!thread_name.representable_view().is_null()); + auto thread_name_view = thread_name.representable_view(); + if (thread_name_view.length() + 1 > buffer_size) return ENAMETOOLONG; - return copy_to_user(buffer, thread_name->characters(), thread_name->length() + 1); + return copy_to_user(buffer, thread_name_view.characters_without_null_termination(), thread_name_view.length() + 1); })); return 0; diff --git a/Kernel/Tasks/FinalizerTask.cpp b/Kernel/Tasks/FinalizerTask.cpp index 2fccea664a..9586a9b4ea 100644 --- a/Kernel/Tasks/FinalizerTask.cpp +++ b/Kernel/Tasks/FinalizerTask.cpp @@ -30,7 +30,7 @@ static void finalizer_task(void*) UNMAP_AFTER_INIT void FinalizerTask::spawn() { - auto [_, finalizer_thread] = MUST(Process::create_kernel_process(KString::must_create(finalizer_task_name), finalizer_task, nullptr)); + auto [_, finalizer_thread] = MUST(Process::create_kernel_process(finalizer_task_name, finalizer_task, nullptr)); g_finalizer = move(finalizer_thread); } diff --git a/Kernel/Tasks/PerformanceEventBuffer.cpp b/Kernel/Tasks/PerformanceEventBuffer.cpp index 7a67708e10..f0087e1ae4 100644 --- a/Kernel/Tasks/PerformanceEventBuffer.cpp +++ b/Kernel/Tasks/PerformanceEventBuffer.cpp @@ -340,7 +340,7 @@ ErrorOr PerformanceEventBuffer::add_process(Process const& process, Proces executable = TRY(process.executable()->try_serialize_absolute_path()); } else { executable = TRY(process.name().with([&](auto& process_name) { - return KString::formatted("<{}>", process_name->view()); + return KString::formatted("<{}>", process_name.representable_view()); })); } diff --git a/Kernel/Tasks/PowerStateSwitchTask.cpp b/Kernel/Tasks/PowerStateSwitchTask.cpp index 5d304e1c01..a12bc64052 100644 --- a/Kernel/Tasks/PowerStateSwitchTask.cpp +++ b/Kernel/Tasks/PowerStateSwitchTask.cpp @@ -26,8 +26,6 @@ namespace Kernel { -static constexpr StringView power_state_switch_task_name_view = "Power State Switch Task"sv; - Thread* g_power_state_switch_task; bool g_in_system_shutdown { false }; @@ -53,12 +51,9 @@ void PowerStateSwitchTask::power_state_switch_task(void* raw_entry_data) void PowerStateSwitchTask::spawn(PowerStateCommand command) { - // FIXME: If we switch power states during memory pressure, don't let the system crash just because of our task name. - NonnullOwnPtr power_state_switch_task_name = MUST(KString::try_create(power_state_switch_task_name_view)); - VERIFY(g_power_state_switch_task == nullptr); auto [_, power_state_switch_task_thread] = MUST(Process::create_kernel_process( - move(power_state_switch_task_name), power_state_switch_task, bit_cast(command))); + "Power State Switch Task"sv, power_state_switch_task, bit_cast(command))); g_power_state_switch_task = move(power_state_switch_task_thread); } @@ -189,7 +184,7 @@ ErrorOr PowerStateSwitchTask::kill_processes(ProcessKind kind, ProcessID f if (process.pid() != Process::current().pid() && !process.is_dead() && process.pid() != finalizer_pid && process.is_kernel_process() == kill_kernel_processes) { dbgln("Process {:2} kernel={} dead={} dying={} ({})", process.pid(), process.is_kernel_process(), process.is_dead(), process.is_dying(), - process.name().with([](auto& name) { return name->view(); })); + process.name().with([](auto& name) { return name.representable_view(); })); } }); } diff --git a/Kernel/Tasks/Process.cpp b/Kernel/Tasks/Process.cpp index 9834b7c98b..2c7651c59b 100644 --- a/Kernel/Tasks/Process.cpp +++ b/Kernel/Tasks/Process.cpp @@ -219,8 +219,7 @@ ErrorOr Process::create_user_process(StringView } auto path_string = TRY(KString::try_create(path)); - auto name = TRY(KString::try_create(parts.last())); - auto [process, first_thread] = TRY(Process::create(move(name), uid, gid, ProcessID(0), false, VirtualFileSystem::the().root_custody(), nullptr, tty)); + auto [process, first_thread] = TRY(Process::create(parts.last(), uid, gid, ProcessID(0), false, VirtualFileSystem::the().root_custody(), nullptr, tty)); TRY(process->m_fds.with_exclusive([&](auto& fds) -> ErrorOr { TRY(fds.try_resize(Process::OpenFileDescriptions::max_open())); @@ -255,9 +254,9 @@ ErrorOr Process::create_user_process(StringView return ProcessAndFirstThread { move(process), move(first_thread) }; } -ErrorOr Process::create_kernel_process(NonnullOwnPtr name, void (*entry)(void*), void* entry_data, u32 affinity, RegisterProcess do_register) +ErrorOr Process::create_kernel_process(StringView name, void (*entry)(void*), void* entry_data, u32 affinity, RegisterProcess do_register) { - auto process_and_first_thread = TRY(Process::create(move(name), UserID(0), GroupID(0), ProcessID(0), true)); + auto process_and_first_thread = TRY(Process::create(name, UserID(0), GroupID(0), ProcessID(0), true)); auto& process = *process_and_first_thread.process; auto& thread = *process_and_first_thread.first_thread; @@ -286,13 +285,22 @@ void Process::unprotect_data() }); } -ErrorOr Process::create(NonnullOwnPtr name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, RefPtr tty, Process* fork_parent) +ErrorOr Process::create_with_forked_name(UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, RefPtr tty, Process* fork_parent) +{ + Process::Name name {}; + Process::current().name().with([&name](auto& process_name) { + name.store_characters(process_name.representable_view()); + }); + return TRY(Process::create(name.representable_view(), uid, gid, ppid, is_kernel_process, current_directory, executable, tty, fork_parent)); +} + +ErrorOr Process::create(StringView name, UserID uid, GroupID gid, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, RefPtr tty, Process* fork_parent) { auto unveil_tree = UnveilNode { TRY(KString::try_create("/"sv)), UnveilMetadata(TRY(KString::try_create("/"sv))) }; auto exec_unveil_tree = UnveilNode { TRY(KString::try_create("/"sv)), UnveilMetadata(TRY(KString::try_create("/"sv))) }; auto credentials = TRY(Credentials::create(uid, gid, uid, gid, uid, gid, {}, fork_parent ? fork_parent->sid() : 0, fork_parent ? fork_parent->pgid() : 0)); - auto process = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Process(move(name), move(credentials), ppid, is_kernel_process, move(current_directory), move(executable), tty, move(unveil_tree), move(exec_unveil_tree), kgettimeofday()))); + auto process = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Process(name, move(credentials), ppid, is_kernel_process, move(current_directory), move(executable), tty, move(unveil_tree), move(exec_unveil_tree), kgettimeofday()))); OwnPtr new_address_space; if (fork_parent) { @@ -309,9 +317,8 @@ ErrorOr Process::create(NonnullOwnPtr n return ProcessAndFirstThread { move(process), move(first_thread) }; } -Process::Process(NonnullOwnPtr name, NonnullRefPtr credentials, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, RefPtr tty, UnveilNode unveil_tree, UnveilNode exec_unveil_tree, UnixDateTime creation_time) - : m_name(move(name)) - , m_is_kernel_process(is_kernel_process) +Process::Process(StringView name, NonnullRefPtr credentials, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, RefPtr tty, UnveilNode unveil_tree, UnveilNode exec_unveil_tree, UnixDateTime creation_time) + : m_is_kernel_process(is_kernel_process) , m_executable(move(executable)) , m_current_directory(move(current_directory)) , m_creation_time(creation_time) @@ -319,6 +326,7 @@ Process::Process(NonnullOwnPtr name, NonnullRefPtr credent , m_exec_unveil_data(move(exec_unveil_tree)) , m_wait_blocker_set(*this) { + set_name(name); // Ensure that we protect the process data when exiting the constructor. with_mutable_protected_data([&](auto& protected_data) { protected_data.pid = allocate_pid(); @@ -329,7 +337,7 @@ Process::Process(NonnullOwnPtr name, NonnullRefPtr credent if constexpr (PROCESS_DEBUG) { this->name().with([&](auto& process_name) { - dbgln("Created new process {}({})", process_name->view(), this->pid().value()); + dbgln("Created new process {}({})", process_name.representable_view(), this->pid().value()); }); } } @@ -701,7 +709,7 @@ ErrorOr Process::dump_core() return {}; } auto coredump_path = TRY(name().with([&](auto& process_name) { - return KString::formatted("{}/{}_{}_{}", coredump_directory_path->view(), process_name->view(), pid().value(), kgettimeofday().seconds_since_epoch()); + return KString::formatted("{}/{}_{}_{}", coredump_directory_path->view(), process_name.representable_view(), pid().value(), kgettimeofday().seconds_since_epoch()); })); auto coredump = TRY(Coredump::try_create(*this, coredump_path->view())); return coredump->write(); @@ -715,7 +723,7 @@ ErrorOr Process::dump_perfcore() // Try to generate a filename which isn't already used. auto base_filename = TRY(name().with([&](auto& process_name) { - return KString::formatted("{}_{}", process_name->view(), pid().value()); + return KString::formatted("{}_{}", process_name.representable_view(), pid().value()); })); auto perfcore_filename = TRY(KString::formatted("{}.profile", base_filename)); RefPtr description; @@ -757,7 +765,7 @@ void Process::finalize() if (veil_state() == VeilState::Dropped) { name().with([&](auto& process_name) { - dbgln("\x1b[01;31mProcess '{}' exited with the veil left open\x1b[0m", process_name->view()); + dbgln("\x1b[01;31mProcess '{}' exited with the veil left open\x1b[0m", process_name.representable_view()); }); } @@ -888,7 +896,7 @@ void Process::die() if constexpr (PROCESS_DEBUG) { process.name().with([&](auto& process_name) { name().with([&](auto& name) { - dbgln("Process {} ({}) is attached by {} ({}) which will exit", process_name->view(), process.pid(), name->view(), pid()); + dbgln("Process {} ({}) is attached by {} ({}) which will exit", process_name.representable_view(), process.pid(), name.representable_view(), pid()); }); }); } @@ -896,7 +904,7 @@ void Process::die() auto err = process.send_signal(SIGSTOP, this); if (err.is_error()) { process.name().with([&](auto& process_name) { - dbgln("Failed to send the SIGSTOP signal to {} ({})", process_name->view(), process.pid()); + dbgln("Failed to send the SIGSTOP signal to {} ({})", process_name.representable_view(), process.pid()); }); } } @@ -943,14 +951,14 @@ ErrorOr Process::send_signal(u8 signal, Process* sender) return ESRCH; } -ErrorOr> Process::create_kernel_thread(void (*entry)(void*), void* entry_data, u32 priority, NonnullOwnPtr name, u32 affinity, bool joinable) +ErrorOr> Process::create_kernel_thread(void (*entry)(void*), void* entry_data, u32 priority, StringView name, u32 affinity, bool joinable) { VERIFY((priority >= THREAD_PRIORITY_MIN) && (priority <= THREAD_PRIORITY_MAX)); // FIXME: Do something with guard pages? auto thread = TRY(Thread::create(*this)); - thread->set_name(move(name)); + thread->set_name(name); thread->set_affinity(affinity); thread->set_priority(priority); if (!joinable) @@ -1138,15 +1146,15 @@ ErrorOr> Process::custody_for_dirfd(int dirfd) return *description->custody(); } -SpinlockProtected, LockRank::None> const& Process::name() const +SpinlockProtected const& Process::name() const { return m_name; } -void Process::set_name(NonnullOwnPtr name) +void Process::set_name(StringView name) { - m_name.with([&](auto& this_name) { - this_name = move(name); + m_name.with([name](auto& process_name) { + process_name.store_characters(name); }); } diff --git a/Kernel/Tasks/Process.h b/Kernel/Tasks/Process.h index c1331dfb00..ffb3e42646 100644 --- a/Kernel/Tasks/Process.h +++ b/Kernel/Tasks/Process.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -193,13 +194,13 @@ public: }; template - static ErrorOr create_kernel_process(NonnullOwnPtr name, EntryFunction entry, u32 affinity = THREAD_AFFINITY_DEFAULT, RegisterProcess do_register = RegisterProcess::Yes) + static ErrorOr create_kernel_process(StringView name, EntryFunction entry, u32 affinity = THREAD_AFFINITY_DEFAULT, RegisterProcess do_register = RegisterProcess::Yes) { auto* entry_func = new EntryFunction(move(entry)); - return create_kernel_process(move(name), &Process::kernel_process_trampoline, entry_func, affinity, do_register); + return create_kernel_process(name, &Process::kernel_process_trampoline, entry_func, affinity, do_register); } - static ErrorOr create_kernel_process(NonnullOwnPtr name, void (*entry)(void*), void* entry_data = nullptr, u32 affinity = THREAD_AFFINITY_DEFAULT, RegisterProcess do_register = RegisterProcess::Yes); + static ErrorOr create_kernel_process(StringView name, void (*entry)(void*), void* entry_data = nullptr, u32 affinity = THREAD_AFFINITY_DEFAULT, RegisterProcess do_register = RegisterProcess::Yes); static ErrorOr create_user_process(StringView path, UserID, GroupID, Vector> arguments, Vector> environment, RefPtr); static void register_new(Process&); @@ -207,7 +208,7 @@ public: virtual void remove_from_secondary_lists(); - ErrorOr> create_kernel_thread(void (*entry)(void*), void* entry_data, u32 priority, NonnullOwnPtr name, u32 affinity = THREAD_AFFINITY_DEFAULT, bool joinable = true); + ErrorOr> create_kernel_thread(void (*entry)(void*), void* entry_data, u32 priority, StringView name, u32 affinity = THREAD_AFFINITY_DEFAULT, bool joinable = true); bool is_profiling() const { return m_profiling; } void set_profiling(bool profiling) { m_profiling = profiling; } @@ -228,8 +229,9 @@ public: static RefPtr from_pid_ignoring_jails(ProcessID); static SessionID get_sid_from_pgid(ProcessGroupID pgid); - SpinlockProtected, LockRank::None> const& name() const; - void set_name(NonnullOwnPtr); + using Name = FixedStringBuffer<32>; + SpinlockProtected const& name() const; + void set_name(StringView); ProcessID pid() const { @@ -612,8 +614,9 @@ private: bool add_thread(Thread&); bool remove_thread(Thread&); - Process(NonnullOwnPtr name, NonnullRefPtr, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, RefPtr tty, UnveilNode unveil_tree, UnveilNode exec_unveil_tree, UnixDateTime creation_time); - static ErrorOr create(NonnullOwnPtr name, UserID, GroupID, ProcessID ppid, bool is_kernel_process, RefPtr current_directory = nullptr, RefPtr executable = nullptr, RefPtr = nullptr, Process* fork_parent = nullptr); + Process(StringView name, NonnullRefPtr, ProcessID ppid, bool is_kernel_process, RefPtr current_directory, RefPtr executable, RefPtr tty, UnveilNode unveil_tree, UnveilNode exec_unveil_tree, UnixDateTime creation_time); + static ErrorOr create_with_forked_name(UserID, GroupID, ProcessID ppid, bool is_kernel_process, RefPtr current_directory = nullptr, RefPtr executable = nullptr, RefPtr = nullptr, Process* fork_parent = nullptr); + static ErrorOr create(StringView name, UserID, GroupID, ProcessID ppid, bool is_kernel_process, RefPtr current_directory = nullptr, RefPtr executable = nullptr, RefPtr = nullptr, Process* fork_parent = nullptr); ErrorOr> attach_resources(NonnullOwnPtr&&, Process* fork_parent); static ProcessID allocate_pid(); @@ -684,7 +687,7 @@ private: return nullptr; } - SpinlockProtected, LockRank::None> m_name; + SpinlockProtected m_name; SpinlockProtected, LockRank::None> m_space; @@ -1046,7 +1049,7 @@ struct AK::Formatter : AK::Formatter { ErrorOr format(FormatBuilder& builder, Kernel::Process const& value) { return value.name().with([&](auto& process_name) { - return AK::Formatter::format(builder, "{}({})"sv, process_name->view(), value.pid().value()); + return AK::Formatter::format(builder, "{}({})"sv, process_name.representable_view(), value.pid().value()); }); } }; diff --git a/Kernel/Tasks/Scheduler.cpp b/Kernel/Tasks/Scheduler.cpp index 9bb7821b5c..86b42000fb 100644 --- a/Kernel/Tasks/Scheduler.cpp +++ b/Kernel/Tasks/Scheduler.cpp @@ -372,10 +372,10 @@ UNMAP_AFTER_INIT void Scheduler::initialize() g_finalizer_wait_queue = new WaitQueue; g_finalizer_has_work.store(false, AK::MemoryOrder::memory_order_release); - auto [colonel_process, idle_thread] = MUST(Process::create_kernel_process(KString::must_create("colonel"sv), idle_loop, nullptr, 1, Process::RegisterProcess::No)); + auto [colonel_process, idle_thread] = MUST(Process::create_kernel_process("colonel"sv, idle_loop, nullptr, 1, Process::RegisterProcess::No)); s_colonel_process = &colonel_process.leak_ref(); idle_thread->set_priority(THREAD_PRIORITY_MIN); - idle_thread->set_name(KString::must_create("Idle Task #0"sv)); + idle_thread->set_name("Idle Task #0"sv); set_idle_thread(idle_thread); } @@ -394,7 +394,7 @@ UNMAP_AFTER_INIT Thread* Scheduler::create_ap_idle_thread(u32 cpu) VERIFY(Processor::is_bootstrap_processor()); VERIFY(s_colonel_process); - Thread* idle_thread = MUST(s_colonel_process->create_kernel_thread(idle_loop, nullptr, THREAD_PRIORITY_MIN, MUST(KString::formatted("idle thread #{}", cpu)), 1 << cpu, false)); + Thread* idle_thread = MUST(s_colonel_process->create_kernel_thread(idle_loop, nullptr, THREAD_PRIORITY_MIN, MUST(KString::formatted("idle thread #{}", cpu))->view(), 1 << cpu, false)); VERIFY(idle_thread); return idle_thread; } diff --git a/Kernel/Tasks/SyncTask.cpp b/Kernel/Tasks/SyncTask.cpp index d7574b3aef..9e7b87d6ff 100644 --- a/Kernel/Tasks/SyncTask.cpp +++ b/Kernel/Tasks/SyncTask.cpp @@ -14,7 +14,7 @@ namespace Kernel { UNMAP_AFTER_INIT void SyncTask::spawn() { - MUST(Process::create_kernel_process(KString::must_create("VFS Sync Task"sv), [] { + MUST(Process::create_kernel_process("VFS Sync Task"sv, [] { dbgln("VFS SyncTask is running"); while (!Process::current().is_dying()) { VirtualFileSystem::sync(); diff --git a/Kernel/Tasks/Thread.cpp b/Kernel/Tasks/Thread.cpp index c47ccc145a..813284fb5b 100644 --- a/Kernel/Tasks/Thread.cpp +++ b/Kernel/Tasks/Thread.cpp @@ -47,16 +47,18 @@ ErrorOr> Thread::create(NonnullRefPtr process) auto block_timer = TRY(try_make_ref_counted()); - auto name = TRY(process->name().with([](auto& name) { return name->try_clone(); })); - return adopt_nonnull_ref_or_enomem(new (nothrow) Thread(move(process), move(kernel_stack_region), move(block_timer), move(name))); + return adopt_nonnull_ref_or_enomem(new (nothrow) Thread(move(process), move(kernel_stack_region), move(block_timer))); } -Thread::Thread(NonnullRefPtr process, NonnullOwnPtr kernel_stack_region, NonnullRefPtr block_timer, NonnullOwnPtr name) +Thread::Thread(NonnullRefPtr process, NonnullOwnPtr kernel_stack_region, NonnullRefPtr block_timer) : m_process(move(process)) , m_kernel_stack_region(move(kernel_stack_region)) - , m_name(move(name)) , m_block_timer(move(block_timer)) { + m_process->name().with([this](auto& process_name) { + set_name(process_name.representable_view()); + }); + bool is_first_thread = m_process->add_thread(*this); if (is_first_thread) { // First thread gets TID == PID @@ -74,7 +76,7 @@ Thread::Thread(NonnullRefPtr process, NonnullOwnPtr ker if constexpr (THREAD_DEBUG) { m_process->name().with([&](auto& process_name) { - dbgln("Created new thread {}({}:{})", process_name->view(), m_process->pid().value(), m_tid.value()); + dbgln("Created new thread {}({}:{})", process_name.representable_view(), m_process->pid().value(), m_tid.value()); }); } @@ -1465,10 +1467,10 @@ void Thread::track_lock_release(LockRank rank) m_lock_rank_mask ^= rank; } -void Thread::set_name(NonnullOwnPtr name) +void Thread::set_name(StringView name) { - m_name.with([&](auto& this_name) { - this_name = move(name); + m_name.with([name](auto& thread_name) { + thread_name.store_characters(name); }); } @@ -1476,9 +1478,9 @@ void Thread::set_name(NonnullOwnPtr name) ErrorOr AK::Formatter::format(FormatBuilder& builder, Kernel::Thread const& value) { - return value.process().name().with([&](auto& process_name) { + return value.process().name().with([&](auto& thread_name) { return AK::Formatter::format( builder, - "{}({}:{})"sv, process_name->view(), value.pid().value(), value.tid().value()); + "{}({}:{})"sv, thread_name.representable_view(), value.pid().value(), value.tid().value()); }); } diff --git a/Kernel/Tasks/Thread.h b/Kernel/Tasks/Thread.h index 74d33a89b6..cec430fe66 100644 --- a/Kernel/Tasks/Thread.h +++ b/Kernel/Tasks/Thread.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -94,11 +95,13 @@ public: Process& process() { return m_process; } Process const& process() const { return m_process; } - SpinlockProtected, LockRank::None> const& name() const + using Name = FixedStringBuffer<64>; + SpinlockProtected const& name() const { return m_name; } - void set_name(NonnullOwnPtr name); + + void set_name(StringView); void finalize(); @@ -1083,7 +1086,7 @@ public: #endif private: - Thread(NonnullRefPtr, NonnullOwnPtr, NonnullRefPtr, NonnullOwnPtr); + Thread(NonnullRefPtr, NonnullOwnPtr, NonnullRefPtr); BlockResult block_impl(BlockTimeout const&, Blocker&); @@ -1221,7 +1224,7 @@ private: FPUState m_fpu_state {}; State m_state { Thread::State::Invalid }; - SpinlockProtected, LockRank::None> m_name; + SpinlockProtected m_name; u32 m_priority { THREAD_PRIORITY_NORMAL }; State m_stop_state { Thread::State::Invalid }; diff --git a/Kernel/Tasks/WorkQueue.cpp b/Kernel/Tasks/WorkQueue.cpp index e9102d0ce8..bf88875e1c 100644 --- a/Kernel/Tasks/WorkQueue.cpp +++ b/Kernel/Tasks/WorkQueue.cpp @@ -24,10 +24,7 @@ UNMAP_AFTER_INIT void WorkQueue::initialize() UNMAP_AFTER_INIT WorkQueue::WorkQueue(StringView name) { - auto name_kstring = KString::try_create(name); - if (name_kstring.is_error()) - TODO(); - auto [_, thread] = Process::create_kernel_process(name_kstring.release_value(), [this] { + auto [_, thread] = Process::create_kernel_process(name, [this] { while (!Process::current().is_dying()) { WorkItem* item; bool have_more;