diff --git a/include/metalsvm/tasks_types.h b/include/metalsvm/tasks_types.h index dbadd0a5..a4c080a4 100755 --- a/include/metalsvm/tasks_types.h +++ b/include/metalsvm/tasks_types.h @@ -51,7 +51,6 @@ extern "C" { #define TASK_DEFAULT_FLAGS 0 #define TASK_FPU_INIT (1 << 0) #define TASK_FPU_USED (1 << 1) -#define TASK_SWITCH_IN_PROGESS (1 << 2) typedef int (*entry_point_t)(void*); typedef int (STDCALL *internal_entry_point_t)(void*); diff --git a/kernel/tasks.c b/kernel/tasks.c index 508cf53f..28629171 100755 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -53,7 +53,9 @@ static task_t task_table[MAX_TASKS] = { \ static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT; DEFINE_PER_CORE(task_t*, current_task, task_table+0); +#if MAX_CORES > 1 DEFINE_PER_CORE_STATIC(task_t*, old_task, NULL); +#endif /** @brief helper function for the assembly code to determine the current task * @return Pointer to the task_t structure of current task @@ -148,7 +150,7 @@ static void NORETURN do_exit(int arg) { curr_task->status = TASK_FINISHED; reschedule(); - kputs("Kernel panic: scheduler found no valid task\n"); + kprintf("Kernel panic: scheduler on core %d found no valid task\n", CORE_ID); while(1) { HALT; } @@ -173,21 +175,14 @@ void NORETURN abort(void) { } /* - * @brief: if the task switch is finished, we reset - * the TASK_SWITCH_IN_PROGRESS bit + * @brief: if the task gets the first time slice, + * the table_lock is hold and have to be released. */ -inline static void task_switch_finished(void) +inline static void start_first_time_slice(void) { - uint32_t flags = irq_nested_disable(); - - // do we already reset the TASK_SWITCH_IN_PROGRESS bit? - task_t* old = per_core(old_task); - if (old) { - old->flags &= ~TASK_SWITCH_IN_PROGESS; - per_core(old_task) = NULL; - } - - irq_nested_enable(flags); +#if MAX_CORES > 1 + spinlock_irqsave_unlock(&table_lock); +#endif } /** @brief Create a task with a specific entry point @@ -318,10 +313,7 @@ int sys_fork(void) // Leave the function without releasing the locks // because the locks are already released // by the parent task! - - // first switch to the new current task - // => signalizes a successful task switch - task_switch_finished(); + start_first_time_slice(); return 0; } @@ -356,9 +348,7 @@ static int STDCALL kernel_entry(void* args) int ret; kernel_args_t* kernel_args = (kernel_args_t*) args; - // first switch to the new current task - // => signalizes a successful task switch - task_switch_finished(); + start_first_time_slice(); if (BUILTIN_EXPECT(!kernel_args, 0)) return -EINVAL; @@ -606,9 +596,7 @@ static int STDCALL user_entry(void* arg) { int ret; - // first switch to the new current task - // => signalizes a successful task switch - task_switch_finished(); + start_first_time_slice(); if (BUILTIN_EXPECT(!arg, 0)) return -EINVAL; @@ -827,11 +815,6 @@ void scheduler(void) unsigned int i; unsigned int new_id; - // let's play it save - // => check if we already signalizes that the previous switch - // is finished - task_switch_finished(); - #if MAX_CORES > 1 spinlock_irqsave_lock(&table_lock); #endif @@ -851,26 +834,16 @@ void scheduler(void) for(i=1, new_id=(curr_task->id + 1) % MAX_TASKS; istatus == TASK_RUNNING) { + if (task_table[new_id].status == TASK_READY) { + if (curr_task->status == TASK_RUNNING) curr_task->status = TASK_READY; - curr_task->flags |= TASK_SWITCH_IN_PROGESS; - per_core(old_task) = curr_task; - } else per_core(old_task) = NULL; - task_table[new_id].status = TASK_RUNNING; curr_task = per_core(current_task) = task_table+new_id; goto get_task_out; } - - //if ((task_table[new_id].status == TASK_READY) && (task_table[new_id].flags & TASK_SWITCH_IN_PROGESS)) - // kprintf("task switch %d is in progress\n", new_id); } - // old task will never rescheduled - per_core(old_task) = NULL; - if ((curr_task->status == TASK_RUNNING) || (curr_task->status == TASK_IDLE)) goto get_task_out; @@ -883,14 +856,13 @@ void scheduler(void) get_task_out: //kprintf("schedule %d on core %d\n", per_core(current_task)->id, smp_id()); + + if (curr_task != orig_task) + switch_task(new_id); + #if MAX_CORES > 1 spinlock_irqsave_unlock(&table_lock); #endif - - if (curr_task != orig_task) { - switch_task(new_id); - task_switch_finished(); - } } void reschedule(void)