blob: e891ff2f88ad0720d461774d64252a629ea3d1cb [file] [log] [blame]
swissChilie20b79b2021-03-17 21:20:13 -07001#include "task.h"
2#include "alloc.h"
3#include "io.h"
swissChilicfd3c3c2021-04-03 15:04:24 -07004#include "log.h"
swissChilie20b79b2021-03-17 21:20:13 -07005#include "paging.h"
6
swissChilie9289ee2021-03-20 21:54:28 -07007struct process processes[1024] = {0};
8struct ll_task_i *first_task = NULL, *last_task = NULL, *current_task = NULL;
swissChilicfd3c3c2021-04-03 15:04:24 -07009static uint next_task_id = 0;
swissChilie9289ee2021-03-20 21:54:28 -070010
swissChilicfd3c3c2021-04-03 15:04:24 -070011void _init_tasks(uint kernel_esp, uint kernel_ebp, uint kernel_eip)
swissChilie20b79b2021-03-17 21:20:13 -070012{
swissChilicfd3c3c2021-04-03 15:04:24 -070013 kprintf("_init_tasks\n");
14
swissChilie9289ee2021-03-20 21:54:28 -070015 processes[0] = (struct process){
16 .exists = true,
17 .id = 0,
18 .ring = 0,
19 .uid = 0,
swissChilicfd3c3c2021-04-03 15:04:24 -070020 .page_directory_p = VIRT_TO_PHYS(kernel_page_directory),
21 // Obviously this isn't the actual stack position, but we want it to
22 // grow down from 4 gb so we will pretend that the first task has its
23 // stack at exactly 4gb and work from there. Because the new stack will
24 // be mapped to any random frame, it doesn't actually matter where we
25 // put it, we just want somewhere that won't collide with any user space
26 // stuff or our heap.
27 .last_stack_pos = 0xFFFFF000,
swissChilie9289ee2021-03-20 21:54:28 -070028 };
29 strcpy(processes[0].name, "kernel");
swissChilicfd3c3c2021-04-03 15:04:24 -070030 kprintf("in _init_tasks, strlen of 'kernel' is %d\n", strlen("kernel"));
swissChilie20b79b2021-03-17 21:20:13 -070031
swissChilie9289ee2021-03-20 21:54:28 -070032 first_task = last_task = current_task = malloc(sizeof(struct ll_task_i));
swissChilie20b79b2021-03-17 21:20:13 -070033
swissChilie9289ee2021-03-20 21:54:28 -070034 first_task->next = NULL;
35 first_task->task = (struct task){
36 .proc = &processes[0],
37 .esp = kernel_esp,
38 .ebp = kernel_ebp,
39 .eip = kernel_eip,
swissChilicfd3c3c2021-04-03 15:04:24 -070040 .id = next_task_id++,
swissChilie9289ee2021-03-20 21:54:28 -070041 };
swissChilie20b79b2021-03-17 21:20:13 -070042
swissChilicfd3c3c2021-04-03 15:04:24 -070043 kprintf("Returning from _init_tasks\n");
swissChilie20b79b2021-03-17 21:20:13 -070044}
45
swissChilie9289ee2021-03-20 21:54:28 -070046struct process *get_process(uint pid)
swissChilie20b79b2021-03-17 21:20:13 -070047{
swissChilie9289ee2021-03-20 21:54:28 -070048 if (pid < 1024)
49 return &processes[pid];
50 else
51 return NULL;
52}
swissChilie20b79b2021-03-17 21:20:13 -070053
swissChilie9289ee2021-03-20 21:54:28 -070054int get_task_id()
55{
56 return current_task->task.id;
57}
swissChilie20b79b2021-03-17 21:20:13 -070058
swissChilie9289ee2021-03-20 21:54:28 -070059int get_process_id()
60{
61 return current_task->task.proc->id;
62}
63
swissChilicfd3c3c2021-04-03 15:04:24 -070064void spawn_thread(void (*function)())
swissChilie9289ee2021-03-20 21:54:28 -070065{
swissChilicfd3c3c2021-04-03 15:04:24 -070066 asm volatile("cli");
swissChilie9289ee2021-03-20 21:54:28 -070067
swissChilicfd3c3c2021-04-03 15:04:24 -070068 struct process *proc = current_task->task.proc;
69 // Virtual address of page directory (in kernel memory)
70 uint *dir_v = PHYS_TO_VIRT(proc->page_directory_p);
71 // Virtual location of new stack
swissChilic496cd72021-04-04 09:58:38 -070072 uint new_stack_base_v = proc->last_stack_pos - sizeof(uint);
73 proc->last_stack_pos -= 0x1000;
swissChilicfd3c3c2021-04-03 15:04:24 -070074
75 // Alloc a new page in the current process mapping to the new stack
swissChilic496cd72021-04-04 09:58:38 -070076 alloc_page(dir_v, (void *)proc->last_stack_pos);
swissChilicfd3c3c2021-04-03 15:04:24 -070077
78 // <TEST>: see if we can assign to the new stack memory (ie: did mapping succeed)
79 uint *base = (uint *)new_stack_base_v;
80
81 kprintf("base = 0x%x\n", base);
82
83 *base = 0;
swissChilicfd3c3c2021-04-03 15:04:24 -070084 // </TEST>
85
86 struct ll_task_i *ll_task = malloc(sizeof(struct ll_task_i));
87 memset(ll_task, 0, sizeof(struct ll_task_i));
88 struct task *task = &ll_task->task;
89
90 task->proc = proc;
91 task->id = next_task_id++;
92 task->ebp = task->esp = new_stack_base_v;
93 task->eip = (uint)function;
94
95 last_task->next = ll_task;
96 last_task = ll_task;
97
98 asm volatile("sti");
99}
100
101extern void _switch_to_task(uint page_directory, uint eip, uint ebp, uint esp);
102
103void switch_to_task(struct task *task)
104{
105 _switch_to_task(task->proc->page_directory_p, task->eip, task->ebp,
106 task->esp);
107 __builtin_unreachable();
108}
109
110// WARNING: do not call this manually, it will clobber everything
111// except esp, ebp, and eip (obviously). Use switch_task in task_api.s
112// instead.
113void _do_switch_task(uint eip, uint ebp, uint esp)
114{
115 // sti is called in switch_to_task
116 asm volatile("cli");
117
118 kprintf("\nin _do_switch_task(%d, %d, %d)\n", eip, ebp, esp);
119
120 // save context for this task
121 current_task->task.ebp = ebp;
122 current_task->task.esp = esp;
123 current_task->task.eip = eip;
124
125 if (current_task->next == NULL)
126 {
127 // Start from the first task if there are more tasks, or just return
128 if (current_task == first_task)
129 return; // No context switch necessary
130
131 current_task = first_task;
132 }
133 else
134 {
135 // Continue the next task
136 current_task = current_task->next;
137 }
138
139 kprintf("Will switch to task id %d\n", current_task->task.id);
140
141 switch_to_task(&current_task->task);
swissChilie20b79b2021-03-17 21:20:13 -0700142}