From 9fac193453af32f04fda750f4422be1765f86a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 21 Apr 2004 22:57:39 +0000 Subject: [PATCH] Partially implemented get_system_info(), courtesy of Jack Burton. Added system_info.c to the build. Added stats support functions to sems & ports. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7290 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/core/Jamfile | 50 ++++++++++++--------- src/kernel/core/port.c | 71 +++++++++++++++++++---------- src/kernel/core/sem.c | 61 +++++++++++++++++-------- src/kernel/core/syscalls.c | 5 ++- src/kernel/core/system_info.c | 85 +++++++++++++++++++++++++++++++++++ 5 files changed, 208 insertions(+), 64 deletions(-) create mode 100644 src/kernel/core/system_info.c diff --git a/src/kernel/core/Jamfile b/src/kernel/core/Jamfile index 8600103b8a..4ea85d7aa4 100644 --- a/src/kernel/core/Jamfile +++ b/src/kernel/core/Jamfile @@ -1,37 +1,47 @@ SubDir OBOS_TOP src kernel core ; +{ + local defines = + OBOS_ARCH=\\\"$(OBOS_ARCH)\\\" + ; + + defines = [ FDefines $(defines) ] ; + SubDirCcFlags $(defines) ; + SubDirC++Flags $(defines) ; +} + KernelMergeObject kernel_core.o : <$(SOURCE_GRIST)>cbuf.c <$(SOURCE_GRIST)>console.c <$(SOURCE_GRIST)>cpu.c <$(SOURCE_GRIST)>debug.c - <$(SOURCE_GRIST)>elf.c + <$(SOURCE_GRIST)>elf.c <$(SOURCE_GRIST)>faults.c - <$(SOURCE_GRIST)>gdb.c - <$(SOURCE_GRIST)>heap.c - <$(SOURCE_GRIST)>image.c - <$(SOURCE_GRIST)>int.c - <$(SOURCE_GRIST)>kernel_daemon.c - <$(SOURCE_GRIST)>khash.c - <$(SOURCE_GRIST)>linkhack.c - <$(SOURCE_GRIST)>lock.c - <$(SOURCE_GRIST)>main.c - <$(SOURCE_GRIST)>misc.c - <$(SOURCE_GRIST)>module.c -# <$(SOURCE_GRIST)>pools.c - <$(SOURCE_GRIST)>port.c + <$(SOURCE_GRIST)>gdb.c + <$(SOURCE_GRIST)>heap.c + <$(SOURCE_GRIST)>image.c + <$(SOURCE_GRIST)>int.c + <$(SOURCE_GRIST)>kernel_daemon.c + <$(SOURCE_GRIST)>khash.c + <$(SOURCE_GRIST)>linkhack.c + <$(SOURCE_GRIST)>lock.c + <$(SOURCE_GRIST)>main.c + <$(SOURCE_GRIST)>misc.c + <$(SOURCE_GRIST)>module.c + <$(SOURCE_GRIST)>port.c <$(SOURCE_GRIST)>queue.c <$(SOURCE_GRIST)>real_time_clock.c - <$(SOURCE_GRIST)>scheduler.c + <$(SOURCE_GRIST)>scheduler.c <$(SOURCE_GRIST)>sem.c <$(SOURCE_GRIST)>signal.c + <$(SOURCE_GRIST)>system_info.c <$(SOURCE_GRIST)>smp.c - <$(SOURCE_GRIST)>syscalls.c + <$(SOURCE_GRIST)>syscalls.c <$(SOURCE_GRIST)>sysctl.c - <$(SOURCE_GRIST)>team.c - <$(SOURCE_GRIST)>thread.c - <$(SOURCE_GRIST)>timer.c - : + <$(SOURCE_GRIST)>team.c + <$(SOURCE_GRIST)>thread.c + <$(SOURCE_GRIST)>timer.c + : -fno-pic -D_KERNEL_MODE ; diff --git a/src/kernel/core/port.c b/src/kernel/core/port.c index 5ddf75c205..3a85ede1af 100644 --- a/src/kernel/core/port.c +++ b/src/kernel/core/port.c @@ -54,8 +54,8 @@ static int dump_port_info(int argc, char **argv); static void _dump_port_info(struct port_entry *port); -// gMaxPorts must be power of 2 -int32 gMaxPorts = 4096; +// sMaxPorts must be power of 2 +static int32 sMaxPorts = 4096; #define MAX_QUEUE_LENGTH 4096 #define PORT_MAX_MESSAGE_SIZE 65536 @@ -77,7 +77,7 @@ status_t port_init(kernel_args *ka) { int i; - int size = sizeof(struct port_entry) * gMaxPorts; + int size = sizeof(struct port_entry) * sMaxPorts; // create and initialize ports table sPortArea = create_area("port_table", (void **)&sPorts, B_ANY_KERNEL_ADDRESS, @@ -91,7 +91,7 @@ port_init(kernel_args *ka) // might do it as well, though :-) memset(sPorts, 0, size); - for (i = 0; i < gMaxPorts; i++) + for (i = 0; i < sMaxPorts; i++) sPorts[i].id = -1; // add debugger commands @@ -212,7 +212,7 @@ dump_port_list(int argc, char **argv) { int i; - for (i = 0; i < gMaxPorts; i++) { + for (i = 0; i < sMaxPorts; i++) { if (sPorts[i].id >= 0) dprintf("%p\tid: 0x%lx\t\tname: '%s'\n", &sPorts[i], sPorts[i].id, sPorts[i].name); } @@ -251,11 +251,11 @@ dump_port_info(int argc, char **argv) if (num > KERNEL_BASE && num <= (KERNEL_BASE + (KERNEL_SIZE - 1))) { // XXX semi-hack - // one can use either address or a port_id, since KERNEL_BASE > gMaxPorts assumed + // one can use either address or a port_id, since KERNEL_BASE > sMaxPorts assumed _dump_port_info((struct port_entry *)num); return 0; } else { - unsigned slot = num % gMaxPorts; + unsigned slot = num % sMaxPorts; if(sPorts[slot].id != (int)num) { dprintf("port 0x%lx doesn't exist!\n", num); return 0; @@ -266,7 +266,7 @@ dump_port_info(int argc, char **argv) } // walk through the ports list, trying to match name - for (i = 0; i < gMaxPorts; i++) { + for (i = 0; i < sMaxPorts; i++) { if (sPorts[i].name != NULL && strcmp(argv[1], sPorts[i].name) == 0) { _dump_port_info(&sPorts[i]); @@ -296,7 +296,7 @@ delete_owned_ports(team_id owner) state = disable_interrupts(); GRAB_PORT_LIST_LOCK(); - for (i = 0; i < gMaxPorts; i++) { + for (i = 0; i < sMaxPorts; i++) { if (sPorts[i].id != -1 && sPorts[i].owner == owner) { port_id id = sPorts[i].id; @@ -351,6 +351,29 @@ get_port_msg(int32 code, size_t bufferSize) } +int32 +port_max_ports(void) +{ + return sMaxPorts; +} + + +int32 +port_used_ports(void) +{ + int32 count = 0; + int32 i; + + // ToDo: we should have a variable that counts the used ports for us + for (i = 0; i < sMaxPorts; i++) { + if (sPorts[i].id >= 0) + count++; + } + + return count; +} + + // #pragma mark - // public kernel API @@ -407,13 +430,13 @@ create_port(int32 queueLength, const char *name) GRAB_PORT_LIST_LOCK(); // find the first empty spot - for (i = 0; i < gMaxPorts; i++) { + for (i = 0; i < sMaxPorts; i++) { if (sPorts[i].id == -1) { // make the port_id be a multiple of the slot it's in - if (i >= sNextPort % gMaxPorts) - sNextPort += i - sNextPort % gMaxPorts; + if (i >= sNextPort % sMaxPorts) + sNextPort += i - sNextPort % sMaxPorts; else - sNextPort += gMaxPorts - (sNextPort % gMaxPorts - i); + sNextPort += sMaxPorts - (sNextPort % sMaxPorts - i); GRAB_PORT_LOCK(sPorts[i]); sPorts[i].id = sNextPort++; @@ -461,7 +484,7 @@ close_port(port_id id) if (!sPortsActive || id < 0) return B_BAD_PORT_ID; - slot = id % gMaxPorts; + slot = id % sMaxPorts; // walk through the sem list, trying to match name state = disable_interrupts(); @@ -497,7 +520,7 @@ delete_port(port_id id) if (!sPortsActive || id < 0) return B_BAD_PORT_ID; - slot = id % gMaxPorts; + slot = id % sMaxPorts; state = disable_interrupts(); GRAB_PORT_LOCK(sPorts[slot]); @@ -553,7 +576,7 @@ find_port(const char *name) // the port lock in question, not the port list lock // loop over list - for (i = 0; i < gMaxPorts && portFound < B_OK; i++) { + for (i = 0; i < sMaxPorts && portFound < B_OK; i++) { // lock every individual port before comparing state = disable_interrupts(); GRAB_PORT_LOCK(sPorts[i]); @@ -605,7 +628,7 @@ _get_port_info(port_id id, port_info *info, size_t size) if (!sPortsActive || id < 0) return B_BAD_PORT_ID; - slot = id % gMaxPorts; + slot = id % sMaxPorts; state = disable_interrupts(); GRAB_PORT_LOCK(sPorts[slot]); @@ -639,7 +662,7 @@ _get_next_port_info(team_id team, int32 *_cookie, struct port_info *info, size_t return B_BAD_PORT_ID; slot = *_cookie; - if (slot >= gMaxPorts) + if (slot >= sMaxPorts) return B_BAD_PORT_ID; if (team == B_CURRENT_TEAM) @@ -651,7 +674,7 @@ _get_next_port_info(team_id team, int32 *_cookie, struct port_info *info, size_t state = disable_interrupts(); GRAB_PORT_LIST_LOCK(); - while (slot < gMaxPorts) { + while (slot < sMaxPorts) { GRAB_PORT_LOCK(sPorts[slot]); if (sPorts[slot].id != -1 && sPorts[slot].capacity != 0 && sPorts[slot].owner == team) { // found one! @@ -695,7 +718,7 @@ port_buffer_size_etc(port_id id, uint32 flags, bigtime_t timeout) if (!sPortsActive || id < 0) return B_BAD_PORT_ID; - slot = id % gMaxPorts; + slot = id % sMaxPorts; state = disable_interrupts(); GRAB_PORT_LOCK(sPorts[slot]); @@ -761,7 +784,7 @@ port_count(port_id id) if (!sPortsActive || id < 0) return B_BAD_PORT_ID; - slot = id % gMaxPorts; + slot = id % sMaxPorts; state = disable_interrupts(); GRAB_PORT_LOCK(sPorts[slot]); @@ -814,7 +837,7 @@ read_port_etc(port_id id, int32 *_msgCode, void *msgBuffer, size_t bufferSize, return B_BAD_VALUE; flags = flags & (B_CAN_INTERRUPT | B_TIMEOUT); - slot = id % gMaxPorts; + slot = id % sMaxPorts; state = disable_interrupts(); GRAB_PORT_LOCK(sPorts[slot]); @@ -922,7 +945,7 @@ write_port_etc(port_id id, int32 msgCode, const void *msgBuffer, // mask irrelevant flags (for acquire_sem() usage) flags = flags & (B_CAN_INTERRUPT | B_TIMEOUT); - slot = id % gMaxPorts; + slot = id % sMaxPorts; if (bufferSize > PORT_MAX_MESSAGE_SIZE) return EINVAL; @@ -1020,7 +1043,7 @@ set_port_owner(port_id id, team_id team) if (!sPortsActive || id < 0) return B_BAD_PORT_ID; - slot = id % gMaxPorts; + slot = id % sMaxPorts; state = disable_interrupts(); GRAB_PORT_LOCK(sPorts[slot]); diff --git a/src/kernel/core/sem.c b/src/kernel/core/sem.c index b1a92fa2e2..da622e1c87 100644 --- a/src/kernel/core/sem.c +++ b/src/kernel/core/sem.c @@ -52,7 +52,7 @@ struct sem_entry { }; // Todo: Compute based on the amount of available memory. -#define MAX_SEMS 4096 +static int32 sMaxSems = 4096; static struct sem_entry *gSems = NULL; static region_id gSemRegion = 0; @@ -80,7 +80,7 @@ dump_sem_list(int argc, char **argv) { int i; - for (i = 0; i < MAX_SEMS; i++) { + for (i = 0; i < sMaxSems; i++) { if (gSems[i].id >= 0) dprintf("%p\tid: 0x%lx\t\tname: '%s'\n", &gSems[i], gSems[i].id, gSems[i].u.used.name); @@ -126,7 +126,7 @@ dump_sem_info(int argc, char **argv) dump_sem((struct sem_entry *)num); return 0; } else { - unsigned slot = num % MAX_SEMS; + unsigned slot = num % sMaxSems; if (gSems[slot].id != (int)num) { dprintf("sem 0x%lx doesn't exist!\n", num); return 0; @@ -137,7 +137,7 @@ dump_sem_info(int argc, char **argv) } // walk through the sem list, trying to match name - for (i = 0; i < MAX_SEMS; i++) { + for (i = 0; i < sMaxSems; i++) { if (gSems[i].u.used.name != NULL && strcmp(argv[1], gSems[i].u.used.name) == 0) { dump_sem(&gSems[i]); @@ -185,12 +185,12 @@ sem_init(kernel_args *ka) // create and initialize semaphore table gSemRegion = create_area("sem_table", (void **)&gSems, B_ANY_KERNEL_ADDRESS, - sizeof(struct sem_entry) * MAX_SEMS, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); + sizeof(struct sem_entry) * sMaxSems, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); if (gSemRegion < 0) panic("unable to allocate semaphore table!\n"); - memset(gSems, 0, sizeof(struct sem_entry) * MAX_SEMS); - for (i = 0; i < MAX_SEMS; i++) { + memset(gSems, 0, sizeof(struct sem_entry) * sMaxSems); + for (i = 0; i < sMaxSems; i++) { gSems[i].id = -1; free_sem_slot(i, i); } @@ -298,7 +298,7 @@ delete_sem_etc(sem_id id, status_t return_code, bool interrupted) if (id < 0) return B_BAD_SEM_ID; - slot = id % MAX_SEMS; + slot = id % sMaxSems; state = disable_interrupts(); GRAB_SEM_LOCK(gSems[slot]); @@ -331,7 +331,7 @@ delete_sem_etc(sem_id id, status_t return_code, bool interrupted) // append slot to the free list GRAB_SEM_LIST_LOCK(); - free_sem_slot(slot, id + MAX_SEMS); + free_sem_slot(slot, id + sMaxSems); RELEASE_SEM_LIST_LOCK(); if (released_threads > 0) { @@ -365,7 +365,7 @@ sem_timeout(timer *data) t = thread_get_thread_struct(args->blocked_thread); if (t == NULL) return B_HANDLED_INTERRUPT; - slot = args->blocked_sem_id % MAX_SEMS; + slot = args->blocked_sem_id % sMaxSems; state = disable_interrupts(); GRAB_SEM_LOCK(gSems[slot]); @@ -406,7 +406,7 @@ acquire_sem(sem_id id) status_t acquire_sem_etc(sem_id id, int32 count, uint32 flags, bigtime_t timeout) { - int slot = id % MAX_SEMS; + int slot = id % sMaxSems; int state; status_t status = B_OK; @@ -538,7 +538,7 @@ release_sem(sem_id id) status_t release_sem_etc(sem_id id, int32 count, uint32 flags) { - int slot = id % MAX_SEMS; + int slot = id % sMaxSems; int state; int released_threads = 0; struct thread_queue release_queue; @@ -630,7 +630,7 @@ get_sem_count(sem_id id, int32 *thread_count) if (thread_count == NULL) return EINVAL; - slot = id % MAX_SEMS; + slot = id % sMaxSems; state = disable_interrupts(); GRAB_SEM_LOCK(gSems[slot]); @@ -689,7 +689,7 @@ _get_sem_info(sem_id id, struct sem_info *info, size_t size) if (info == NULL || size != sizeof(sem_info)) return B_BAD_VALUE; - slot = id % MAX_SEMS; + slot = id % sMaxSems; state = disable_interrupts(); GRAB_SEM_LOCK(gSems[slot]); @@ -732,13 +732,13 @@ _get_next_sem_info(team_id team, int32 *_cookie, struct sem_info *info, size_t s return B_BAD_TEAM_ID; slot = *_cookie; - if (slot >= MAX_SEMS) + if (slot >= sMaxSems) return B_BAD_VALUE; state = disable_interrupts(); GRAB_SEM_LIST_LOCK(); - while (slot < MAX_SEMS) { + while (slot < sMaxSems) { if (gSems[slot].id != -1 && gSems[slot].u.used.owner == team) { GRAB_SEM_LOCK(gSems[slot]); if (gSems[slot].id != -1 && gSems[slot].u.used.owner == team) { @@ -778,7 +778,7 @@ set_sem_owner(sem_id id, team_id team) if (team < 0 || !team_is_valid(team)) return B_BAD_TEAM_ID; - slot = id % MAX_SEMS; + slot = id % sMaxSems; state = disable_interrupts(); GRAB_SEM_LOCK(gSems[slot]); @@ -822,7 +822,7 @@ sem_interrupt_thread(struct thread *t) if (!(t->sem_flags & B_CAN_INTERRUPT)) return B_NOT_ALLOWED; - slot = t->sem_blocking % MAX_SEMS; + slot = t->sem_blocking % sMaxSems; GRAB_SEM_LOCK(gSems[slot]); @@ -898,7 +898,7 @@ sem_delete_owned_sems(team_id owner) state = disable_interrupts(); GRAB_SEM_LIST_LOCK(); - for (i = 0; i < MAX_SEMS; i++) { + for (i = 0; i < sMaxSems; i++) { if (gSems[i].id != -1 && gSems[i].u.used.owner == owner) { sem_id id = gSems[i].id; @@ -920,6 +920,29 @@ sem_delete_owned_sems(team_id owner) } +int32 +sem_max_sems(void) +{ + return sMaxSems; +} + + +int32 +sem_used_sems(void) +{ + int32 count = 0; + int32 i; + + // ToDo: we should have a variable that counts the used sems for us + for (i = 0; i < sMaxSems; i++) { + if (gSems[i].id >= 0) + count++; + } + + return count; +} + + // #pragma mark - diff --git a/src/kernel/core/syscalls.c b/src/kernel/core/syscalls.c index b7e622c979..0e2f3e6e97 100644 --- a/src/kernel/core/syscalls.c +++ b/src/kernel/core/syscalls.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -451,7 +452,9 @@ syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_ret) case SYSCALL_SET_ALARM: *call_ret = user_set_alarm((bigtime_t)INT32TOINT64(arg0, arg1), (uint32)arg2); break; - + case SYSCALL_GET_SYSTEM_INFO: + *call_ret = _user_get_system_info((system_info *)arg0, (size_t)arg1); + break; // 32 bit atomic functions #ifdef ATOMIC_FUNCS_ARE_SYSCALLS case SYSCALL_ATOMIC_SET: diff --git a/src/kernel/core/system_info.c b/src/kernel/core/system_info.c new file mode 100644 index 0000000000..efd15da5a5 --- /dev/null +++ b/src/kernel/core/system_info.c @@ -0,0 +1,85 @@ +/* +** Copyright 2004, Stefano Ceccherini. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + +const static int64 kKernelVersion = 0x1; +const static char kKernelName[] = "kernel_" OBOS_ARCH; + + +status_t +_get_system_info(system_info *info, size_t size) +{ + if (size != sizeof(system_info)) + return B_BAD_VALUE; + + memset(info, 0, sizeof(system_info)); + // TODO: Add: + // - max_pages + // - used_pages + // - page_faults + // - max_threads + // - used_threads + // - max_teams + // - used_teams + + info->boot_time = rtc_boot_time(); + info->cpu_count = smp_get_num_cpus(); + info->used_ports = port_used_ports(); + info->max_ports = port_max_ports(); + info->used_sems = sem_used_sems(); + info->max_sems = sem_max_sems(); + + info->kernel_version = kKernelVersion; + strlcpy(info->kernel_name, kKernelName, B_FILE_NAME_LENGTH); + strlcpy(info->kernel_build_date, __DATE__, B_OS_NAME_LENGTH); + strlcpy(info->kernel_build_time, __TIME__, B_OS_NAME_LENGTH); + + // TODO: Add arch specific stuff (arch_get_system_info() ?) + // - cpu_type + // - cpu_revision + // - various cpu_info + // - cpu_clock_speed + // - bus_clock_speed + // - platform_type + + return B_OK; +} + + +status_t +_user_get_system_info(system_info *userInfo, size_t size) +{ + system_info info; + status_t status; + + // The BeBook says get_system_info() always returns B_OK, + // but that ain't true with invalid addresses + if (userInfo == NULL || !IS_USER_ADDRESS(userInfo)) + return B_BAD_ADDRESS; + + status = _get_system_info(&info, size); + if (status == B_OK) { + if (user_memcpy(userInfo, &info, sizeof(system_info)) < B_OK) + return B_BAD_ADDRESS; + + return B_OK; + } + + return status; +}