summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/hooks.c11
-rw-r--r--common/main.c3
-rw-r--r--core/cortex-m/task.c14
-rw-r--r--core/cortex-m0/task.c14
-rw-r--r--core/host/main.c1
-rw-r--r--core/host/task.c81
-rw-r--r--core/nds32/task.c14
-rw-r--r--include/hooks.h5
-rw-r--r--include/task.h5
9 files changed, 113 insertions, 35 deletions
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<<TASK_ID_COUNT) - 1;
+static uint32_t tasks_ready = (1 << TASK_ID_HOOKS);
static int start_called; /* Has task swapping started */
@@ -412,6 +414,14 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us)
return events & event_mask;
}
+void task_enable_all_tasks(void)
+{
+ /* Mark all tasks as ready to run. */
+ tasks_ready = (1 << TASK_ID_COUNT) - 1;
+ /* Reschedule the highest priority task. */
+ __schedule(0, 0);
+}
+
void task_enable_irq(int irq)
{
CPU_NVIC_EN(irq / 32) = 1 << (irq % 32);
diff --git a/core/cortex-m0/task.c b/core/cortex-m0/task.c
index 9d9b049c37..0a229fcbde 100644
--- a/core/cortex-m0/task.c
+++ b/core/cortex-m0/task.c
@@ -126,9 +126,11 @@ static task_ *current_task = (task_ *)scratchpad;
/*
* 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<<TASK_ID_COUNT) - 1;
+static uint32_t tasks_ready = (1 << TASK_ID_HOOKS);
static int start_called; /* Has task swapping started */
@@ -432,6 +434,14 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us)
return events & event_mask;
}
+void task_enable_all_tasks(void)
+{
+ /* Mark all tasks as ready to run. */
+ tasks_ready = (1 << TASK_ID_COUNT) - 1;
+ /* Reschedule the highest priority task. */
+ __schedule(0, 0);
+}
+
void task_enable_irq(int irq)
{
CPU_NVIC_EN(0) = 1 << irq;
diff --git a/core/host/main.c b/core/host/main.c
index 80c2f33bf5..fbb28d9127 100644
--- a/core/host/main.c
+++ b/core/host/main.c
@@ -45,7 +45,6 @@ int main(int argc, char **argv)
#ifdef HAS_TASK_KEYSCAN
keyboard_scan_init();
#endif
- hook_init();
uart_init();
if (system_jumped_to_this_image()) {
diff --git a/core/host/task.c b/core/host/task.c
index 53f722e8b7..28c0cb0297 100644
--- a/core/host/task.c
+++ b/core/host/task.c
@@ -56,6 +56,8 @@ static int has_interrupt_generator = 1;
static __thread task_id_t my_task_id; /* thread local task id */
+static void task_enable_all_tasks_callback(void);
+
#define TASK(n, r, d, s) void r(void *);
CONFIG_TASK_LIST
CONFIG_TEST_TASK_LIST
@@ -331,6 +333,7 @@ static int fast_forward(void)
return TASK_ID_IDLE;
if (task_id != TASK_ID_INVALID &&
+ tasks[task_id].thread != (pthread_t)NULL &&
tasks[task_id].wake_time.val < generator_sleep_deadline.val) {
force_time(tasks[task_id].wake_time);
return task_id;
@@ -356,8 +359,15 @@ void task_scheduler(void)
now = get_time();
i = TASK_ID_COUNT - 1;
while (i >= 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,31 +424,72 @@ int task_start(void)
pthread_mutex_lock(&run_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);
+
+ /*
+ * 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);
+
+ 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);
- 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);
+ pthread_cond_wait(&scheduler_cond, &run_lock);
}
- /*
- * All tasks are now waiting in task_wait_event(). Lock interrupt_lock
- * here so the first task chosen sees it locked.
- */
- pthread_mutex_lock(&interrupt_lock);
-
- pthread_create(&interrupt_thread, NULL,
- _task_int_generator_start, NULL);
-
- task_scheduler();
+}
- return 0;
+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<<TASK_ID_COUNT) - 1;
+static uint32_t tasks_ready = (1 << TASK_ID_HOOKS);
static int start_called; /* Has task swapping started */
@@ -306,6 +308,14 @@ static void set_int_priority(uint32_t val)
asm volatile ("mtsr %0, $INT_PRI" : : "r"(val));
}
+void task_enable_all_tasks(void)
+{
+ /* Mark all tasks are ready to run. */
+ tasks_ready = (1 << TASK_ID_COUNT) - 1;
+ /* Reschedule the highest priority task. */
+ __schedule(0, 0, 0);
+}
+
void task_enable_irq(int irq)
{
int cpu_int = chip_enable_irq(irq);
diff --git a/include/hooks.h b/include/hooks.h
index f5a728d8e1..d62fca9b4a 100644
--- a/include/hooks.h
+++ b/include/hooks.h
@@ -168,11 +168,6 @@ struct hook_data {
};
/**
- * Initialize the hooks library.
- */
-void hook_init(void);
-
-/**
* Call all the hook routines of a specified type.
*
* This function must be called from the correct type-specific context (task);
diff --git a/include/task.h b/include/task.h
index 06cef86946..d7d6dd1ca3 100644
--- a/include/task.h
+++ b/include/task.h
@@ -184,6 +184,11 @@ void task_clear_fp_used(void);
#endif
/**
+ * Mark all tasks as ready to run and reschedule the highest priority task.
+ */
+void task_enable_all_tasks(void);
+
+/**
* Enable an interrupt.
*/
void task_enable_irq(int irq);