mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 21:07:34 +00:00
Kernel: Expose thread stacks as separate files
This breaks SystemMonitor, which the next commit fixes.
This commit is contained in:
parent
9abac64333
commit
c3df2fe83f
1 changed files with 86 additions and 9 deletions
|
@ -69,7 +69,9 @@ enum ProcParentDirectory {
|
||||||
PDI_Root_net,
|
PDI_Root_net,
|
||||||
PDI_PID,
|
PDI_PID,
|
||||||
PDI_PID_fd,
|
PDI_PID_fd,
|
||||||
|
PDI_PID_stacks,
|
||||||
};
|
};
|
||||||
|
static_assert(PDI_PID_stacks < 16, "Too many directories for identifier scheme");
|
||||||
|
|
||||||
enum ProcFileType {
|
enum ProcFileType {
|
||||||
FI_Invalid = 0,
|
FI_Invalid = 0,
|
||||||
|
@ -111,7 +113,7 @@ enum ProcFileType {
|
||||||
__FI_PID_Start,
|
__FI_PID_Start,
|
||||||
FI_PID_vm,
|
FI_PID_vm,
|
||||||
FI_PID_vmobjects,
|
FI_PID_vmobjects,
|
||||||
FI_PID_stack,
|
FI_PID_stacks, // directory
|
||||||
FI_PID_fds,
|
FI_PID_fds,
|
||||||
FI_PID_unveil,
|
FI_PID_unveil,
|
||||||
FI_PID_exe, // symlink
|
FI_PID_exe, // symlink
|
||||||
|
@ -131,6 +133,12 @@ static inline ProcessID to_pid(const InodeIdentifier& identifier)
|
||||||
return identifier.index() >> 16u;
|
return identifier.index() >> 16u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline ThreadID to_tid(const InodeIdentifier& identifier)
|
||||||
|
{
|
||||||
|
// Sneakily, use the exact same mechanism.
|
||||||
|
return to_pid(identifier).value();
|
||||||
|
}
|
||||||
|
|
||||||
static inline ProcParentDirectory to_proc_parent_directory(const InodeIdentifier& identifier)
|
static inline ProcParentDirectory to_proc_parent_directory(const InodeIdentifier& identifier)
|
||||||
{
|
{
|
||||||
return (ProcParentDirectory)((identifier.index() >> 12) & 0xf);
|
return (ProcParentDirectory)((identifier.index() >> 12) & 0xf);
|
||||||
|
@ -164,6 +172,11 @@ static inline InodeIdentifier to_identifier_with_fd(unsigned fsid, ProcessID pid
|
||||||
return { fsid, (PDI_PID_fd << 12u) | ((unsigned)pid.value() << 16u) | (FI_MaxStaticFileIndex + fd) };
|
return { fsid, (PDI_PID_fd << 12u) | ((unsigned)pid.value() << 16u) | (FI_MaxStaticFileIndex + fd) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline InodeIdentifier to_identifier_with_stack(unsigned fsid, ThreadID tid)
|
||||||
|
{
|
||||||
|
return { fsid, (PDI_PID_stacks << 12u) | ((unsigned)tid.value() << 16u) | FI_MaxStaticFileIndex };
|
||||||
|
}
|
||||||
|
|
||||||
static inline InodeIdentifier sys_var_to_identifier(unsigned fsid, unsigned index)
|
static inline InodeIdentifier sys_var_to_identifier(unsigned fsid, unsigned index)
|
||||||
{
|
{
|
||||||
ASSERT(index < 256);
|
ASSERT(index < 256);
|
||||||
|
@ -184,6 +197,8 @@ static inline InodeIdentifier to_parent_id(const InodeIdentifier& identifier)
|
||||||
return to_identifier(identifier.fsid(), PDI_Root, to_pid(identifier), FI_PID);
|
return to_identifier(identifier.fsid(), PDI_Root, to_pid(identifier), FI_PID);
|
||||||
case PDI_PID_fd:
|
case PDI_PID_fd:
|
||||||
return to_identifier(identifier.fsid(), PDI_PID, to_pid(identifier), FI_PID_fd);
|
return to_identifier(identifier.fsid(), PDI_PID, to_pid(identifier), FI_PID_fd);
|
||||||
|
case PDI_PID_stacks:
|
||||||
|
return to_identifier(identifier.fsid(), PDI_PID, to_pid(identifier), FI_PID_stacks);
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -209,6 +224,12 @@ static inline bool is_process_related_file(const InodeIdentifier& identifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_thread_related_file(const InodeIdentifier& identifier)
|
||||||
|
{
|
||||||
|
auto proc_parent_directory = to_proc_parent_directory(identifier);
|
||||||
|
return proc_parent_directory == PDI_PID_stacks;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool is_directory(const InodeIdentifier& identifier)
|
static inline bool is_directory(const InodeIdentifier& identifier)
|
||||||
{
|
{
|
||||||
auto proc_file_type = to_proc_file_type(identifier);
|
auto proc_file_type = to_proc_file_type(identifier);
|
||||||
|
@ -218,6 +239,7 @@ static inline bool is_directory(const InodeIdentifier& identifier)
|
||||||
case FI_Root_net:
|
case FI_Root_net:
|
||||||
case FI_PID:
|
case FI_PID:
|
||||||
case FI_PID_fd:
|
case FI_PID_fd:
|
||||||
|
case FI_PID_stacks:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -626,12 +648,15 @@ Optional<KBuffer> procfs$pid_unveil(InodeIdentifier identifier)
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<KBuffer> procfs$pid_stack(InodeIdentifier identifier)
|
Optional<KBuffer> procfs$tid_stack(InodeIdentifier identifier)
|
||||||
{
|
{
|
||||||
auto process = Process::from_pid(to_pid(identifier));
|
auto thread = Thread::from_tid(to_tid(identifier));
|
||||||
if (!process)
|
if (!thread)
|
||||||
return {};
|
return {};
|
||||||
return process->backtrace();
|
KBufferBuilder builder;
|
||||||
|
builder.appendf("Thread %d (%s):\n", thread->tid().value(), thread->name().characters());
|
||||||
|
builder.append(thread->backtrace());
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<KBuffer> procfs$pid_exe(InodeIdentifier identifier)
|
Optional<KBuffer> procfs$pid_exe(InodeIdentifier identifier)
|
||||||
|
@ -1071,7 +1096,6 @@ InodeMetadata ProcFSInode::metadata() const
|
||||||
metadata.atime = mepoch;
|
metadata.atime = mepoch;
|
||||||
metadata.mtime = mepoch;
|
metadata.mtime = mepoch;
|
||||||
auto proc_parent_directory = to_proc_parent_directory(identifier());
|
auto proc_parent_directory = to_proc_parent_directory(identifier());
|
||||||
auto pid = to_pid(identifier());
|
|
||||||
auto proc_file_type = to_proc_file_type(identifier());
|
auto proc_file_type = to_proc_file_type(identifier());
|
||||||
|
|
||||||
#ifdef PROCFS_DEBUG
|
#ifdef PROCFS_DEBUG
|
||||||
|
@ -1079,6 +1103,7 @@ InodeMetadata ProcFSInode::metadata() const
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (is_process_related_file(identifier())) {
|
if (is_process_related_file(identifier())) {
|
||||||
|
ProcessID pid = to_pid(identifier());
|
||||||
auto process = Process::from_pid(pid);
|
auto process = Process::from_pid(pid);
|
||||||
if (process) {
|
if (process) {
|
||||||
metadata.uid = process->sys$getuid();
|
metadata.uid = process->sys$getuid();
|
||||||
|
@ -1088,6 +1113,17 @@ InodeMetadata ProcFSInode::metadata() const
|
||||||
metadata.uid = 0;
|
metadata.uid = 0;
|
||||||
metadata.gid = 0;
|
metadata.gid = 0;
|
||||||
}
|
}
|
||||||
|
} else if (is_thread_related_file(identifier())) {
|
||||||
|
ThreadID tid = to_tid(identifier());
|
||||||
|
auto thread = Thread::from_tid(tid);
|
||||||
|
if (thread) {
|
||||||
|
metadata.uid = thread->process().sys$getuid();
|
||||||
|
metadata.gid = thread->process().sys$getgid();
|
||||||
|
} else {
|
||||||
|
// TODO: How to handle this?
|
||||||
|
metadata.uid = 0;
|
||||||
|
metadata.gid = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proc_parent_directory == PDI_PID_fd) {
|
if (proc_parent_directory == PDI_PID_fd) {
|
||||||
|
@ -1111,6 +1147,7 @@ InodeMetadata ProcFSInode::metadata() const
|
||||||
break;
|
break;
|
||||||
case FI_PID:
|
case FI_PID:
|
||||||
case FI_PID_fd:
|
case FI_PID_fd:
|
||||||
|
case FI_PID_stacks:
|
||||||
metadata.mode = S_IFDIR | S_IRUSR | S_IXUSR;
|
metadata.mode = S_IFDIR | S_IRUSR | S_IXUSR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1152,6 +1189,10 @@ ssize_t ProcFSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDes
|
||||||
callback_tmp = procfs$pid_fd_entry;
|
callback_tmp = procfs$pid_fd_entry;
|
||||||
read_callback = &callback_tmp;
|
read_callback = &callback_tmp;
|
||||||
break;
|
break;
|
||||||
|
case PDI_PID_stacks:
|
||||||
|
callback_tmp = procfs$tid_stack;
|
||||||
|
read_callback = &callback_tmp;
|
||||||
|
break;
|
||||||
case PDI_Root_sys:
|
case PDI_Root_sys:
|
||||||
switch (SysVariable::for_inode(identifier()).type) {
|
switch (SysVariable::for_inode(identifier()).type) {
|
||||||
case SysVariable::Type::Invalid:
|
case SysVariable::Type::Invalid:
|
||||||
|
@ -1209,7 +1250,6 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
|
||||||
if (!Kernel::is_directory(identifier()))
|
if (!Kernel::is_directory(identifier()))
|
||||||
return KResult(-ENOTDIR);
|
return KResult(-ENOTDIR);
|
||||||
|
|
||||||
auto pid = to_pid(identifier());
|
|
||||||
auto proc_file_type = to_proc_file_type(identifier());
|
auto proc_file_type = to_proc_file_type(identifier());
|
||||||
auto parent_id = to_parent_id(identifier());
|
auto parent_id = to_parent_id(identifier());
|
||||||
|
|
||||||
|
@ -1248,6 +1288,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FI_PID: {
|
case FI_PID: {
|
||||||
|
auto pid = to_pid(identifier());
|
||||||
auto process = Process::from_pid(pid);
|
auto process = Process::from_pid(pid);
|
||||||
if (!process)
|
if (!process)
|
||||||
return KResult(-ENOENT);
|
return KResult(-ENOENT);
|
||||||
|
@ -1262,6 +1303,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FI_PID_fd: {
|
case FI_PID_fd: {
|
||||||
|
auto pid = to_pid(identifier());
|
||||||
auto process = Process::from_pid(pid);
|
auto process = Process::from_pid(pid);
|
||||||
if (!process)
|
if (!process)
|
||||||
return KResult(-ENOENT);
|
return KResult(-ENOENT);
|
||||||
|
@ -1274,6 +1316,21 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
|
||||||
callback({ name, name_length, to_identifier_with_fd(fsid(), pid, i), 0 });
|
callback({ name, name_length, to_identifier_with_fd(fsid(), pid, i), 0 });
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case FI_PID_stacks: {
|
||||||
|
auto pid = to_pid(identifier());
|
||||||
|
auto process = Process::from_pid(pid);
|
||||||
|
if (!process)
|
||||||
|
return KResult(-ENOENT);
|
||||||
|
process->for_each_thread([&](Thread& thread) -> IterationDecision {
|
||||||
|
int tid = thread.tid().value();
|
||||||
|
char name[16];
|
||||||
|
size_t name_length = (size_t)sprintf(name, "%d", tid);
|
||||||
|
callback({ name, name_length, to_identifier_with_stack(fsid(), tid), 0 });
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return KSuccess;
|
return KSuccess;
|
||||||
}
|
}
|
||||||
|
@ -1367,6 +1424,25 @@ RefPtr<Inode> ProcFSInode::lookup(StringView name)
|
||||||
if (fd_exists)
|
if (fd_exists)
|
||||||
return fs().get_inode(to_identifier_with_fd(fsid(), to_pid(identifier()), name_as_number.value()));
|
return fs().get_inode(to_identifier_with_fd(fsid(), to_pid(identifier()), name_as_number.value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (proc_file_type == FI_PID_stacks) {
|
||||||
|
auto name_as_number = name.to_int();
|
||||||
|
if (!name_as_number.has_value())
|
||||||
|
return {};
|
||||||
|
int tid = name_as_number.value();
|
||||||
|
if (tid <= 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
bool thread_exists = false;
|
||||||
|
{
|
||||||
|
auto process = Process::from_pid(to_pid(identifier()));
|
||||||
|
auto thread = Thread::from_tid(tid);
|
||||||
|
thread_exists = process && thread && process->pid() == thread->pid();
|
||||||
|
}
|
||||||
|
if (thread_exists)
|
||||||
|
return fs().get_inode(to_identifier_with_stack(fsid(), tid));
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1416,6 +1492,8 @@ ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, F
|
||||||
|
|
||||||
KResultOr<NonnullRefPtr<Custody>> ProcFSInode::resolve_as_link(Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const
|
KResultOr<NonnullRefPtr<Custody>> ProcFSInode::resolve_as_link(Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const
|
||||||
{
|
{
|
||||||
|
// The only links are in pid directories, so it's safe to ignore
|
||||||
|
// unrelated files and the thread-specific stacks/ directory.
|
||||||
if (!is_process_related_file(identifier()))
|
if (!is_process_related_file(identifier()))
|
||||||
return Inode::resolve_as_link(base, out_parent, options, symlink_recursion_level);
|
return Inode::resolve_as_link(base, out_parent, options, symlink_recursion_level);
|
||||||
|
|
||||||
|
@ -1600,7 +1678,7 @@ ProcFS::ProcFS()
|
||||||
|
|
||||||
m_entries[FI_PID_vm] = { "vm", FI_PID_vm, false, procfs$pid_vm };
|
m_entries[FI_PID_vm] = { "vm", FI_PID_vm, false, procfs$pid_vm };
|
||||||
m_entries[FI_PID_vmobjects] = { "vmobjects", FI_PID_vmobjects, true, procfs$pid_vmobjects };
|
m_entries[FI_PID_vmobjects] = { "vmobjects", FI_PID_vmobjects, true, procfs$pid_vmobjects };
|
||||||
m_entries[FI_PID_stack] = { "stack", FI_PID_stack, false, procfs$pid_stack };
|
m_entries[FI_PID_stacks] = { "stacks", FI_PID_stacks, false };
|
||||||
m_entries[FI_PID_fds] = { "fds", FI_PID_fds, false, procfs$pid_fds };
|
m_entries[FI_PID_fds] = { "fds", FI_PID_fds, false, procfs$pid_fds };
|
||||||
m_entries[FI_PID_exe] = { "exe", FI_PID_exe, false, procfs$pid_exe };
|
m_entries[FI_PID_exe] = { "exe", FI_PID_exe, false, procfs$pid_exe };
|
||||||
m_entries[FI_PID_cwd] = { "cwd", FI_PID_cwd, false, procfs$pid_cwd };
|
m_entries[FI_PID_cwd] = { "cwd", FI_PID_cwd, false, procfs$pid_cwd };
|
||||||
|
@ -1621,5 +1699,4 @@ KResult ProcFSInode::chown(uid_t, gid_t)
|
||||||
{
|
{
|
||||||
return KResult(-EPERM);
|
return KResult(-EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue