From 854c31f835e445f5caecc8a9d6342f3677cb48c8 Mon Sep 17 00:00:00 2001 From: lillo Date: Sun, 4 Aug 2002 02:04:37 +0000 Subject: [PATCH] finished implementing get_thread_info, get_next_thread_info, get_team_info, get_next_team_info. New ps command behaving like the BeOS one is here, but doesn't work as libroot seems to crash when loaded at process startup... :/ git-svn-id: file:///srv/svn/repos/haiku/trunk/current@570 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/kernel/OS.h | 10 +- headers/os/kernel/syscalls.h | 7 +- headers/private/kernel/ksyscalls.h | 4 + headers/private/kernel/thread.h | 5 +- src/kernel/Jamfile | 1 + src/kernel/apps/ps/main.c | 97 ++++++------------- src/kernel/core/syscalls.c | 12 +++ src/kernel/core/team.c | 6 +- src/kernel/core/thread.c | 143 +++++++++++++++++++++++++++++ src/kernel/libroot/libroot.c | 33 +++++-- 10 files changed, 229 insertions(+), 89 deletions(-) diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index d537b79392..1d6bbc0173 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -345,14 +345,22 @@ thread_id find_thread(const char *); status_t snooze(bigtime_t); +status_t _get_thread_info(thread_id id, thread_info *info, size_t size); +status_t _get_next_thread_info(team_id team, int32 *cookie, thread_info *info, size_t size); status_t _get_team_info(team_id id, team_info *info, size_t size); status_t _get_next_team_info(int32 *cookie, team_info *info, size_t size); +#define get_thread_info(id, info) \ + _get_thread_info((id), (info), sizeof(*(info))) + +#define get_next_thread_info(team, cookie, info) \ + _get_next_thread_info((team), (cookie), (info), sizeof(*(info))) + #define get_team_info(id, info) \ _get_team_info((id), (info), sizeof(*(info))) #define get_next_team_info(cookie, info) \ - _get_next_sem_info((cookie), (info), sizeof(*(info))) + _get_next_team_info((cookie), (info), sizeof(*(info))) /** @} */ #ifdef __cplusplus diff --git a/headers/os/kernel/syscalls.h b/headers/os/kernel/syscalls.h index d5d92aac7a..dbf0ab33f5 100755 --- a/headers/os/kernel/syscalls.h +++ b/headers/os/kernel/syscalls.h @@ -60,8 +60,6 @@ int sys_get_sem_info(sem_id, struct sem_info *, size_t); int sys_get_next_sem_info(team_id, uint32 *, struct sem_info *, size_t); int sys_set_sem_owner(sem_id id, team_id proc); - -//int sys_team_get_table(struct proc_info *pi, size_t len); void sys_exit(int retcode); team_id sys_create_team(const char *path, const char *name, char **args, int argc, char **envp, int envc, int priority); @@ -77,6 +75,11 @@ int sys_kill_team(team_id tid); team_id sys_get_current_team_id(); int sys_wait_on_team(team_id tid, int *retcode); +status_t sys_get_thread_info(thread_id id, thread_info *info); +status_t sys_get_next_thread_info(team_id team, int32 *cookie, thread_info *info); +status_t sys_get_team_info(team_id id, team_info *info); +status_t sys_get_next_team_info(int32 *cookie, team_info *info); + region_id sys_vm_create_anonymous_region(const char *name, void **address, int addr_type, addr size, int wiring, int lock); region_id sys_vm_clone_region(const char *name, void **address, int addr_type, diff --git a/headers/private/kernel/ksyscalls.h b/headers/private/kernel/ksyscalls.h index f67a9d96a3..aa99fe9f6e 100755 --- a/headers/private/kernel/ksyscalls.h +++ b/headers/private/kernel/ksyscalls.h @@ -96,6 +96,10 @@ enum { SYSCALL_CREATE_DIR_ENTRY_REF, SYSCALL_CREATE_SYMLINK, SYSCALL_READ_LINK, + SYSCALL_GET_THREAD_INFO, + SYSCALL_GET_NEXT_THREAD_INFO, + SYSCALL_GET_TEAM_INFO, /* 90 */ + SYSCALL_GET_NEXT_TEAM_INFO, }; int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_ret); diff --git a/headers/private/kernel/thread.h b/headers/private/kernel/thread.h index ab158714d6..3362d1004c 100755 --- a/headers/private/kernel/thread.h +++ b/headers/private/kernel/thread.h @@ -58,6 +58,7 @@ team_id team_get_kernel_team_id(void); team_id team_get_current_team_id(void); char **user_team_get_arguments(void); int user_team_get_arg_count(void); +struct team *team_get_team_struct(team_id id); struct team *team_get_team_struct_locked(team_id id); // used in syscalls.c @@ -68,11 +69,11 @@ int user_team_wait_on_team(team_id id, int *uretcode); thread_id user_thread_create_user_thread(addr, team_id, const char*, int, void *); +status_t user_get_thread_info(thread_id id, thread_info *info); +status_t user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info); status_t user_get_team_info(team_id id, team_info *info); status_t user_get_next_team_info(int32 *cookie, team_info *info); - -//int user_proc_get_table(struct proc_info *pi, size_t len); int user_getrlimit(int resource, struct rlimit * rlp); int user_setrlimit(int resource, const struct rlimit * rlp); diff --git a/src/kernel/Jamfile b/src/kernel/Jamfile index 06db591dee..349881f2a5 100644 --- a/src/kernel/Jamfile +++ b/src/kernel/Jamfile @@ -728,6 +728,7 @@ KernelLd ps : libglue2.o <$(SOURCE_GRIST)!apps!ps>main.o libc.so + libroot.so : $(SUBDIR)/ldscripts/$(OBOS_ARCH)/app.ld : diff --git a/src/kernel/apps/ps/main.c b/src/kernel/apps/ps/main.c index 3927686bcc..1a10fad4db 100644 --- a/src/kernel/apps/ps/main.c +++ b/src/kernel/apps/ps/main.c @@ -1,83 +1,38 @@ /* -** Copyright 2002, Dan Sinclair. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ -/* - * This code was originally in the shell/command.c file and - * was written by: - * Damien Guard - * I just split it out into its own file -*/ + * PS command + * Rewritten for OpenBeOS by Angelo Mottola, Aug 2002. + */ +#include +#include #include #include #include #include -#if 0 - -#define MAX_PROCESSES 1024 - -typedef struct proc_info proc_info; - - -inline const char *proc_state_string (int state); - -inline -const char * -proc_state_string (int state) -{ - switch (state) { - case 0: return "normal"; - case 1: return "birth"; - case 2: return "death"; - default: - return "???"; - } -} - - -int -main(int argc, char ** argv) -{ - size_t table_size = MAX_PROCESSES * sizeof(proc_info); - proc_info *table = (proc_info *) malloc(table_size); - - if (table) { - int num_procs = sys_proc_get_table(table, table_size); - - if (num_procs <= 0) - printf("ps: sys_get_proc_table() returned error %s!\n", strerror(num_procs)); - - else { - int n = num_procs; - proc_info *p = table; - - printf("process list\n\n"); - printf("id\tstate\tthreads\tname\n"); - - while (n--) { - printf("%d\t%s\t%d\t%s\n", - p->id, - proc_state_string(p->state), - p->num_threads, - p->name); - p += sizeof(proc_info); - } - printf("\n%d processes listed\n", num_procs); - } - - free(table); - } - - return 0; -} - -#else int main(int argc, char **argv) { + int32 thread_num; + int32 team_num = 0; + thread_info thread; + team_info team; + + printf("\n thread name state prio user kernel semaphore\n"); + printf("-----------------------------------------------------------------------\n"); + + while (get_next_team_info(&team_num, &team) == B_OK) { + printf("%s (team %d) (uid %d) (gid %d)\n", + team.args, team.team, team.uid, team.gid); + thread_num = 0; + while (get_next_thread_info(team.team, &thread_num, &thread) == B_OK) { + // Fix thread state and sem output once states are BeOS compatible + printf(" %6d %20s %s %3d %7d %7d %s\n", + thread.thread, thread.name, "???", thread.priority, + (int)thread.user_time, (int)thread.kernel_time, ""); + } + } + printf("\n"); + return 0; } - -#endif diff --git a/src/kernel/core/syscalls.c b/src/kernel/core/syscalls.c index e60e12afef..87c68a05ae 100644 --- a/src/kernel/core/syscalls.c +++ b/src/kernel/core/syscalls.c @@ -330,6 +330,18 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re case SYSCALL_GETENV: *call_ret = user_getenv((const char *)arg0, (char **)arg1); break; + case SYSCALL_GET_THREAD_INFO: + *call_ret = user_get_thread_info((thread_id)arg0, (thread_info *)arg1); + break; + case SYSCALL_GET_NEXT_THREAD_INFO: + *call_ret = user_get_next_thread_info((team_id)arg0, (int32 *)arg1, (thread_info *)arg2); + break; + case SYSCALL_GET_TEAM_INFO: + *call_ret = user_get_team_info((team_id)arg0, (team_info *)arg1); + break; + case SYSCALL_GET_NEXT_TEAM_INFO: + *call_ret = user_get_next_team_info((int32 *)arg0, (team_info *)arg1); + break; default: *call_ret = -1; } diff --git a/src/kernel/core/team.c b/src/kernel/core/team.c index 7582c5db9e..5dfe2c814a 100644 --- a/src/kernel/core/team.c +++ b/src/kernel/core/team.c @@ -254,8 +254,8 @@ int team_wait_on_team(team_id id, int *retcode) return thread_wait_on_thread(tid, retcode); } -/* -static struct team *team_get_team_struct(team_id id) + +struct team *team_get_team_struct(team_id id) { struct team *p; int state; @@ -270,7 +270,7 @@ static struct team *team_get_team_struct(team_id id) return p; } -*/ + struct team *team_get_team_struct_locked(team_id id) { diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index 0419f610cb..d451de19c8 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -1289,6 +1289,149 @@ void thread_atkernel_exit(void) restore_interrupts(state); } + +status_t +user_get_thread_info(thread_id id, thread_info *info) +{ + thread_info kinfo; + status_t rc = B_OK; + status_t rc2; + + if ((addr)info >= KERNEL_BASE && (addr)info <= KERNEL_TOP) + return ERR_VM_BAD_USER_MEMORY; + + rc = _get_thread_info(id, &kinfo, sizeof(thread_info)); + if (rc != B_OK) + return rc; + + rc2 = user_memcpy(info, &kinfo, sizeof(team_info)); + if (rc2 < 0) + return rc2; + + return rc; +} + + +status_t +_get_thread_info(thread_id id, thread_info *info, size_t size) +{ + int state; + status_t rc = B_OK; + struct thread *t; + + state = disable_interrupts(); + GRAB_THREAD_LOCK(); + + t = thread_get_thread_struct_locked(id); + if (!t) { + rc = B_BAD_VALUE; + goto err; + } + info->thread = t->id; + info->team = t->team->id; + strncpy(info->name, t->name, B_OS_NAME_LENGTH); + info->name[B_OS_NAME_LENGTH - 1] = '\0'; + // XXX- Fix me + info->state = t->state; + info->priority = t->priority; + info->sem = t->sem_blocking; + info->user_time = t->user_time; + info->kernel_time = t->kernel_time; + info->stack_base = (void *)t->user_stack_base; + info->stack_end = (void *)(t->user_stack_base + STACK_SIZE); +err: + RELEASE_THREAD_LOCK(); + restore_interrupts(state); + + return rc; +} + + +status_t +user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info) +{ + int32 kcookie; + thread_info kinfo; + status_t rc = B_OK; + status_t rc2; + + if ((addr)cookie >= KERNEL_BASE && (addr)cookie <= KERNEL_TOP) + return ERR_VM_BAD_USER_MEMORY; + if ((addr)info >= KERNEL_BASE && (addr)info <= KERNEL_TOP) + return ERR_VM_BAD_USER_MEMORY; + + rc2 = user_memcpy(&kcookie, cookie, sizeof(int32)); + if (rc2 < 0) + return rc2; + + rc = _get_next_thread_info(team, &kcookie, &kinfo, sizeof(team_info)); + if (rc != B_OK) + return rc; + + rc2 = user_memcpy(cookie, &kcookie, sizeof(int32)); + if (rc2 < 0) + return rc2; + + rc2 = user_memcpy(info, &kinfo, sizeof(team_info)); + if (rc2 < 0) + return rc2; + + return rc; +} + + +status_t +_get_next_thread_info(team_id tid, int32 *cookie, thread_info *info, size_t size) +{ + int state; + int slot; + status_t rc = B_BAD_VALUE; + struct team *team; + struct thread *t = NULL; + + if (tid == 0) + tid = team_get_current_team_id(); + team = team_get_team_struct(tid); + if (!team) + return B_BAD_VALUE; + + state = disable_interrupts(); + GRAB_THREAD_LOCK(); + + if (*cookie == 0) + slot = 0; + else { + slot = *cookie; + if (slot >= next_thread_id) + goto err; + } + while (!(t = thread_get_thread_struct_locked(slot)) && (t->team->id != tid) && (slot < next_thread_id)) + slot++; + if (t) { + info->thread = t->id; + info->team = t->team->id; + strncpy(info->name, t->name, B_OS_NAME_LENGTH); + info->name[B_OS_NAME_LENGTH - 1] = '\0'; + // XXX- Fix me + info->state = t->state; + info->priority = t->priority; + info->sem = t->sem_blocking; + info->user_time = t->user_time; + info->kernel_time = t->kernel_time; + info->stack_base = (void *)t->user_stack_base; + info->stack_end = (void *)(t->user_stack_base + STACK_SIZE); + slot++; + *cookie = slot; + rc = B_OK; + } +err: + RELEASE_THREAD_LOCK(); + restore_interrupts(state); + + return rc; +} + + int user_getrlimit(int resource, struct rlimit * urlp) { int ret; diff --git a/src/kernel/libroot/libroot.c b/src/kernel/libroot/libroot.c index 5093fa9f1d..322164ad88 100755 --- a/src/kernel/libroot/libroot.c +++ b/src/kernel/libroot/libroot.c @@ -176,18 +176,25 @@ status_t wait_for_thread (thread_id thread, status_t *thread_return_value) // TO DO status_t on_exit_thread(void (*callback)(void *), void *data); -// TO DO -status_t _get_thread_info(thread_id thread, thread_info *info, size_t size); -// TO DO -status_t _get_next_thread_info(team_id tmid, int32 *cookie, thread_info *info, size_t size); + +// OK +status_t _get_thread_info(thread_id thread, thread_info *info, size_t size) + { return sys_get_thread_info(thread, info); } + +// OK +status_t _get_next_thread_info(team_id tmid, int32 *cookie, thread_info *info, size_t size) + { return sys_get_next_thread_info(tmid, cookie, info); } + // TO DO status_t _get_team_usage_info(team_id tmid, int32 who, team_usage_info *ti, size_t size); // TO DO thread_id find_thread(const char *name); +/* #define get_thread_info(thread, info) _get_thread_info((thread), (info), sizeof(*(info))) #define get_next_thread_info(tmid, cookie, info) _get_next_thread_info((tmid), (cookie), (info), sizeof(*(info))) #define get_team_usage_info(tmid, who, info) _get_team_usage_info((tmid), (who), (info), sizeof(*(info))) +*/ // TO DO status_t send_data(thread_id thread, int32 code, const void *buf, size_t buffer_size); @@ -204,12 +211,18 @@ status_t snooze_until(bigtime_t time, int timebase); status_t kill_team(team_id team) { return sys_kill_team(team); } -// TO DO -status_t _get_team_info(team_id team, team_info *info, size_t size); -// TO DO -status_t _get_next_team_info(int32 *cookie, team_info *info, size_t size); -//#define get_team_info(team, info) _get_team_info((team), (info), sizeof(*(info))) -//#define get_next_team_info(cookie, info) _get_next_team_info((cookie), (info), sizeof(*(info))) +// OK +status_t _get_team_info(team_id team, team_info *info, size_t size) + { return sys_get_team_info(team, info); } + +// OK +status_t _get_next_team_info(int32 *cookie, team_info *info, size_t size) + { return sys_get_next_team_info(cookie, info); } + +/* +#define get_team_info(team, info) _get_team_info((team), (info), sizeof(*(info))) +#define get_next_team_info(cookie, info) _get_next_team_info((cookie), (info), sizeof(*(info))) +*/ // TO DO status_t get_cpuid(cpuid_info* info, uint32 eax_register, uint32 cpu_num);