diff --git a/common/hooks.c b/common/hooks.c index c07a3d1d1c..6cca00c914 100644 --- a/common/hooks.c +++ b/common/hooks.c @@ -131,11 +131,6 @@ void hook_notify(enum hook_type type) #endif } -void hook_init(void) -{ - hook_notify(HOOK_INIT); -} - int hook_call_deferred(void (*routine)(void), int us) { const struct deferred_data *p; @@ -180,6 +175,12 @@ void hook_task(void) hook_task_started = 1; + /* Call HOOK_INIT hooks. */ + hook_notify(HOOK_INIT); + + /* Now, enable the rest of the tasks. */ + task_enable_all_tasks(); + while (1) { uint64_t t = get_time().val; int next = 0; diff --git a/common/main.c b/common/main.c index a2f86abdee..d70d987d43 100644 --- a/common/main.c +++ b/common/main.c @@ -160,9 +160,6 @@ test_mockable __keep int main(void) check_rw_signature(); #endif - /* Initialize the hook library. This calls HOOK_INIT hooks. */ - hook_init(); - /* * Print the init time. Not completely accurate because it can't take * into account the time before timer_init(), but it'll at least catch diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c index 639cef9d48..09d7108e7b 100644 --- a/core/cortex-m/task.c +++ b/core/cortex-m/task.c @@ -139,9 +139,11 @@ static int need_resched_or_profiling; /* * Bitmap of all tasks ready to be run. * - * Currently all tasks are enabled at startup. + * Start off with only the hooks task marked as ready such that all the modules + * can do their init within a task switching context. The hooks task will then + * make a call to enable all tasks. */ -static uint32_t tasks_ready = (1<= 0) { - if (tasks[i].event || now.val >= tasks[i].wake_time.val) - break; + /* + * Only tasks with spawned threads are valid to be + * resumed. + */ + if (tasks[i].thread) { + if (tasks[i].event || + now.val >= tasks[i].wake_time.val) + break; + } --i; } if (i < 0) @@ -404,7 +414,7 @@ void *_task_int_generator_start(void *d) int task_start(void) { - int i; + int i = TASK_ID_HOOKS; task_register_interrupt(); @@ -414,23 +424,25 @@ int task_start(void) pthread_mutex_lock(&run_lock); - for (i = 0; i < TASK_ID_COUNT; ++i) { - tasks[i].event = TASK_EVENT_WAKE; - tasks[i].wake_time.val = ~0ull; - tasks[i].started = 0; - pthread_cond_init(&tasks[i].resume, NULL); - pthread_create(&tasks[i].thread, NULL, _task_start_impl, - (void *)(uintptr_t)i); - pthread_cond_wait(&scheduler_cond, &run_lock); - /* - * Interrupt lock is grabbed by the task which just started. - * Let's unlock it so the next task can be started. - */ - pthread_mutex_unlock(&interrupt_lock); - } + /* + * Initialize the hooks task first. After its init, it will callback to + * enable the remaining tasks. + */ + tasks[i].event = TASK_EVENT_WAKE; + tasks[i].wake_time.val = ~0ull; + tasks[i].started = 0; + pthread_cond_init(&tasks[i].resume, NULL); + pthread_create(&tasks[i].thread, NULL, _task_start_impl, + (void *)(uintptr_t)i); + pthread_cond_wait(&scheduler_cond, &run_lock); + /* + * Interrupt lock is grabbed by the task which just started. + * Let's unlock it so the next task can be started. + */ + pthread_mutex_unlock(&interrupt_lock); /* - * All tasks are now waiting in task_wait_event(). Lock interrupt_lock + * The hooks task is waiting in task_wait_event(). Lock interrupt_lock * here so the first task chosen sees it locked. */ pthread_mutex_lock(&interrupt_lock); @@ -438,7 +450,46 @@ int task_start(void) pthread_create(&interrupt_thread, NULL, _task_int_generator_start, NULL); + /* + * Tell the hooks task to continue so that it can call back to enable + * the other tasks. + */ + pthread_cond_signal(&tasks[i].resume); + pthread_cond_wait(&scheduler_cond, &run_lock); + task_enable_all_tasks_callback(); + task_scheduler(); return 0; } + +static void task_enable_all_tasks_callback(void) +{ + int i; + + /* Initialize the remaning tasks. */ + for (i = 0; i < TASK_ID_COUNT; ++i) { + if (tasks[i].thread != (pthread_t)NULL) + continue; + + tasks[i].event = TASK_EVENT_WAKE; + tasks[i].wake_time.val = ~0ull; + tasks[i].started = 0; + pthread_cond_init(&tasks[i].resume, NULL); + pthread_create(&tasks[i].thread, NULL, _task_start_impl, + (void *)(uintptr_t)i); + /* + * Interrupt lock is grabbed by the task which just started. + * Let's unlock it so the next task can be started. + */ + pthread_mutex_unlock(&interrupt_lock); + pthread_cond_wait(&scheduler_cond, &run_lock); + } + +} + +void task_enable_all_tasks(void) +{ + /* Signal to the scheduler to enable the remaining tasks. */ + pthread_cond_signal(&scheduler_cond); +} diff --git a/core/nds32/task.c b/core/nds32/task.c index 269513092b..baf87ffbf3 100644 --- a/core/nds32/task.c +++ b/core/nds32/task.c @@ -139,9 +139,11 @@ int need_resched; /* * Bitmap of all tasks ready to be run. * - * Currently all tasks are enabled at startup. + * Start off with only the hooks task marked as ready such that all the modules + * can do their init within a task switching context. The hooks task will then + * make a call to enable all tasks. */ -static uint32_t tasks_ready = (1<