Mercurial > lcfOS
comparison cos/kernel/task.c @ 25:d3c4bf3720a3
Beginning of multitasking
author | windel |
---|---|
date | Tue, 27 Dec 2011 13:31:38 +0100 |
parents | |
children | 47b7df514243 |
comparison
equal
deleted
inserted
replaced
24:d8627924d40d | 25:d3c4bf3720a3 |
---|---|
1 #include "kernel.h" | |
2 | |
3 // global variables: | |
4 uint64_t next_pid = 1; | |
5 task_t* ready_queue = 0; // Head of the queue of tasks. | |
6 task_t* current_task = 0; // Pointer to the currently running task. | |
7 | |
8 void initialize_tasking() | |
9 { | |
10 next_pid = 1; | |
11 } | |
12 | |
13 /* | |
14 Create a new task with some loaded program. | |
15 */ | |
16 void new_task() | |
17 { | |
18 task_t* newtask = (task_t*)kmalloc(sizeof(task_t)); | |
19 newtask->pid = next_pid++; | |
20 newtask->rip = 0; | |
21 newtask->next = 0; | |
22 | |
23 // Append the new task to the ready queue: | |
24 task_t* task = ready_queue; | |
25 while (task->next != 0) | |
26 { | |
27 task = task->next; | |
28 } | |
29 task->next = newtask; | |
30 } | |
31 | |
32 /* Fork function duplicates the process */ | |
33 void task_fork() | |
34 { | |
35 asm volatile("cli"); // Disable interrupts | |
36 task_t *parent_task = current_task; | |
37 | |
38 // Create new task: | |
39 task_t *new_task = (task_t*)kmalloc(sizeof(task_t)); | |
40 new_task->pid = next_pid++; | |
41 new_task->rsp = 0; | |
42 new_task->rbp = 0; | |
43 new_task->rip = 0; | |
44 new_task->next = 0; | |
45 | |
46 // Append to the queue: | |
47 task_t* tmp_task = ready_queue; | |
48 while (tmp_task->next != 0) | |
49 { | |
50 tmp_task = tmp_task->next; | |
51 } | |
52 tmp_task->next = new_task; | |
53 | |
54 uint64_t rip = read_rip(); | |
55 | |
56 if (current_task == parent_task) | |
57 { | |
58 uint64_t rbp, rsp; | |
59 asm volatile("mov %%rsp, %0" : "=r"(rsp)); | |
60 asm volatile("mov %%rbp, %0" : "=r"(rbp)); | |
61 new_task->rip = rip; | |
62 | |
63 asm volatile("sti"); | |
64 } | |
65 } | |
66 | |
67 /* | |
68 Scheduler function that switches tasks for multi tasking. | |
69 */ | |
70 void task_scheduler() | |
71 { | |
72 if (current_task == 0) | |
73 { | |
74 return; | |
75 } | |
76 | |
77 uint64_t rbp, rsp, rip; | |
78 | |
79 rip = 0; | |
80 rsp = 0; | |
81 rbp = 0; | |
82 | |
83 current_task->rip = rip; // TODO | |
84 current_task->rsp = rsp; | |
85 current_task->rbp = rbp; | |
86 | |
87 // Select next task: | |
88 current_task = current_task->next; | |
89 if (current_task == 0) | |
90 { | |
91 current_task = ready_queue; | |
92 } | |
93 | |
94 // Set the rbp, rsp and rip registers: | |
95 rsp = current_task->rsp; | |
96 rbp = current_task->rbp; | |
97 } | |
98 |