SayoriOS 0.3.3

scheduler.c
См. документацию.
1
9 #include "sys/scheduler.h"
10 #include "lib/string.h"
11 #include "io/ports.h"
12 #include "mem/vmm.h"
13
14 list_t process_list;
15 list_t thread_list;
16
17 uint32_t next_pid = 0;
18 uint32_t next_thread_id = 0;
19 bool multi_task = false;
20 process_t* kernel_proc = 0;
21 thread_t* kernel_thread = 0;
22 process_t* current_proc = 0;
23 thread_t* current_thread = 0;
24 extern uint32_t init_esp;
25
26 bool scheduler_working = true;
27
28 extern physical_addr_t kernel_page_directory;
29
33 void init_task_manager(void){
34 uint32_t esp = 0;
35 __asm__ volatile("mov %%esp, %0" : "=a"(esp));
36
37 /* Disable all interrupts */
38 __asm__ volatile ("cli");
39
40 list_init(&process_list);
41 list_init(&thread_list);
42
43 /* Create kernel process */
44 kernel_proc = (process_t*)kcalloc(sizeof(process_t), 1);
45
46 kernel_proc->pid = next_pid++;
47 // NOTE: Page directory address must be PHYSICAL!
48 kernel_proc->page_dir = kernel_page_directory;
49 kernel_proc->list_item.list = nullptr;
50 kernel_proc->threads_count = 1;
51 strcpy(kernel_proc->name, "Kernel");
52 kernel_proc->suspend = false;
53
54 list_add(&process_list, &kernel_proc->list_item);
55
56 /* Create kernel thread */
57 kernel_thread = (thread_t*) kmalloc(sizeof(thread_t));
58
59 memset(kernel_thread, 0, sizeof(thread_t));
60
61 kernel_thread->process = kernel_proc;
62 kernel_thread->list_item.list = nullptr;
63 kernel_thread->id = next_thread_id++;
64 kernel_thread->stack_size = 0x4000;
65 kernel_thread->suspend = false;
66 kernel_thread->esp = esp;
67 kernel_thread->stack_top = init_esp;
68
69 list_add(&thread_list, &kernel_thread->list_item);
70
71 current_proc = kernel_proc;
72 current_thread = kernel_thread;
73
74 __asm__ volatile ("sti");
75
76 /* Enable multitasking flag */
77 multi_task = true;
78
79 qemu_ok("OK");
80 }
81
82 void scheduler_mode(bool on) {
83 scheduler_working = on;
84 }
85
86 size_t create_process(void* entry_point, char name[256], bool suspend, bool is_kernel) {
87 scheduler_working = false;
88 __asm__ volatile("cli");
89
90 process_t* proc = (process_t*)kcalloc(1, sizeof(process_t));
91
92 proc->pid = next_pid++;
93 proc->list_item.list = nullptr; // No nested processes hehe :)
94 proc->threads_count = 0;
95
96 strcpy(proc->name, name);
97 proc->suspend = suspend;
98
99 list_add(&process_list, &proc->list_item);
100
101 thread_t* thread = _thread_create_unwrapped(proc, entry_point, DEFAULT_STACK_SIZE, is_kernel, suspend);
102
103 qemu_log("PID: %d, DIR: %x; Threads: %d; Suspend: %d", proc->pid, proc->page_dir, proc->threads_count, proc->suspend);
104
105 list_add(&thread_list, &thread->list_item);
106
107 void* virt = clone_kernel_page_directory(proc->page_tables_virts);
108 uint32_t phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t) virt);
109
110 proc->page_dir = phys;
111
112 qemu_log("FINISHED!");
113
114 __asm__ volatile("sti");
115 scheduler_working = true;
116
117 return proc->pid;
118 }
119
125 volatile process_t * get_current_proc(void) {
126 return current_proc;
127 }
128
129 __attribute__((noreturn)) void blyat_fire() {
130 qemu_note("THREAD %d WANTS TO EXIT!", current_thread->id);
131 thread_exit(current_thread);
132 while(1) // If something goes wrong, we loop here.
133 ;
134 }
135
147 thread_t* _thread_create_unwrapped(process_t* proc, void* entry_point, size_t stack_size,
148 bool kernel, bool suspend) {
149 void* stack = nullptr;
150 uint32_t eflags;
151
152 /* Create new thread handler */
153 thread_t* tmp_thread = (thread_t*) kcalloc(sizeof(thread_t), 1);
154
155 /* Clear memory */
156 memset(tmp_thread, 0, sizeof(thread_t));
157
158 /* Initialization of thread */
159 tmp_thread->id = next_thread_id++;
160 tmp_thread->list_item.list = nullptr;
161 tmp_thread->process = proc;
162 tmp_thread->stack_size = stack_size;
163 tmp_thread->suspend = suspend;/* */
164 tmp_thread->entry_point = (uint32_t) entry_point;
165
166 /* Create thread's stack */
167 stack = (void*) kcalloc(stack_size, 1);
168
169 tmp_thread->stack = stack;
170 tmp_thread->esp = (uint32_t) stack + stack_size - (7 * 4);
171 tmp_thread->stack_top = (uint32_t) stack + stack_size;
172
173 /* Add thread to ring queue */
174 list_add(&thread_list, &tmp_thread->list_item);
175
176 /* Thread's count increment */
177 proc->threads_count++;
178
179 /* Fill stack */
180
181 /* Create pointer to stack frame */
182 uint32_t* esp = (uint32_t*) ((char*)stack + stack_size);
183
184 // Get EFL
185 __asm__ volatile ("pushf; pop %0":"=r"(eflags));
186
187 eflags |= (1 << 9);
188
189 esp[-1] = (uint32_t) blyat_fire;
190 esp[-2] = (uint32_t) entry_point;
191 esp[-3] = eflags;
192 esp[-4] = 0;
193 esp[-5] = 0;
194 esp[-6] = 0;
195 esp[-7] = 0;
196
197 return tmp_thread;
198 }
199
200 thread_t* thread_create(process_t* proc, void* entry_point, size_t stack_size,
201 bool kernel, bool suspend){
202 /* Disable all interrupts */
203 __asm__ volatile ("cli");
204
205 /* Create new thread handler */
206 thread_t* tmp_thread = (thread_t*) _thread_create_unwrapped(proc, entry_point, stack_size, kernel, suspend);
207
208 /* Enable all interrupts */
209 __asm__ volatile ("sti");
210
211 qemu_ok("CREATED THREAD");
212
213 return tmp_thread;
214 }
215
222 void thread_suspend(thread_t* thread, bool suspend){
223 thread->suspend = suspend;
224 }
225
231 void thread_exit(thread_t* thread){
232 /* Disable all interrupts */
233 __asm__ volatile ("cli");
234
235 /* Remove thread from queue */
236 // list_remove(&thread->list_item);
237 //
238 // thread->process->threads_count--;
239 //
240 // /* Free thread's memory (handler and stack) */
241 // kfree(thread->stack);
242 // kfree(thread);
243
244 thread->state = DEAD;
245
246 /* Load to ECX switch function address */
247 __asm__ volatile ("mov %0, %%ecx"::"a"(&task_switch_v2_wrapper));
248
249 /* Enable all interrupts */
250 __asm__ volatile ("sti");
251
252 /* Jump to switch_task() */
253 __asm__ volatile ("call *%ecx");
254 }
255
261 bool is_multitask(void){
262 return multi_task;
263 }
264
265 void task_switch_v2_wrapper(__attribute__((unused)) registers_t regs) {
266 thread_t* next_thread = (thread_t *)current_thread->list_item.next;
267
268 while(next_thread->state == PAUSED || next_thread->state == DEAD) {
269 thread_t* next_thread_soon = (thread_t *)next_thread->list_item.next;
270
271 if(next_thread->state == DEAD) {
272 qemu_log("QUICK NOTICE: WE ARE IN PROCESS NR. #%u", current_proc->pid);
273
274 process_t* process = next_thread->process;
275 qemu_log("REMOVING DEAD THREAD: #%u", next_thread->id);
276
277 list_remove(&next_thread->list_item);
278
279 qemu_log("REMOVED FROM LIST");
280
281 kfree(next_thread->stack);
282 kfree(next_thread);
283
284 qemu_log("FREED MEMORY");
285
286 process->threads_count--;
287
288 qemu_log("MODIFIED PROCESS");
289
290 bool is_krnl_process = current_proc->pid == 0; // TODO: Switch to kernel's PD here, because process info stored there
291 if(process->threads_count == 0 && is_krnl_process) {
292 // `st` command crashes here
293 qemu_log("PROCESS #%d `%s` DOES NOT HAVE ANY THREADS", process->pid, process->name);
294
295 // heap_dump();
296
297 for(size_t pt = 0; pt < 1024; pt++) {
298 size_t page_table = process->page_tables_virts[pt];
299 // qemu_log("[%p: %d] PAGE TABLE AT: %x", process->page_tables_virts + pt, pt, page_table);
300
301 if(page_table) {
302 qemu_note("[%d] FREE PAGE TABLE AT: %x", pt, page_table);
303 kfree((void *) page_table);
304 }
305 }
306 // end
307
308 qemu_log("FREED PAGE TABLES");
309
310 kfree((void *) process->page_dir_virt);
311
312 qemu_log("FREED SPACE FOR TABLES");
313
314 list_remove(&process->list_item);
315
316 qemu_log("REMOVED PROCESS FROM LIST");
317
318 kfree(process);
319
320 qemu_log("FREED PROCESS LIST ITEM");
321 }
322 }
323
324 next_thread = next_thread_soon;
325 }
326
327 task_switch_v2(current_thread, next_thread);
328 }
329
336 //void init_user_mode(void* entry_point, size_t stack_size){
337 // void* user_stack = (void*) kmalloc(stack_size);
338 //
339 // user_mode_switch(entry_point, (uint32_t) user_stack + stack_size);
340 //}
memset
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
Definition: string.c:203
strcpy
int strcpy(char *dest, const char *src)
Копирование строк
Definition: string.c:282
get_current_proc
volatile process_t * get_current_proc(void)
Получить текущий обработчик процесса
Definition: scheduler.c:125
thread_exit
void thread_exit(thread_t *thread)
Завершить текущий поток
Definition: scheduler.c:231
process_list
list_t process_list
Список процессов
Definition: scheduler.c:14
thread_list
list_t thread_list
Список потоков
Definition: scheduler.c:15
_thread_create_unwrapped
thread_t * _thread_create_unwrapped(process_t *proc, void *entry_point, size_t stack_size, bool kernel, bool suspend)
Создание потока
Definition: scheduler.c:147
init_task_manager
void init_task_manager(void)
Инициализация менеджера задач
Definition: scheduler.c:33
kernel_thread
thread_t * kernel_thread
Обработчик основного потока ядра
Definition: scheduler.c:21
kernel_proc
process_t * kernel_proc
Обработчик процесса ядра
Definition: scheduler.c:20
thread_suspend
void thread_suspend(thread_t *thread, bool suspend)
Остановить поток
Definition: scheduler.c:222
next_pid
uint32_t next_pid
Следующий ID задачи (PID)
Definition: scheduler.c:17
multi_task
bool multi_task
Готова ли система к многозадачности
Definition: scheduler.c:19
current_thread
thread_t * current_thread
Текущий поток
Definition: scheduler.c:23
current_proc
process_t * current_proc
Текущий процесс
Definition: scheduler.c:22
next_thread_id
uint32_t next_thread_id
Следующий ID потока
Definition: scheduler.c:18
is_multitask
bool is_multitask(void)
Получение состояния о мультипотоке
Definition: scheduler.c:261
__attribute__
Структура файла
Definition: ahci.h:15
list_t
Definition: list.h:16
registers
Definition: common.h:59