-
Notifications
You must be signed in to change notification settings - Fork 0
/
task.c
66 lines (58 loc) · 1.26 KB
/
task.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "task.h"
#include "os.h"
#include "armv7.h"
extern void task_entry_shim(void);
/*
stk 100
-- Popped by task_entry_shim --
FC pc_new
F8 lr_new
-- Popped by do_task_switch --
F4 lr
F0 r11
EC r10
E8 r9
E4 r8
E0 r7
DC r6
D8 r5
sp D4 r4
*/
struct cpu_regs {
u32 r4;
u32 r5;
u32 r6;
u32 r7;
u32 r8;
u32 r9;
u32 r10;
u32 r11;
u32 lr;
u32 lr_new;
u32 pc_new;
};
struct task* current_task;
struct task* next_task;
void init_task(struct task *task, void (*func)(void), void* stack) {
struct cpu_regs *regs;
task->priority = 0;
task->q = LIST_INIT(task->q);
task->sp = (u32)stack - sizeof(struct cpu_regs);
regs = (void*)task->sp;
memset(regs, 0, sizeof(*regs));
regs->lr = (u32)task_entry_shim;
regs->pc_new = (u32)func;
regs->lr_new = (u32)dequeue_current_task;
}
void task_switch(void) {
struct task *old;
/* TODO: assert interrupts enabled */
/* TODO: assert current/next task runnable */
/* disable interrupts. Interrups are reenabled in do_tasks_switch */
disable_irq();
if (next_task != current_task) {
old = current_task;
current_task = next_task;
do_task_switch(current_task, old);
}
}