add basic functions to block and to unblock a task

This commit is contained in:
Stefan Lankes 2013-11-26 09:17:14 +01:00
parent ab28a5e612
commit ba491114bc
2 changed files with 103 additions and 0 deletions

View file

@ -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);

View file

@ -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;