25
|
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
|