blob: b460f25ecff7d40b6d606540ff5f88702121ed3b [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{
swissChilie9289ee2021-03-20 21:54:28 -070013 asm volatile("cli");
swissChilie20b79b2021-03-17 21:20:13 -070014
swissChilicfd3c3c2021-04-03 15:04:24 -070015 kprintf("_init_tasks\n");
16
swissChilie9289ee2021-03-20 21:54:28 -070017 processes[0] = (struct process){
18 .exists = true,
19 .id = 0,
20 .ring = 0,
21 .uid = 0,
swissChilicfd3c3c2021-04-03 15:04:24 -070022 .page_directory_p = VIRT_TO_PHYS(kernel_page_directory),
23 // Obviously this isn't the actual stack position, but we want it to
24 // grow down from 4 gb so we will pretend that the first task has its
25 // stack at exactly 4gb and work from there. Because the new stack will
26 // be mapped to any random frame, it doesn't actually matter where we
27 // put it, we just want somewhere that won't collide with any user space
28 // stuff or our heap.
29 .last_stack_pos = 0xFFFFF000,
swissChilie9289ee2021-03-20 21:54:28 -070030 };
31 strcpy(processes[0].name, "kernel");
swissChilicfd3c3c2021-04-03 15:04:24 -070032 kprintf("in _init_tasks, strlen of 'kernel' is %d\n", strlen("kernel"));
swissChilie20b79b2021-03-17 21:20:13 -070033
swissChilie9289ee2021-03-20 21:54:28 -070034 first_task = last_task = current_task = malloc(sizeof(struct ll_task_i));
swissChilie20b79b2021-03-17 21:20:13 -070035
swissChilie9289ee2021-03-20 21:54:28 -070036 first_task->next = NULL;
37 first_task->task = (struct task){
38 .proc = &processes[0],
39 .esp = kernel_esp,
40 .ebp = kernel_ebp,
41 .eip = kernel_eip,
swissChilicfd3c3c2021-04-03 15:04:24 -070042 .id = next_task_id++,
swissChilie9289ee2021-03-20 21:54:28 -070043 };
swissChilie20b79b2021-03-17 21:20:13 -070044
swissChilicfd3c3c2021-04-03 15:04:24 -070045 kprintf("Returning from _init_tasks\n");
46
swissChilie9289ee2021-03-20 21:54:28 -070047 asm volatile("sti");
swissChilie20b79b2021-03-17 21:20:13 -070048}
49
swissChilie9289ee2021-03-20 21:54:28 -070050struct process *get_process(uint pid)
swissChilie20b79b2021-03-17 21:20:13 -070051{
swissChilie9289ee2021-03-20 21:54:28 -070052 if (pid < 1024)
53 return &processes[pid];
54 else
55 return NULL;
56}
swissChilie20b79b2021-03-17 21:20:13 -070057
swissChilie9289ee2021-03-20 21:54:28 -070058int get_task_id()
59{
60 return current_task->task.id;
61}
swissChilie20b79b2021-03-17 21:20:13 -070062
swissChilie9289ee2021-03-20 21:54:28 -070063int get_process_id()
64{
65 return current_task->task.proc->id;
66}
67
swissChilicfd3c3c2021-04-03 15:04:24 -070068void spawn_thread(void (*function)())
swissChilie9289ee2021-03-20 21:54:28 -070069{
swissChilicfd3c3c2021-04-03 15:04:24 -070070 asm volatile("cli");
swissChilie9289ee2021-03-20 21:54:28 -070071
swissChilicfd3c3c2021-04-03 15:04:24 -070072 struct process *proc = current_task->task.proc;
73 // Virtual address of page directory (in kernel memory)
74 uint *dir_v = PHYS_TO_VIRT(proc->page_directory_p);
75 // Virtual location of new stack
swissChilic496cd72021-04-04 09:58:38 -070076 uint new_stack_base_v = proc->last_stack_pos - sizeof(uint);
77 proc->last_stack_pos -= 0x1000;
swissChilicfd3c3c2021-04-03 15:04:24 -070078
79 // Alloc a new page in the current process mapping to the new stack
swissChilic496cd72021-04-04 09:58:38 -070080 alloc_page(dir_v, (void *)proc->last_stack_pos);
swissChilicfd3c3c2021-04-03 15:04:24 -070081
82 // <TEST>: see if we can assign to the new stack memory (ie: did mapping succeed)
83 uint *base = (uint *)new_stack_base_v;
84
85 kprintf("base = 0x%x\n", base);
86
87 *base = 0;
swissChilicfd3c3c2021-04-03 15:04:24 -070088 // </TEST>
89
90 struct ll_task_i *ll_task = malloc(sizeof(struct ll_task_i));
91 memset(ll_task, 0, sizeof(struct ll_task_i));
92 struct task *task = &ll_task->task;
93
94 task->proc = proc;
95 task->id = next_task_id++;
96 task->ebp = task->esp = new_stack_base_v;
97 task->eip = (uint)function;
98
99 last_task->next = ll_task;
100 last_task = ll_task;
101
102 asm volatile("sti");
103}
104
105extern void _switch_to_task(uint page_directory, uint eip, uint ebp, uint esp);
106
107void switch_to_task(struct task *task)
108{
109 _switch_to_task(task->proc->page_directory_p, task->eip, task->ebp,
110 task->esp);
111 __builtin_unreachable();
112}
113
114// WARNING: do not call this manually, it will clobber everything
115// except esp, ebp, and eip (obviously). Use switch_task in task_api.s
116// instead.
117void _do_switch_task(uint eip, uint ebp, uint esp)
118{
119 // sti is called in switch_to_task
120 asm volatile("cli");
121
122 kprintf("\nin _do_switch_task(%d, %d, %d)\n", eip, ebp, esp);
123
124 // save context for this task
125 current_task->task.ebp = ebp;
126 current_task->task.esp = esp;
127 current_task->task.eip = eip;
128
129 if (current_task->next == NULL)
130 {
131 // Start from the first task if there are more tasks, or just return
132 if (current_task == first_task)
133 return; // No context switch necessary
134
135 current_task = first_task;
136 }
137 else
138 {
139 // Continue the next task
140 current_task = current_task->next;
141 }
142
143 kprintf("Will switch to task id %d\n", current_task->task.id);
144
145 switch_to_task(&current_task->task);
swissChilie20b79b2021-03-17 21:20:13 -0700146}