From ba491114bceab1f578cbdf336cb294a108430251 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 26 Nov 2013 09:17:14 +0100 Subject: [PATCH] add basic functions to block and to unblock a task --- include/eduos/tasks.h | 20 +++++++++++ kernel/tasks.c | 83 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/include/eduos/tasks.h b/include/eduos/tasks.h index 05e89e2..11515c1 100644 --- a/include/eduos/tasks.h +++ b/include/eduos/tasks.h @@ -74,6 +74,26 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* args, uint8_t prio); */ void reschedule(void); +/** @brief Wake up a blocked task + * + * The task's status will be changed to TASK_READY + * + * @return + * - 0 on success + * - -EINVAL (-22) on failure + */ +int wakeup_task(tid_t); + +/** @brief Block current task + * + * The current task's status will be changed to TASK_BLOCKED + * + * @return + * - 0 on success + * - -EINVAL (-22) on failure + */ +int block_current_task(void); + /** @brief This function shall be called by leaving kernel level tasks */ void NORETURN leave_kernel_task(void); diff --git a/kernel/tasks.c b/kernel/tasks.c index 220a495..17a6abf 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -184,6 +184,89 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* args, uint8_t prio) return create_task(id, ep, args, prio); } +/** @brief Wakeup a blocked task + * @param id The task's tid_t structure + * @return + * - 0 on success + * - -EINVAL (-22) on failure + */ +int wakeup_task(tid_t id) +{ + task_t* task; + uint32_t prio; + int ret = -EINVAL; + + task = task_table + id; + prio = task->prio; + + if (task->status == TASK_BLOCKED) { + task->status = TASK_READY; + ret = 0; + + // increase the number of ready tasks + readyqueues.nr_tasks++; + + // add task to the runqueue + if (!readyqueues.queue[prio-1].last) { + readyqueues.queue[prio-1].last = readyqueues.queue[prio-1].first = task; + task->next = task->prev = NULL; + readyqueues.prio_bitmap |= (1 << prio); + } else { + task->prev = readyqueues.queue[prio-1].last; + task->next = NULL; + readyqueues.queue[prio-1].last->next = task; + readyqueues.queue[prio-1].last = task; + } + } + + return ret; +} + +/** @brief Block current task + * + * The current task's status will be changed to TASK_BLOCKED + * + * @return + * - 0 on success + * - -EINVAL (-22) on failure + */ +int block_current_task(void) +{ + tid_t id; + uint32_t prio; + int ret = -EINVAL; + + id = current_task->id; + prio = current_task->prio; + + if (task_table[id].status == TASK_RUNNING) { + task_table[id].status = TASK_BLOCKED; + ret = 0; + + // reduce the number of ready tasks + readyqueues.nr_tasks--; + + // remove task from queue + if (task_table[id].prev) + task_table[id].prev->next = task_table[id].next; + if (task_table[id].next) + task_table[id].next->prev = task_table[id].prev; + if (readyqueues.queue[prio-1].first == task_table+id) + readyqueues.queue[prio-1].first = task_table[id].next; + if (readyqueues.queue[prio-1].last == task_table+id) { + readyqueues.queue[prio-1].last = task_table[id].prev; + if (!readyqueues.queue[prio-1].last) + readyqueues.queue[prio-1].last = readyqueues.queue[prio-1].first; + } + + // No valid task in queue => update prio_bitmap + if (!readyqueues.queue[prio-1].first) + readyqueues.prio_bitmap &= ~(1 << prio); + } + + return ret; +} + size_t** scheduler(void) { task_t* orig_task;