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
This commit is contained in:
Axel Dörfler 2004-04-21 22:57:39 +00:00
parent f6a31876ce
commit 9fac193453
5 changed files with 208 additions and 64 deletions

View File

@ -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
;

View File

@ -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]);

View File

@ -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 -

View File

@ -26,6 +26,7 @@
#include <kimage.h>
#include <ksignal.h>
#include <real_time_clock.h>
#include <system_info.h>
#include <sys/ioccom.h>
#include <sys/socket.h>
#include <user_atomic.h>
@ -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:

View File

@ -0,0 +1,85 @@
/*
** Copyright 2004, Stefano Ceccherini. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#include <OS.h>
#include <KernelExport.h>
#include <system_info.h>
#include <vm.h>
#include <debug.h>
#include <port.h>
#include <real_time_clock.h>
#include <sem.h>
#include <smp.h>
#include <string.h>
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;
}