Late cleanup a bit before actually going to bed. Good night world.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19762 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2007-01-10 01:26:49 +00:00
parent 7d2635cbc0
commit daf593cf9c
+21 -18
View File
@@ -8,32 +8,34 @@
*/ */
#include <KernelExport.h> #include <KernelExport.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <module.h> #include <module.h>
// #include <dpc.h> // #include <dpc.h>
// ----
// To be moved into a new headers/os/drivers/dpc.h:
#define DPC_MODULE_NAME "generic/dpc/v1" #define DPC_MODULE_NAME "generic/dpc/v1"
typedef void (*dpc_func) (void *arg); typedef void (*dpc_func) (void *arg);
typedef struct { typedef struct {
module_info info; module_info info;
void * (*new_dpc_thread)(const char *name, long priority, int max_dpc); void * (*new_dpc_thread)(const char *name, long priority, int queue_size);
status_t (*delete_dpc_thread)(void *thread); status_t (*delete_dpc_thread)(void *thread);
status_t (*queue_dpc)(void *thread, dpc_func dpc_name, void *arg); status_t (*queue_dpc)(void *thread, dpc_func dpc_name, void *arg);
} dpc_module_info; } dpc_module_info;
// ---- // ----
// Private DPC queue structures
typedef struct { typedef struct {
dpc_func function; dpc_func function;
void *arg; void *arg;
} dpc_slot; } dpc_slot;
typedef struct { typedef struct {
thread_id thread; thread_id thread;
sem_id wakeup_sem; sem_id wakeup_sem;
@@ -45,6 +47,7 @@ typedef struct {
// size * slots follow // size * slots follow
} dpc_queue; } dpc_queue;
static int32 static int32
dpc_thread(void *arg) dpc_thread(void *arg)
{ {
@@ -53,10 +56,9 @@ dpc_thread(void *arg)
if (!queue) if (!queue)
return -1; return -1;
// Let's wait forever/until sem death for DPC to show up // Let's wait forever/until semaphore death for new DPC slot to show up
while (acquire_sem(queue->wakeup_sem) == B_OK) { while (acquire_sem(queue->wakeup_sem) == B_OK) {
cpu_status former; cpu_status former;
int i;
dpc_slot call; dpc_slot call;
// grab the next dpc slot // grab the next dpc slot
@@ -73,11 +75,11 @@ dpc_thread(void *arg)
call.function(call.arg); call.function(call.arg);
} }
// Let's die quietly, ignored by all... // Let's die quietly, ignored by all... sigh.
return 0; return 0;
} }
// ---- // ---- Public API
static void * static void *
new_dpc_thread(const char *name, long priority, int queue_size) new_dpc_thread(const char *name, long priority, int queue_size)
@@ -91,7 +93,7 @@ new_dpc_thread(const char *name, long priority, int queue_size)
queue->head = queue->tail = 0; queue->head = queue->tail = 0;
queue->size = queue_size; queue->size = queue_size;
queue->lock = 0; queue->lock = 0; // Init the spinlock
strncpy(str, name, sizeof(str)); strncpy(str, name, sizeof(str));
strncat(str, "_wakeup_sem", sizeof(str)); strncat(str, "_wakeup_sem", sizeof(str));
@@ -103,8 +105,8 @@ new_dpc_thread(const char *name, long priority, int queue_size)
} }
set_sem_owner(queue->wakeup_sem, B_SYSTEM_TEAM); set_sem_owner(queue->wakeup_sem, B_SYSTEM_TEAM);
// Fire a kernel thread to do actually do // Fire a kernel thread to actually handle (aka call them!)
// the deferred procedure calls // the queued/deferred procedure calls
queue->thread = spawn_kernel_thread(dpc_thread, name, priority, queue); queue->thread = spawn_kernel_thread(dpc_thread, name, priority, queue);
if (queue->thread < 0) { if (queue->thread < 0) {
delete_sem(queue->wakeup_sem); delete_sem(queue->wakeup_sem);
@@ -129,6 +131,7 @@ delete_dpc_thread(void *thread)
// Wakeup the thread by murdering its favorite semaphore // Wakeup the thread by murdering its favorite semaphore
delete_sem(queue->wakeup_sem); delete_sem(queue->wakeup_sem);
wait_for_thread(queue->thread, &exit_value); wait_for_thread(queue->thread, &exit_value);
free(queue); free(queue);
return B_OK; return B_OK;
@@ -144,20 +147,20 @@ queue_dpc(void *thread, dpc_func function, void *arg)
if (!queue) if (!queue)
return B_BAD_VALUE; return B_BAD_VALUE;
// Take measure to be safe to be called from interrupt handlers: // Try to be safe being called from interrupt handlers:
former = disable_interrupts(); former = disable_interrupts();
acquire_spinlock(&queue->lock); acquire_spinlock(&queue->lock);
queue->slots[queue->tail].function = function; queue->slots[queue->tail].function = function;
queue->slots[queue->tail].arg = arg; queue->slots[queue->tail].arg = arg;
queue->tail = (queue->tail++) % queue->size; queue->tail = (queue->tail++) % queue->size;
release_spinlock(&queue->lock); release_spinlock(&queue->lock);
restore_interrupts(former); restore_interrupts(former);
// wake up the corresponding dpc thead // Wake up the corresponding dpc thead
// Notice that the interrupt handler should returns B_INVOKE_SCHEDULER for // Notice that interrupt handlers should returns B_INVOKE_SCHEDULER to
// shortest DPC latency... // shorten DPC latency as much as possible...
return release_sem_etc(queue->wakeup_sem, 1, B_DO_NOT_RESCHEDULE); return release_sem_etc(queue->wakeup_sem, 1, B_DO_NOT_RESCHEDULE);
} }