diff --git a/common/cpu.c b/common/cpu.c index 0a915878..7f01cca4 100644 --- a/common/cpu.c +++ b/common/cpu.c @@ -113,16 +113,28 @@ void unblock_all_cpus(void) { set_cpu_unblocked(cpu); } +void block_all_cpus(void) { + cpu_t *cpu; + + list_for_each_entry (cpu, &cpus, list) + set_cpu_blocked(cpu); +} + +void finish_all_cpus(void) { + cpu_t *cpu; + + list_for_each_entry (cpu, &cpus, list) + set_cpu_finished(cpu); +} + void wait_for_all_cpus(void) { - cpu_t *cpu, *safe; - - do { - list_for_each_entry_safe (cpu, safe, &cpus, list) { - if (is_cpu_finished(cpu)) { - spin_lock(&cpu->lock); - list_unlink(&cpu->list); - spin_unlock(&cpu->lock); - } - } - } while (!list_is_empty(&cpus)); + cpu_t *cpu; + + list_for_each_entry (cpu, &cpus, list) { + if (cpu->bsp) + continue; + + while (!is_cpu_finished(cpu) || !list_is_empty(&cpu->task_queue)) + cpu_relax(); + } } diff --git a/common/kernel.c b/common/kernel.c index 6758391b..3ab05eb6 100644 --- a/common/kernel.c +++ b/common/kernel.c @@ -43,9 +43,6 @@ static void __noreturn echo_loop(void) { } void kernel_main(void) { - task_t *tests_task; - cpu_t *cpu; - printk("\nKTF - Kernel Test Framework!\n"); zap_boot_mappings(); @@ -54,17 +51,13 @@ void kernel_main(void) { display_multiboot_mmap(); } - tests_task = new_kernel_task("tests", test_main, NULL); - cpu = get_bsp_cpu(); - - schedule_task(tests_task, cpu); - - run_tasks(cpu); - unblock_all_cpus(); - wait_for_all_cpus(); + execute_tasks(); + test_main(NULL); printk("All tasks done.\n"); + execute_tasks(); + #ifdef KTF_PMU pfm_terminate(); #endif diff --git a/common/sched.c b/common/sched.c index 1da14b5e..4d8fa50f 100644 --- a/common/sched.c +++ b/common/sched.c @@ -217,7 +217,9 @@ void wait_for_task_group(const cpu_t *cpu, task_group_t group) { void run_tasks(cpu_t *cpu) { task_t *task, *safe; - wait_cpu_unblocked(cpu); + if (!cpu->bsp) + wait_cpu_unblocked(cpu); + set_cpu_unfinished(cpu); do { list_for_each_entry_safe (task, safe, &cpu->task_queue, list) { @@ -238,5 +240,7 @@ void run_tasks(cpu_t *cpu) { } } while (!list_is_empty(&cpu->task_queue)); + if (!cpu->bsp) + set_cpu_blocked(cpu); set_cpu_finished(cpu); } diff --git a/include/cpu.h b/include/cpu.h index 4b68761b..ed979bfb 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -60,6 +60,8 @@ extern cpu_t *get_bsp_cpu(void); extern unsigned int get_nr_cpus(void); extern void for_each_cpu(void (*func)(cpu_t *cpu)); extern void unblock_all_cpus(void); +extern void block_all_cpus(void); +extern void finish_all_cpus(void); extern void wait_for_all_cpus(void); /* Static declarations */ @@ -76,6 +78,10 @@ static inline void set_cpu_finished(cpu_t *cpu) { atomic_test_and_set_bit(CPU_FINISHED, &cpu->run_state); } +static inline void set_cpu_unfinished(cpu_t *cpu) { + atomic_test_and_reset_bit(CPU_FINISHED, &cpu->run_state); +} + static inline bool is_cpu_unblocked(cpu_t *cpu) { return atomic_test_bit(CPU_UNBLOCKED, &cpu->run_state); } @@ -84,6 +90,10 @@ static inline void set_cpu_unblocked(cpu_t *cpu) { atomic_test_and_set_bit(CPU_UNBLOCKED, &cpu->run_state); } +static inline void set_cpu_blocked(cpu_t *cpu) { + atomic_test_and_reset_bit(CPU_UNBLOCKED, &cpu->run_state); +} + static inline void wait_cpu_unblocked(cpu_t *cpu) { while (!is_cpu_unblocked(cpu)) cpu_relax(); diff --git a/include/sched.h b/include/sched.h index d40af72e..2e4af358 100644 --- a/include/sched.h +++ b/include/sched.h @@ -105,4 +105,9 @@ static inline task_t *new_user_task(const char *name, task_func_t func, void *ar return new_task(name, func, arg, TASK_TYPE_USER); } +static inline void execute_tasks(void) { + unblock_all_cpus(); + run_tasks(get_bsp_cpu()); + wait_for_all_cpus(); +} #endif /* KTF_SCHED_H */ diff --git a/smp/smp.c b/smp/smp.c index 47457119..438ee89a 100644 --- a/smp/smp.c +++ b/smp/smp.c @@ -64,10 +64,8 @@ void __noreturn ap_startup(void) { if (opt_fpu) enable_fpu(); - run_tasks(cpu); - while (true) - halt(); + run_tasks(cpu); UNREACHABLE(); } diff --git a/tests/test.c b/tests/test.c index 31295511..90ac8d9f 100644 --- a/tests/test.c +++ b/tests/test.c @@ -71,6 +71,8 @@ unsigned long test_main(void *unused) { printk("Running test: %s\n", name); rc = fn(NULL); + execute_tasks(); + printk("Test %s returned: 0x%x\n", name, rc); n++; }