Exemple #1
0
int set_timer(uint64_t deadline)
{
	task_t* curr_task;
	uint32_t core_id;
	uint8_t flags;
	int ret = -EINVAL;

	flags = irq_nested_disable();

	curr_task = per_core(current_task);
	core_id = CORE_ID;

	if (curr_task->status == TASK_RUNNING) {
		// blocks task and removes from ready queue
		block_task(curr_task->id);

		curr_task->flags |= TASK_TIMER;
		curr_task->timeout = deadline;

		timer_queue_push(core_id, curr_task);

		ret = 0;
	} else {
		LOG_INFO("Task is already blocked. No timer will be set!\n");
	}

	irq_nested_enable(flags);

	return ret;
}
Exemple #2
0
int block_task(tid_t id)
{
	task_t* task;
	uint32_t core_id;
	int ret = -EINVAL;
	uint8_t flags;

	flags = irq_nested_disable();

	task = &task_table[id];
	core_id = task->last_core;

	if (task->status == TASK_RUNNING) {
		LOG_DEBUG("block task %d on core %d\n", id, core_id);

		task->status = TASK_BLOCKED;

		spinlock_irqsave_lock(&readyqueues[core_id].lock);

		// remove task from ready queue
		readyqueues_remove(core_id, task);

		// reduce the number of ready tasks
		readyqueues[core_id].nr_tasks--;
		LOG_DEBUG("update nr_tasks on core %d to %d\n", core_id, readyqueues[core_id].nr_tasks);

		spinlock_irqsave_unlock(&readyqueues[core_id].lock);

		ret = 0;
	}

	irq_nested_enable(flags);

	return ret;
}
Exemple #3
0
void NORETURN do_exit(int arg)
{
	task_t* curr_task = per_core(current_task);
	const uint32_t core_id = CORE_ID;

	LOG_INFO("Terminate task: %u, return value %d\n", curr_task->id, arg);

	uint8_t flags = irq_nested_disable();

	// decrease the number of active tasks
	spinlock_irqsave_lock(&readyqueues[core_id].lock);
	readyqueues[core_id].nr_tasks--;
	spinlock_irqsave_unlock(&readyqueues[core_id].lock);

	// release the thread local storage
	destroy_tls();

	curr_task->status = TASK_FINISHED;

	reschedule();

	irq_nested_enable(flags);

	LOG_ERROR("Kernel panic: scheduler found no valid task\n");
	while(1) {
		HALT;
	}
}
Exemple #4
0
void reschedule(void)
{
	size_t** stack;
	uint8_t flags;

	flags = irq_nested_disable();
	if ((stack = scheduler()))
		switch_context(stack);
	irq_nested_enable(flags);
}
Exemple #5
0
/** @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;
	uint8_t flags;

	flags = irq_nested_disable();

	id = current_task->id;
	prio = current_task->prio;

	if (task_table[id].status == TASK_RUNNING) {
		task_table[id].status = TASK_BLOCKED;
		ret = 0;

		spinlock_irqsave_lock(&readyqueues.lock);
		// 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);
		spinlock_irqsave_unlock(&readyqueues.lock);
	}

	irq_nested_enable(flags);

	return ret;
}
Exemple #6
0
/** @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;
	uint8_t flags;

	flags = irq_nested_disable();

	task = task_table + id;
	prio = task->prio;

	if (task->status == TASK_BLOCKED) {
		task->status = TASK_READY;
		ret = 0;

		spinlock_irqsave_lock(&readyqueues.lock);
		// 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;
		}
		spinlock_irqsave_unlock(&readyqueues.lock);
	}

	irq_nested_enable(flags);

	return ret;
}