Nucleus
Barry Object locking e8e484f (3 years, 3 months ago)
/*
* This file implements the Task Queue object and contains all the functions for
* dealing with them. A Task Queue holds a reference to every Task it contains.
* There is a single reference per task for the entire queue, and tasks do not
* hold references to their neighbour, nor the queue its end.
*/
#include <nucleus/object.h>
#include <nucleus/task.h>
static void *task_queue_new(void);
static void task_queue_delete(Object *);
/* Task Queue object type */
ObjectType taskQueueType = {
.new = task_queue_new,
.delete = task_queue_delete,
};
/* Create a new Task Queue */
static void *
task_queue_new(void)
{
TaskQueue *queue = kmalloc(sizeof(TaskQueue));
}
/* Destroy a Task Queue */
static void
task_queue_delete(Object *obj)
{
TaskQueue *queue = (void *) obj;
while (queue->start)
put(pop_from_queue(queue));
kfree(queue);
}
/* Add a Task to a Task Queue */
void
add_to_queue(TaskQueue *queue, Task *task)
{
lock(queue);
if (!queue->start)
queue->start = get(task);
else
queue->end->next = get(task);
queue->end = task;
task->next = NULL;
unlock(queue);
}
/* Remove a Task from a Task Queue */
void
remove_from_queue(TaskQueue *queue, Task *task)
{
lock(queue);
/* Start of queue */
if (queue->start == task) {
queue->start = task->next;
goto found;
}
/* Search */
Task *prev;
for (prev = queue->start; prev->next; prev = prev->next)
if (prev->next == task)
break;
if (!prev->next) {
unlock(queue);
return;
}
prev->next = task->next;
found:
if (queue->end == task)
queue->end = NULL;
task->next = NULL;
put(task);
unlock(queue);
}
/* Remove the first Task from a Task Queue */
Task *
pop_from_queue(TaskQueue *queue)
{
lock(queue);
Task *head = get(queue->start);
remove_from_queue(queue, queue->start);
unlock(queue);
return head;
}