From 037f70947f14b7e7d452543ad645f38d7c96f6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 9 Apr 2008 14:21:06 +0000 Subject: [PATCH] * Cleaned up KernelExport.h completely, removed deprecated and non implemented API, uses the _PRINTFLIKE macro where appropriate. * Got rid of the "qent" structure, struct timer now contains everything we need. This makes the affected code in sem.cpp, signal.cpp, and timer.c much cleaner, and resolves a few TODOs. * Minor cleanup in vfs.cpp. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24871 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/drivers/KernelExport.h | 198 ++++++++++-------------------- src/system/kernel/fs/vfs.cpp | 12 +- src/system/kernel/sem.cpp | 12 +- src/system/kernel/signal.cpp | 2 +- src/system/kernel/timer.c | 91 +++++++------- 5 files changed, 126 insertions(+), 189 deletions(-) diff --git a/headers/os/drivers/KernelExport.h b/headers/os/drivers/KernelExport.h index 133a8e993a..921301c3be 100644 --- a/headers/os/drivers/KernelExport.h +++ b/headers/os/drivers/KernelExport.h @@ -1,6 +1,5 @@ -/* Kernel only exports for kernel add-ons - * - * Copyright 2005, Haiku Inc. All Rights Reserved. +/* + * Copyright 2005-2008, Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _KERNEL_EXPORT_H @@ -11,31 +10,11 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - -/*-------------------------------------------------------------*/ /* interrupts and spinlocks */ -/* disable/restore interrupts on the current CPU */ - typedef ulong cpu_status; - -extern cpu_status disable_interrupts(void); -extern void restore_interrupts(cpu_status status); - - -/* spinlocks. Note that acquire/release should be called with - * interrupts disabled. - */ - typedef vint32 spinlock; -extern void acquire_spinlock(spinlock *lock); -extern void release_spinlock(spinlock *lock); - - /* interrupt handling support for device drivers */ typedef int32 (*interrupt_handler)(void *data); @@ -49,36 +28,16 @@ typedef int32 (*interrupt_handler)(void *data); #define B_NO_ENABLE_COUNTER 1 #define B_NO_LOCK_VECTOR 2 -extern status_t install_io_interrupt_handler(long interrupt_number, - interrupt_handler handler, void *data, ulong flags); -extern status_t remove_io_interrupt_handler(long interrupt_number, - interrupt_handler handler, void *data); - -/*-------------------------------------------------------------*/ /* timer interrupts services */ -/* The BeOS qent structure is probably part of a general double linked list - * interface used all over the kernel; a struct is required to have a qent - * entry struct as first element, so it can be linked to other elements - * easily. The key field is probably just an id, eventually used to order - * the list. - * Since we don't use this kind of interface, but we have to provide it - * to keep compatibility, we can use the qent struct for other purposes... - * - * ToDo: don't do this! Drop source compatibility, but don't overdefine those values! - */ -typedef struct qent { - int64 key; /* We use this as the sched time */ - struct qent *next; /* This is used as a pointer to next timer */ - struct qent *prev; /* This can be used for callback args */ -} qent; - typedef struct timer timer; typedef int32 (*timer_hook)(timer *); struct timer { - qent entry; + struct timer *next; + int64 schedule_time; + void *user_data; uint16 flags; uint16 cpu; timer_hook hook; @@ -89,24 +48,7 @@ struct timer { #define B_ONE_SHOT_RELATIVE_TIMER 2 #define B_PERIODIC_TIMER 3 -extern status_t add_timer(timer *t, timer_hook hook, bigtime_t period, int32 flags); -extern bool cancel_timer(timer *t); - -/*-------------------------------------------------------------*/ -/* kernel threads */ - -extern thread_id spawn_kernel_thread(thread_func function, const char *threadName, - int32 priority, void *arg); - - -/*-------------------------------------------------------------*/ -/* signal functions */ - -extern int send_signal_etc(pid_t thread, uint sig, uint32 flags); - - -/*-------------------------------------------------------------*/ /* virtual memory buffer functions */ #define B_DMA_IO 0x00000001 @@ -117,11 +59,6 @@ typedef struct { ulong size; /* size of block */ } physical_entry; -extern long lock_memory(void *buffer, ulong numBytes, ulong flags); -extern long unlock_memory(void *buffer, ulong numBytes, ulong flags); -extern long get_memory_map(const void *buffer, ulong size, - physical_entry *table, long numEntries); - /* address specifications for mapping physical memory */ #define B_ANY_KERNEL_BLOCK_ADDRESS (B_ANY_KERNEL_ADDRESS + 1) @@ -130,14 +67,8 @@ extern long get_memory_map(const void *buffer, ulong size, #define B_KERNEL_WRITE_AREA 32 #define B_USER_CLONEABLE_AREA 256 -/* call to map physical memory - typically used for memory-mapped i/o */ - -extern area_id map_physical_memory(const char *areaName, void *physicalAddress, - size_t size, uint32 flags, uint32 protection, void **mappedAddress); - - /* MTR attributes for mapping physical memory (Intel Architecture only) */ -// ToDo: what have those to do here? +// TODO: rename those to something more meaningful #define B_MTR_UC 0x10000000 #define B_MTR_WC 0x20000000 #define B_MTR_WT 0x30000000 @@ -146,52 +77,12 @@ extern area_id map_physical_memory(const char *areaName, void *physicalAddress, #define B_MTR_MASK 0xf0000000 -/*-------------------------------------------------------------*/ -/* hardware inquiry */ +/* kernel daemon service */ -/* platform_type return value is defined in OS.h */ +typedef void (*daemon_hook)(void *arg, int iteration); -extern platform_type platform(); -#if __POWERPC__ -extern long motherboard_version(void); -extern long io_card_version(void); -#endif - -/*-------------------------------------------------------------*/ -/* primitive kernel debugging facilities */ - -/* Standard debug output is on... - * mac: modem port - * pc: com1 - * ...at 19.2 kbaud, no parity, 8 bit, 1 stop bit. - * - * Note: the kernel settings file can override these defaults - */ - -#if __GNUC__ -extern void dprintf(const char *format, ...) /* just like printf */ - __attribute__ ((format (__printf__, 1, 2))); -extern void kprintf(const char *fmt, ...) /* only for debugger cmds */ - __attribute__ ((format (__printf__, 1, 2))); -#else -extern void dprintf(const char *format, ...); /* just like printf */ -extern void kprintf(const char *fmt, ...); /* only for debugger cmds */ -#endif - -extern void dump_block(const char *buffer, int size, const char *prefix); - /* hexdumps given buffer */ - -extern bool set_dprintf_enabled(bool new_state); /* returns old state */ - -#if __GNUC__ -extern void panic(const char *format, ...) __attribute__ ((format (__printf__, 1, 2))); -#else -extern void panic(const char *format, ...); -#endif - -extern void kernel_debugger(const char *message); /* enter kernel debugger */ -extern uint64 parse_expression(const char *string); /* utility for debugger cmds */ +/* kernel debugging facilities */ /* special return codes for kernel debugger */ #define B_KDEBUG_CONT 2 @@ -199,25 +90,70 @@ extern uint64 parse_expression(const char *string); /* utility for debugger cmd typedef int (*debugger_command_hook)(int argc, char **argv); + +#ifdef __cplusplus +extern "C" { +#endif + +/* interrupts, spinlock, and timers */ +extern cpu_status disable_interrupts(void); +extern void restore_interrupts(cpu_status status); + +extern void acquire_spinlock(spinlock *lock); +extern void release_spinlock(spinlock *lock); + +extern status_t install_io_interrupt_handler(long interrupt_number, + interrupt_handler handler, void *data, ulong flags); +extern status_t remove_io_interrupt_handler(long interrupt_number, + interrupt_handler handler, void *data); + +extern status_t add_timer(timer *t, timer_hook hook, bigtime_t period, + int32 flags); +extern bool cancel_timer(timer *t); + +/* kernel threads */ +extern thread_id spawn_kernel_thread(thread_func function, + const char *name, int32 priority, void *arg); + +/* signal functions */ +extern int send_signal_etc(pid_t thread, uint signal, uint32 flags); + +/* virtual memory */ +extern long lock_memory(void *buffer, ulong numBytes, ulong flags); +extern long unlock_memory(void *buffer, ulong numBytes, ulong flags); +extern long get_memory_map(const void *buffer, ulong size, + physical_entry *table, long numEntries); +extern area_id map_physical_memory(const char *areaName, + void *physicalAddress, size_t size, uint32 flags, + uint32 protection, void **_mappedAddress); + +/* kernel debugging facilities */ +extern void dprintf(const char *format, ...) _PRINTFLIKE(1, 2); +extern void kprintf(const char *fmt, ...) _PRINTFLIKE(1, 2); + +extern void dump_block(const char *buffer, int size, const char *prefix); + /* TODO: temporary API: hexdumps given buffer */ + +extern bool set_dprintf_enabled(bool new_state); + +extern void panic(const char *format, ...) _PRINTFLIKE(1, 2); + +extern void kernel_debugger(const char *message); +extern uint64 parse_expression(const char *string); + extern int add_debugger_command(char *name, debugger_command_hook hook, char *help); -extern int remove_debugger_command(char *name, debugger_command_hook hook); - -extern status_t load_driver_symbols(const char *driverName); - - -/*-------------------------------------------------------------*/ -/* misc */ +extern int remove_debugger_command(char *name, + debugger_command_hook hook); +/* Miscellaneous */ extern void spin(bigtime_t microseconds); - /* does a busy delay loop for at least "microseconds" */ -typedef void (*daemon_hook)(void *arg, int iteration); - -extern status_t register_kernel_daemon(daemon_hook hook, void *arg, int frequency); +extern status_t register_kernel_daemon(daemon_hook hook, void *arg, + int frequency); extern status_t unregister_kernel_daemon(daemon_hook hook, void *arg); -extern void call_all_cpus(void (*f)(void *, int), void *cookie); -extern void call_all_cpus_sync(void (*f)(void *, int), void *cookie); +extern void call_all_cpus(void (*func)(void *, int), void *cookie); +extern void call_all_cpus_sync(void (*func)(void *, int), void *cookie); /* safe methods to access user memory without having to lock it */ extern status_t user_memcpy(void *to, const void *from, size_t size); diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 9df82123aa..5e264e3fea 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -5370,16 +5370,16 @@ common_rename(int fd, char *path, int newFD, char *newPath, bool kernel) FUNCTION(("common_rename(fd = %d, path = %s, newFD = %d, newPath = %s, kernel = %d)\n", fd, path, newFD, newPath, kernel)); status = fd_and_path_to_dir_vnode(fd, path, &fromVnode, fromName, kernel); - if (status < 0) + if (status < B_OK) return status; status = fd_and_path_to_dir_vnode(newFD, newPath, &toVnode, toName, kernel); - if (status < 0) - goto err; + if (status < B_OK) + goto err1; if (fromVnode->device != toVnode->device) { status = B_CROSS_DEVICE_LINK; - goto err1; + goto err2; } if (HAS_FS_CALL(fromVnode, rename)) @@ -5387,9 +5387,9 @@ common_rename(int fd, char *path, int newFD, char *newPath, bool kernel) else status = EROFS; -err1: +err2: put_vnode(toVnode); -err: +err1: put_vnode(fromVnode); return status; diff --git a/src/system/kernel/sem.cpp b/src/system/kernel/sem.cpp index 234b099269..c21da57d9f 100644 --- a/src/system/kernel/sem.cpp +++ b/src/system/kernel/sem.cpp @@ -285,7 +285,7 @@ notify_sem_select_events(struct sem_entry* sem, uint16 events) static int32 sem_timeout(timer *data) { - struct sem_timeout_args *args = (struct sem_timeout_args *)data->entry.prev; + struct sem_timeout_args *args = (struct sem_timeout_args *)data->user_data; struct thread *thread; int slot; int state; @@ -879,7 +879,8 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, if ((sSems[slot].u.used.count -= count) < 0) { // we need to block struct thread *thread = thread_get_current_thread(); - timer timeout_timer; // stick it on the stack, since we may be blocking here + timer timeoutTimer; + // stick it on the stack, since we may be blocking here struct sem_timeout_args args; TRACE(("switch_sem_etc(id = %ld): block name = %s, thread = %p," @@ -917,9 +918,8 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, args.blocked_thread = thread->id; args.sem_count = count; - // ToDo: another evil hack: pass the args into timer->entry.prev - timeout_timer.entry.prev = (qent *)&args; - add_timer(&timeout_timer, &sem_timeout, timeout, + timeoutTimer.user_data = &args; + add_timer(&timeoutTimer, &sem_timeout, timeout, flags & B_RELATIVE_TIMEOUT ? B_ONE_SHOT_RELATIVE_TIMER : B_ONE_SHOT_ABSOLUTE_TIMER); } @@ -964,7 +964,7 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, if (thread->sem.acquire_status != B_TIMED_OUT) { // cancel the timer event, the sem may have been deleted or interrupted // with the timer still active - cancel_timer(&timeout_timer); + cancel_timer(&timeoutTimer); } } diff --git a/src/system/kernel/signal.cpp b/src/system/kernel/signal.cpp index eb2766e213..1e739adc86 100644 --- a/src/system/kernel/signal.cpp +++ b/src/system/kernel/signal.cpp @@ -785,7 +785,7 @@ set_alarm(bigtime_t time, uint32 mode) TRACE(("set_alarm: thread = %p\n", thread)); if (thread->alarm.period) - remainingTime = (bigtime_t)thread->alarm.entry.key - system_time(); + remainingTime = (bigtime_t)thread->alarm.schedule_time - system_time(); cancel_timer(&thread->alarm); diff --git a/src/system/kernel/timer.c b/src/system/kernel/timer.c index 099ebd09a7..7d5e9a2239 100644 --- a/src/system/kernel/timer.c +++ b/src/system/kernel/timer.c @@ -1,12 +1,12 @@ -/* Policy info for timers */ - /* -** Copyright 2002-2004, The OpenBeOS Team. All rights reserved. -** Distributed under the terms of the OpenBeOS License. -** -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ + * Copyright 2002-2008, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + +/*! Policy info for timers */ #include @@ -44,8 +44,7 @@ timer_init(kernel_args *args) } -/** NOTE: expects interrupts to be off */ - +/*! NOTE: expects interrupts to be off */ static void add_event_to_list(timer *event, timer * volatile *list) { @@ -53,16 +52,16 @@ add_event_to_list(timer *event, timer * volatile *list) timer *last = NULL; // stick it in the event list - for (next = *list; next; last = next, next = (timer *)next->entry.next) { - if ((bigtime_t)next->entry.key >= (bigtime_t)event->entry.key) + for (next = *list; next; last = next, next = (timer *)next->next) { + if ((bigtime_t)next->schedule_time >= (bigtime_t)event->schedule_time) break; } if (last != NULL) { - event->entry.next = last->entry.next; - last->entry.next = (qent*)event; + event->next = last->next; + last->next = event; } else { - event->entry.next = (qent*)next; + event->next = next; *list = event; } } @@ -76,7 +75,8 @@ timer_interrupt() int currentCPU = smp_get_current_cpu(); int32 rc = B_HANDLED_INTERRUPT; - TRACE(("timer_interrupt: time 0x%x 0x%x, cpu %d\n", system_time(), smp_get_current_cpu())); + TRACE(("timer_interrupt: time 0x%x 0x%x, cpu %d\n", system_time(), + smp_get_current_cpu())); spinlock = &sTimerSpinlock[currentCPU]; @@ -84,25 +84,23 @@ timer_interrupt() restart_scan: event = sEvents[currentCPU]; - if (event != NULL && ((bigtime_t)event->entry.key < system_time())) { + if (event != NULL && ((bigtime_t)event->schedule_time < system_time())) { // this event needs to happen int mode = event->flags; - sEvents[currentCPU] = (timer *)event->entry.next; - event->entry.key = 0; + sEvents[currentCPU] = (timer *)event->next; + event->schedule_time = 0; release_spinlock(spinlock); - TRACE(("timer_interrupt: calling hook %p for event %p\n", event->hook, event)); + TRACE(("timer_interrupt: calling hook %p for event %p\n", event->hook, + event)); // call the callback // note: if the event is not periodic, it is ok // to delete the event structure inside the callback - if (event->hook) { + if (event->hook) rc = event->hook(event); -// if (event->func(event->data) == INT_RESCHEDULE) -// rc = INT_RESCHEDULE; - } acquire_spinlock(spinlock); @@ -114,7 +112,7 @@ restart_scan: // it to one, since zero represents not scheduled scheduleTime = 1; } - event->entry.key = (int64)scheduleTime; + event->schedule_time = (int64)scheduleTime; add_event_to_list(event, &sEvents[currentCPU]); } @@ -122,8 +120,10 @@ restart_scan: } // setup the next hardware timer - if (sEvents[currentCPU] != NULL) - arch_timer_set_hardware_timer((bigtime_t)sEvents[currentCPU]->entry.key - system_time()); + if (sEvents[currentCPU] != NULL) { + arch_timer_set_hardware_timer( + (bigtime_t)sEvents[currentCPU]->schedule_time - system_time()); + } release_spinlock(spinlock); @@ -150,7 +150,7 @@ add_timer(timer *event, timer_hook hook, bigtime_t period, int32 flags) if (scheduleTime == 0) scheduleTime = 1; - event->entry.key = (int64)scheduleTime; + event->schedule_time = (int64)scheduleTime; event->period = period; event->hook = hook; event->flags = flags; @@ -173,11 +173,9 @@ add_timer(timer *event, timer_hook hook, bigtime_t period, int32 flags) } -/** This is a fast path to be called from reschedule() and from - * cancel_timer(). - * Must always be invoked with interrupts disabled. - */ - +/*! This is a fast path to be called from reschedule() and from cancel_timer(). + Must always be invoked with interrupts disabled. +*/ status_t _local_timer_cancel_event(int cpu, timer *event) { @@ -190,21 +188,23 @@ _local_timer_cancel_event(int cpu, timer *event) if (current == event) { // we found it if (current == sEvents[cpu]) - sEvents[cpu] = (timer *)current->entry.next; + sEvents[cpu] = current->next; else - last->entry.next = current->entry.next; - current->entry.next = NULL; + last->next = current->next; + current->next = NULL; // break out of the whole thing break; } last = current; - current = (timer *)current->entry.next; + current = current->next; } if (sEvents[cpu] == NULL) arch_timer_clear_hardware_timer(); - else - arch_timer_set_hardware_timer((bigtime_t)sEvents[cpu]->entry.key - system_time()); + else { + arch_timer_set_hardware_timer( + (bigtime_t)sEvents[cpu]->schedule_time - system_time()); + } release_spinlock(&sTimerSpinlock[cpu]); @@ -244,19 +244,19 @@ cancel_timer(timer *event) if (current == event) { // we found it if (current == sEvents[cpu]) - sEvents[cpu] = (timer *)current->entry.next; + sEvents[cpu] = current->next; else - last->entry.next = current->entry.next; - current->entry.next = NULL; + last->next = current->next; + current->next = NULL; // break out of the whole thing release_spinlock(&sTimerSpinlock[cpu]); restore_interrupts(state); - return (bigtime_t)event->entry.key < system_time(); + return (bigtime_t)event->schedule_time < system_time(); } last = current; - current = (timer *)current->entry.next; + current = current->next; } release_spinlock(&sTimerSpinlock[cpu]); } @@ -272,6 +272,7 @@ spin(bigtime_t microseconds) { bigtime_t time = system_time(); - while((system_time() - time) < microseconds) + while ((system_time() - time) < microseconds) { PAUSE(); + } }