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