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 
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;
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 
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);
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 //}
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
Definition: string.c:203
int strcpy(char *dest, const char *src)
Копирование строк
Definition: string.c:282
volatile process_t * get_current_proc(void)
Получить текущий обработчик процесса
Definition: scheduler.c:125
void thread_exit(thread_t *thread)
Завершить текущий поток
Definition: scheduler.c:231
list_t process_list
Список процессов
Definition: scheduler.c:14
list_t thread_list
Список потоков
Definition: scheduler.c:15
thread_t * _thread_create_unwrapped(process_t *proc, void *entry_point, size_t stack_size, bool kernel, bool suspend)
Создание потока
Definition: scheduler.c:147
void init_task_manager(void)
Инициализация менеджера задач
Definition: scheduler.c:33
thread_t * kernel_thread
Обработчик основного потока ядра
Definition: scheduler.c:21
process_t * kernel_proc
Обработчик процесса ядра
Definition: scheduler.c:20
void thread_suspend(thread_t *thread, bool suspend)
Остановить поток
Definition: scheduler.c:222
uint32_t next_pid
Следующий ID задачи (PID)
Definition: scheduler.c:17
bool multi_task
Готова ли система к многозадачности
Definition: scheduler.c:19
thread_t * current_thread
Текущий поток
Definition: scheduler.c:23
process_t * current_proc
Текущий процесс
Definition: scheduler.c:22
uint32_t next_thread_id
Следующий ID потока
Definition: scheduler.c:18
bool is_multitask(void)
Получение состояния о мультипотоке
Definition: scheduler.c:261
Структура файла
Definition: ahci.h:15
Definition: list.h:16