OSDN Git Service

svn rev.329より移動。
[chnosproject/CHNOSProject.git] / CHNOSProject / chnos / tolset_chn_000 / chnos_008 / chnos / mtask.c
diff --git a/CHNOSProject/chnos/tolset_chn_000/chnos_008/chnos/mtask.c b/CHNOSProject/chnos/tolset_chn_000/chnos_008/chnos/mtask.c
new file mode 100644 (file)
index 0000000..2ade50d
--- /dev/null
@@ -0,0 +1,189 @@
+\r
+#include "core.h"\r
+\r
+UI_TaskControl *taskctl;\r
+\r
+void task_init(void)\r
+{\r
+       int i;\r
+       taskctl = (UI_TaskControl *)sys_memman_alloc(sizeof(UI_TaskControl));\r
+       for(i = 0; i < MAX_TASKS; i++){\r
+               taskctl->tasks0[i].flags = initialized;\r
+               taskctl->tasks0[i].selector = (TASK_GDT_START + i) * 8;\r
+               set_segmdesc(system.io.mem.segment.gdt + TASK_GDT_START + i, 103, (int)&taskctl->tasks0[i].tss, AR_TSS32);\r
+       }\r
+       for(i = 0; i < MAX_LEVELS; i++){\r
+               taskctl->level[i].running_tasks = 0;\r
+               taskctl->level[i].task_now = 0;\r
+       }\r
+\r
+       system.ui.task.idle = task_alloc();\r
+       system.ui.task.idle->tss.esp = (int)sys_memman_alloc(64 * 1024) + 64 * 1024;\r
+       system.ui.task.idle->tss.eip = (int)&task_idle;\r
+       system.ui.task.idle->tss.es = 1 * 8;\r
+       system.ui.task.idle->tss.cs = 2 * 8;\r
+       system.ui.task.idle->tss.ss = 1 * 8;\r
+       system.ui.task.idle->tss.ds = 1 * 8;\r
+       system.ui.task.idle->tss.fs = 1 * 8;\r
+       system.ui.task.idle->tss.gs = 1 * 8;\r
+       task_run(system.ui.task.idle, MAX_LEVELS - 1, 1);\r
+\r
+       system.ui.task.main = task_alloc();\r
+       system.ui.task.main->flags = inuse;\r
+       system.ui.task.main->priority = 2; /*0.02sec*/\r
+       system.ui.task.main->level = 0;\r
+       task_add(system.ui.task.main);\r
+       task_switchsub();\r
+       load_tr(system.ui.task.main->selector);\r
+       system.ui.timer.taskswitch = timer_alloc();\r
+       timer_settime(system.ui.timer.taskswitch, system.ui.task.main->priority);\r
+       return;\r
+}\r
+\r
+UI_Task *task_alloc(void)\r
+{\r
+       int i;\r
+       UI_Task *task;\r
+       for(i = 0; i < MAX_TASKS; i++){\r
+               if(taskctl->tasks0[i].flags == initialized){\r
+                       task = &taskctl->tasks0[i];\r
+                       task->flags = allocated;\r
+                       task->tss.eflags = 0x00000202;\r
+                       task->tss.eax = 0;\r
+                       task->tss.ecx = 0;\r
+                       task->tss.edx = 0;\r
+                       task->tss.ebx = 0;\r
+                       task->tss.ebp = 0;\r
+                       task->tss.esi = 0;\r
+                       task->tss.edi = 0;\r
+                       task->tss.es = 0;\r
+                       task->tss.ds = 0;\r
+                       task->tss.fs = 0;\r
+                       task->tss.gs = 0;\r
+                       task->tss.ldtr = 0;\r
+                       task->tss.iomap = 0x40000000;\r
+                       task->tss.ss0 = 0;\r
+                       task->tss.cr3 = 0x00400000;\r
+                       return task;\r
+               }\r
+       }\r
+       return 0;\r
+}\r
+\r
+void task_run(UI_Task *task, int level, int priority)\r
+{\r
+       if(level < 0){\r
+               level = task->level;\r
+       }\r
+       if(priority > 0) {\r
+               task->priority = priority;\r
+       }\r
+       if(task->flags == inuse && task->level != level)task_remove(task);\r
+       if(task->flags != inuse){\r
+               task->level = level;\r
+               task_add(task);\r
+       }\r
+       taskctl->change_lv_next = true;\r
+       return;\r
+}\r
+\r
+void task_switch(void)\r
+{\r
+       UI_Task *new_task, *now_task = taskctl->level[taskctl->level_now].tasks[taskctl->level[taskctl->level_now].task_now];\r
+\r
+       taskctl->level[taskctl->level_now].task_now++;\r
+       if(taskctl->level[taskctl->level_now].task_now == taskctl->level[taskctl->level_now].running_tasks) taskctl->level[taskctl->level_now].task_now = 0;\r
+       if(taskctl->change_lv_next) task_switchsub();\r
+       new_task = taskctl->level[taskctl->level_now].tasks[taskctl->level[taskctl->level_now].task_now];\r
+       timer_settime(system.ui.timer.taskswitch, new_task->priority);\r
+       if(new_task != now_task){\r
+               farjmp(0, new_task->selector);\r
+       }\r
+       return;\r
+}\r
+\r
+void task_sleep(UI_Task *task)\r
+{\r
+       UI_Task *now_task;\r
+       int eflags;\r
+\r
+       eflags = io_load_eflags();\r
+       io_cli();\r
+\r
+       if(task->flags == inuse){\r
+               now_task = task_now();\r
+               task_remove(task);\r
+               if(task == now_task){\r
+                       task_switchsub();\r
+                       now_task = task_now();\r
+                       farjmp(0, now_task->selector);\r
+               }\r
+       }\r
+\r
+       io_store_eflags(eflags);\r
+\r
+       return;\r
+}\r
+\r
+void task_arguments(UI_Task *task, int args, ...)\r
+{\r
+       int i;\r
+       va_list ap;\r
+\r
+       va_start(ap, args);\r
+       \r
+       task->tss.esp -= 4 * (args + 1);\r
+\r
+       for(i = 1; i < args + 1; i++){\r
+               *((int *)(task->tss.esp + (i * 4))) = va_arg(ap, int);\r
+       }\r
+       va_end(ap);\r
+       return; \r
+}\r
+\r
+UI_Task *task_now(void)\r
+{\r
+       return taskctl->level[taskctl->level_now].tasks[taskctl->level[taskctl->level_now].task_now];\r
+}\r
+\r
+void task_add(UI_Task *task)\r
+{\r
+       taskctl->level[task->level].tasks[taskctl->level[task->level].running_tasks] = task;\r
+       taskctl->level[task->level].running_tasks++;\r
+       task->flags = inuse;\r
+       return; \r
+}\r
+\r
+void task_remove(UI_Task *task)\r
+{\r
+       int i;\r
+       for(i = 0; i < taskctl->level[task->level].running_tasks; i++){\r
+               if(taskctl->level[task->level].tasks[i] == task) break;\r
+       }\r
+       taskctl->level[task->level].running_tasks--;\r
+       if(i < taskctl->level[task->level].task_now) taskctl->level[task->level].task_now--;\r
+       if(taskctl->level[task->level].task_now >= taskctl->level[task->level].running_tasks) taskctl->level[task->level].task_now = 0;\r
+       task->flags = allocated;\r
+       for(; i < taskctl->level[task->level].running_tasks; i++){\r
+               taskctl->level[task->level].tasks[i] = taskctl->level[task->level].tasks[i + 1];\r
+       }\r
+       return;\r
+}\r
+\r
+void task_switchsub(void)\r
+{\r
+       int i;\r
+       for(i = 0; i < MAX_LEVELS; i++){\r
+               if(taskctl->level[i].running_tasks > 0) break;\r
+       }\r
+       taskctl->level_now = i;\r
+       taskctl->change_lv_next = false;\r
+       return;\r
+}\r
+\r
+void task_idle(void)\r
+{\r
+       for(;;){\r
+               io_hlt();\r
+       }\r
+}\r