Renamed the public api to underline the DPC *queue* mechanism handled.

Pending DPCs at queue death time are now called too, to avoid possible leaks.
Meanwhile, queue_dpc() will refuse to add another DPC and returns B_CANCELLED.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19798 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2007-01-14 21:58:19 +00:00
parent 6709571e18
commit af1c1a0a03
2 changed files with 42 additions and 20 deletions
+3 -3
View File
@@ -18,9 +18,9 @@ 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 queue_size); void * (*new_dpc_queue)(const char *name, long priority, int queue_size);
status_t (*delete_dpc_thread)(void *thread); status_t (*delete_dpc_queue)(void *queue);
status_t (*queue_dpc)(void *thread, dpc_func dpc_name, void *arg); status_t (*queue_dpc)(void *queue, dpc_func dpc_name, void *arg);
} dpc_module_info; } dpc_module_info;
+39 -17
View File
@@ -40,34 +40,42 @@ static int32
dpc_thread(void *arg) dpc_thread(void *arg)
{ {
dpc_queue *queue = arg; dpc_queue *queue = arg;
dpc_slot dpc;
// Let's wait forever/until semaphore death for new DPC slot 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;
dpc_slot call;
// grab the next dpc slot // grab the next dpc slot
former = disable_interrupts(); former = disable_interrupts();
acquire_spinlock(&queue->lock); acquire_spinlock(&queue->lock);
call = queue->slots[queue->head]; dpc = queue->slots[queue->head];
queue->head = (queue->head++) % queue->size; queue->head = (queue->head++) % queue->size;
queue->count--; queue->count--;
release_spinlock(&queue->lock); release_spinlock(&queue->lock);
restore_interrupts(former); restore_interrupts(former);
call.function(call.arg); dpc.function(dpc.arg);
} }
// Let's die quietly, ignored by all... sigh. // Let's finish the pending DPCs, if any.
// Otherwise, resource could leaks...
while (queue->count--) {
dpc = queue->slots[queue->head];
queue->head = (queue->head++) % queue->size;
dpc.function(dpc.arg);
}
// Now, let's die quietly, ignored by all... sigh.
return 0; return 0;
} }
// ---- Public API // ---- Public API
static void * static void *
new_dpc_thread(const char *name, long priority, int queue_size) new_dpc_queue(const char *name, long priority, int queue_size)
{ {
char str[64]; char str[64];
dpc_queue *queue; dpc_queue *queue;
@@ -111,17 +119,29 @@ new_dpc_thread(const char *name, long priority, int queue_size)
static status_t static status_t
delete_dpc_thread(void *thread) delete_dpc_queue(void *handle)
{ {
dpc_queue *queue = thread; dpc_queue *queue = handle;
thread_id thread;
status_t exit_value; status_t exit_value;
cpu_status former;
if (!queue) if (!queue)
return B_BAD_VALUE; return B_BAD_VALUE;
// Wakeup the thread by murdering its favorite semaphore // Close the queue: queue_dpc() should knows we're closing:
former = disable_interrupts();
acquire_spinlock(&queue->lock);
thread = queue->thread;
queue->thread = -1;
release_spinlock(&queue->lock);
restore_interrupts(former);
// 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(thread, &exit_value);
free(queue); free(queue);
@@ -130,20 +150,23 @@ delete_dpc_thread(void *thread)
static status_t static status_t
queue_dpc(void *thread, dpc_func function, void *arg) queue_dpc(void *handle, dpc_func function, void *arg)
{ {
dpc_queue *queue = thread; dpc_queue *queue = handle;
cpu_status former; cpu_status former;
status_t status = B_OK; status_t status = B_OK;
if (!queue || !function) if (!queue || !function)
return B_BAD_VALUE; return B_BAD_VALUE;
// Try to be safe being 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);
if (queue->count == queue->size) if (queue->thread < 0) {
// Queue thread is dying...
status = B_CANCELED;
} else if (queue->count == queue->size)
// This DPC queue is full, sorry // This DPC queue is full, sorry
status = B_NO_MEMORY; status = B_NO_MEMORY;
else { else {
@@ -166,7 +189,6 @@ queue_dpc(void *thread, dpc_func function, void *arg)
} }
static status_t static status_t
std_ops(int32 op, ...) std_ops(int32 op, ...)
{ {
@@ -188,8 +210,8 @@ static dpc_module_info sDPCModule = {
std_ops std_ops
}, },
new_dpc_thread, new_dpc_queue,
delete_dpc_thread, delete_dpc_queue,
queue_dpc queue_dpc
}; };