mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-14 20:03:29 +00:00
Kernel+LibCore: Make %sid path parsing not take ages
Before this patch, Core::SessionManagement::parse_path_with_sid() would figure out the root session ID by sifting through /sys/kernel/processes. That file can take quite a while to generate (sometimes up to 40ms on my machine, which is a problem on its own!) and with no caching, many of our programs were effectively doing this multiple times on startup when unveiling something in /tmp/session/%sid/ While we should find ways to make generating /sys/kernel/processes fast again, this patch addresses the specific problem by introducing a new syscall: sys$get_root_session_id(). This extracts the root session ID by looking directly at the process table and takes <1ms instead of 40ms. This cuts WebContent process startup time by ~100ms on my machine. :^)
This commit is contained in:
parent
491edaffc7
commit
5dcc58d54a
|
@ -81,6 +81,7 @@ enum class NeedsBigProcessLock {
|
||||||
S(futex, NeedsBigProcessLock::Yes) \
|
S(futex, NeedsBigProcessLock::Yes) \
|
||||||
S(get_dir_entries, NeedsBigProcessLock::Yes) \
|
S(get_dir_entries, NeedsBigProcessLock::Yes) \
|
||||||
S(get_process_name, NeedsBigProcessLock::Yes) \
|
S(get_process_name, NeedsBigProcessLock::Yes) \
|
||||||
|
S(get_root_session_id, NeedsBigProcessLock::No) \
|
||||||
S(get_stack_bounds, NeedsBigProcessLock::No) \
|
S(get_stack_bounds, NeedsBigProcessLock::No) \
|
||||||
S(get_thread_name, NeedsBigProcessLock::Yes) \
|
S(get_thread_name, NeedsBigProcessLock::Yes) \
|
||||||
S(getcwd, NeedsBigProcessLock::No) \
|
S(getcwd, NeedsBigProcessLock::No) \
|
||||||
|
|
|
@ -448,6 +448,7 @@ public:
|
||||||
ErrorOr<FlatPtr> sys$map_time_page();
|
ErrorOr<FlatPtr> sys$map_time_page();
|
||||||
ErrorOr<FlatPtr> sys$jail_create(Userspace<Syscall::SC_jail_create_params*> user_params);
|
ErrorOr<FlatPtr> sys$jail_create(Userspace<Syscall::SC_jail_create_params*> user_params);
|
||||||
ErrorOr<FlatPtr> sys$jail_attach(Userspace<Syscall::SC_jail_attach_params const*> user_params);
|
ErrorOr<FlatPtr> sys$jail_attach(Userspace<Syscall::SC_jail_attach_params const*> user_params);
|
||||||
|
ErrorOr<FlatPtr> sys$get_root_session_id(pid_t force_sid);
|
||||||
|
|
||||||
template<bool sockname, typename Params>
|
template<bool sockname, typename Params>
|
||||||
ErrorOr<void> get_sock_or_peer_name(Params const&);
|
ErrorOr<void> get_sock_or_peer_name(Params const&);
|
||||||
|
|
|
@ -139,4 +139,25 @@ ErrorOr<FlatPtr> Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<FlatPtr> Process::sys$get_root_session_id(pid_t force_sid)
|
||||||
|
{
|
||||||
|
pid_t sid = (force_sid == -1) ? this->sid().value() : force_sid;
|
||||||
|
if (sid == 0)
|
||||||
|
return 0;
|
||||||
|
while (true) {
|
||||||
|
auto sid_process = Process::from_pid_in_same_jail(sid);
|
||||||
|
if (!sid_process)
|
||||||
|
return ESRCH;
|
||||||
|
auto parent_pid = sid_process->ppid().value();
|
||||||
|
auto parent_process = Process::from_pid_in_same_jail(parent_pid);
|
||||||
|
if (!parent_process)
|
||||||
|
return ESRCH;
|
||||||
|
pid_t parent_sid = parent_process->sid().value();
|
||||||
|
if (parent_sid == 0)
|
||||||
|
break;
|
||||||
|
sid = parent_sid;
|
||||||
|
}
|
||||||
|
return sid;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,37 +5,26 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibCore/Directory.h>
|
#include <LibCore/Directory.h>
|
||||||
#include <LibCore/ProcessStatisticsReader.h>
|
|
||||||
#include <LibCore/SessionManagement.h>
|
#include <LibCore/SessionManagement.h>
|
||||||
#include <LibCore/System.h>
|
#include <LibCore/System.h>
|
||||||
|
|
||||||
|
#ifdef AK_OS_SERENITY
|
||||||
|
# include <LibSystem/syscall.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Core::SessionManagement {
|
namespace Core::SessionManagement {
|
||||||
|
|
||||||
static ErrorOr<Core::ProcessStatistics const*> get_proc(Core::AllProcessesStatistics const& stats, pid_t pid)
|
ErrorOr<pid_t> root_session_id([[maybe_unused]] Optional<pid_t> force_sid)
|
||||||
{
|
{
|
||||||
for (auto& proc : stats.processes) {
|
#ifdef AK_OS_SERENITY
|
||||||
if (proc.pid == pid)
|
int rc = syscall(SC_get_root_session_id, force_sid.value_or(-1));
|
||||||
return &proc;
|
if (rc < 0) {
|
||||||
|
return Error::from_syscall("get_root_session_id"sv, rc);
|
||||||
}
|
}
|
||||||
return Error::from_string_literal("Could not find pid in process statistics.");
|
return static_cast<pid_t>(rc);
|
||||||
}
|
#else
|
||||||
|
return 0;
|
||||||
ErrorOr<pid_t> root_session_id(Optional<pid_t> force_sid)
|
#endif
|
||||||
{
|
|
||||||
auto stats = TRY(Core::ProcessStatisticsReader::get_all(false));
|
|
||||||
|
|
||||||
pid_t sid = (force_sid.has_value()) ? force_sid.value() : TRY(System::getsid());
|
|
||||||
while (true) {
|
|
||||||
pid_t parent = TRY(get_proc(stats, sid))->ppid;
|
|
||||||
pid_t parent_sid = TRY(get_proc(stats, parent))->sid;
|
|
||||||
|
|
||||||
if (parent_sid == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
sid = parent_sid;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> logout(Optional<pid_t> force_sid)
|
ErrorOr<void> logout(Optional<pid_t> force_sid)
|
||||||
|
|
Loading…
Reference in a new issue