blob: 82ad5ef42f414adacba912fcb17807b080d4ffbd [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
76 uint new_stack_base_v = proc->last_stack_pos = proc->last_stack_pos - 0x1000;
77
78 // Alloc a new page in the current process mapping to the new stack
79 alloc_page(dir_v, (void *)new_stack_base_v);
80
81 // <TEST>: see if we can assign to the new stack memory (ie: did mapping succeed)
82 uint *base = (uint *)new_stack_base_v;
83
84 kprintf("base = 0x%x\n", base);
85
86 *base = 0;
swissChilicfd3c3c2021-04-03 15:04:24 -070087 // </TEST>
88
89 struct ll_task_i *ll_task = malloc(sizeof(struct ll_task_i));
90 memset(ll_task, 0, sizeof(struct ll_task_i));
91 struct task *task = &ll_task->task;
92
93 task->proc = proc;
94 task->id = next_task_id++;
95 task->ebp = task->esp = new_stack_base_v;
96 task->eip = (uint)function;
97
98 last_task->next = ll_task;
99 last_task = ll_task;
100
101 asm volatile("sti");
102}
103
104extern void _switch_to_task(uint page_directory, uint eip, uint ebp, uint esp);
105
106void switch_to_task(struct task *task)
107{
108 _switch_to_task(task->proc->page_directory_p, task->eip, task->ebp,
109 task->esp);
110 __builtin_unreachable();
111}
112
113// WARNING: do not call this manually, it will clobber everything
114// except esp, ebp, and eip (obviously). Use switch_task in task_api.s
115// instead.
116void _do_switch_task(uint eip, uint ebp, uint esp)
117{
118 // sti is called in switch_to_task
119 asm volatile("cli");
120
121 kprintf("\nin _do_switch_task(%d, %d, %d)\n", eip, ebp, esp);
122
123 // save context for this task
124 current_task->task.ebp = ebp;
125 current_task->task.esp = esp;
126 current_task->task.eip = eip;
127
128 if (current_task->next == NULL)
129 {
130 // Start from the first task if there are more tasks, or just return
131 if (current_task == first_task)
132 return; // No context switch necessary
133
134 current_task = first_task;
135 }
136 else
137 {
138 // Continue the next task
139 current_task = current_task->next;
140 }
141
142 kprintf("Will switch to task id %d\n", current_task->task.id);
143
144 switch_to_task(&current_task->task);
swissChilie20b79b2021-03-17 21:20:13 -0700145}