OSDN Git Service

first commit
[winexe-harib/winexe-harib.git] / haribote / mtask.c
1 /* \83}\83\8b\83`\83^\83X\83N\8aÖ\8cW */
2
3 #include "bootpack.h"
4
5 struct TASKCTL *taskctl;
6 struct TIMER *task_timer;
7
8 struct TASK *task_now(void)
9 {
10         struct TASKLEVEL *tl = &taskctl->level[taskctl->now_lv];
11         return tl->tasks[tl->now];
12 }
13
14 void task_add(struct TASK *task)
15 {
16         struct TASKLEVEL *tl = &taskctl->level[task->level];
17         tl->tasks[tl->running] = task;
18         tl->running++;
19         task->flags = 2; /* \93®\8dì\92\86 */
20         return;
21 }
22
23 void task_remove(struct TASK *task)
24 {
25         int i;
26         struct TASKLEVEL *tl = &taskctl->level[task->level];
27
28         /* task\82ª\82Ç\82±\82É\82¢\82é\82©\82ð\92T\82· */
29         for (i = 0; i < tl->running; i++) {
30                 if (tl->tasks[i] == task) {
31                         /* \82±\82±\82É\82¢\82½ */
32                         break;
33                 }
34         }
35
36         tl->running--;
37         if (i < tl->now) {
38                 tl->now--; /* \82¸\82ê\82é\82Ì\82Å\81A\82±\82ê\82à\82 \82í\82¹\82Ä\82¨\82­ */
39         }
40         if (tl->now >= tl->running) {
41                 /* now\82ª\82¨\82©\82µ\82È\92l\82É\82È\82Á\82Ä\82¢\82½\82ç\81A\8fC\90³\82·\82é */
42                 tl->now = 0;
43         }
44         task->flags = 1; /* \83X\83\8a\81[\83v\92\86 */
45
46         /* \82¸\82ç\82µ */
47         for (; i < tl->running; i++) {
48                 tl->tasks[i] = tl->tasks[i + 1];
49         }
50
51         return;
52 }
53
54 void task_switchsub(void)
55 {
56         int i;
57         /* \88ê\94Ô\8fã\82Ì\83\8c\83x\83\8b\82ð\92T\82· */
58         for (i = 0; i < MAX_TASKLEVELS; i++) {
59                 if (taskctl->level[i].running > 0) {
60                         break; /* \8c©\82Â\82©\82Á\82½ */
61                 }
62         }
63         taskctl->now_lv = i;
64         taskctl->lv_change = 0;
65         return;
66 }
67
68 void task_idle(void)
69 {
70         for (;;) {
71                 io_hlt();
72         }
73 }
74
75 struct TASK *task_init(struct MEMMAN *memman)
76 {
77         int i;
78         struct TASK *task, *idle;
79         struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
80
81         taskctl = (struct TASKCTL *) memman_alloc_4k(memman, sizeof (struct TASKCTL));
82         for (i = 0; i < MAX_TASKS; i++) {
83                 taskctl->tasks0[i].flags = 0;
84                 taskctl->tasks0[i].sel = (TASK_GDT0 + i) * 8;
85                 taskctl->tasks0[i].tss.ldtr = (TASK_GDT0 + MAX_TASKS + i) * 8;
86                 set_segmdesc(gdt + TASK_GDT0 + i, 103, (int) &taskctl->tasks0[i].tss, AR_TSS32);
87                 set_segmdesc(gdt + TASK_GDT0 + MAX_TASKS + i, 15, (int) taskctl->tasks0[i].ldt, AR_LDT);
88         }
89         for (i = 0; i < MAX_TASKLEVELS; i++) {
90                 taskctl->level[i].running = 0;
91                 taskctl->level[i].now = 0;
92         }
93
94         task = task_alloc();
95         task->flags = 2;        /* \93®\8dì\92\86\83}\81[\83N */
96         task->priority = 2; /* 0.02\95b */
97         task->level = 0;        /* \8dÅ\8d\82\83\8c\83x\83\8b */
98         task_add(task);
99         task_switchsub();       /* \83\8c\83x\83\8b\90Ý\92è */
100         load_tr(task->sel);
101         task_timer = timer_alloc();
102         timer_settime(task_timer, task->priority);
103
104         idle = task_alloc();
105         idle->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024;
106         idle->tss.eip = (int) &task_idle;
107         idle->tss.es = 1 * 8;
108         idle->tss.cs = 2 * 8;
109         idle->tss.ss = 1 * 8;
110         idle->tss.ds = 1 * 8;
111         idle->tss.fs = 1 * 8;
112         idle->tss.gs = 1 * 8;
113         task_run(idle, MAX_TASKLEVELS - 1, 1);
114
115         return task;
116 }
117
118 struct TASK *task_alloc(void)
119 {
120         int i;
121         struct TASK *task;
122         for (i = 0; i < MAX_TASKS; i++) {
123                 if (taskctl->tasks0[i].flags == 0) {
124                         task = &taskctl->tasks0[i];
125                         task->flags = 1; /* \8eg\97p\92\86\83}\81[\83N */
126                         task->tss.eflags = 0x00000202; /* IF = 1; */
127                         task->tss.eax = 0; /* \82Æ\82è\82 \82¦\82¸0\82É\82µ\82Ä\82¨\82­\82±\82Æ\82É\82·\82é */
128                         task->tss.ecx = 0;
129                         task->tss.edx = 0;
130                         task->tss.ebx = 0;
131                         task->tss.ebp = 0;
132                         task->tss.esi = 0;
133                         task->tss.edi = 0;
134                         task->tss.es = 0;
135                         task->tss.ds = 0;
136                         task->tss.fs = 0;
137                         task->tss.gs = 0;
138                         task->tss.iomap = 0x40000000;
139                         task->tss.ss0 = 0;
140                         return task;
141                 }
142         }
143         return 0; /* \82à\82¤\91S\95\94\8eg\97p\92\86 */
144 }
145
146 void task_run(struct TASK *task, int level, int priority)
147 {
148         if (level < 0) {
149                 level = task->level; /* \83\8c\83x\83\8b\82ð\95Ï\8dX\82µ\82È\82¢ */
150         }
151         if (priority > 0) {
152                 task->priority = priority;
153         }
154
155         if (task->flags == 2 && task->level != level) { /* \93®\8dì\92\86\82Ì\83\8c\83x\83\8b\82Ì\95Ï\8dX */
156                 task_remove(task); /* \82±\82ê\82ð\8eÀ\8ds\82·\82é\82Æflags\82Í1\82É\82È\82é\82Ì\82Å\89º\82Ìif\82à\8eÀ\8ds\82³\82ê\82é */
157         }
158         if (task->flags != 2) {
159                 /* \83X\83\8a\81[\83v\82©\82ç\8bN\82±\82³\82ê\82é\8fê\8d\87 */
160                 task->level = level;
161                 task_add(task);
162         }
163
164         taskctl->lv_change = 1; /* \8e\9f\89ñ\83^\83X\83N\83X\83C\83b\83`\82Ì\82Æ\82«\82É\83\8c\83x\83\8b\82ð\8c©\92¼\82· */
165         return;
166 }
167
168 void task_sleep(struct TASK *task)
169 {
170         struct TASK *now_task;
171         if (task->flags == 2) {
172                 /* \93®\8dì\92\86\82¾\82Á\82½\82ç */
173                 now_task = task_now();
174                 task_remove(task); /* \82±\82ê\82ð\8eÀ\8ds\82·\82é\82Æflags\82Í1\82É\82È\82é */
175                 if (task == now_task) {
176                         /* \8e©\95ª\8e©\90g\82Ì\83X\83\8a\81[\83v\82¾\82Á\82½\82Ì\82Å\81A\83^\83X\83N\83X\83C\83b\83`\82ª\95K\97v */
177                         task_switchsub();
178                         now_task = task_now(); /* \90Ý\92è\8cã\82Å\82Ì\81A\81u\8c»\8dÝ\82Ì\83^\83X\83N\81v\82ð\8b³\82¦\82Ä\82à\82ç\82¤ */
179                         farjmp(0, now_task->sel);
180                 }
181         }
182         return;
183 }
184
185 void task_switch(void)
186 {
187         struct TASKLEVEL *tl = &taskctl->level[taskctl->now_lv];
188         struct TASK *new_task, *now_task = tl->tasks[tl->now];
189         tl->now++;
190         if (tl->now == tl->running) {
191                 tl->now = 0;
192         }
193         if (taskctl->lv_change != 0) {
194                 task_switchsub();
195                 tl = &taskctl->level[taskctl->now_lv];
196         }
197         new_task = tl->tasks[tl->now];
198         timer_settime(task_timer, new_task->priority);
199         if (new_task != now_task) {
200                 farjmp(0, new_task->sel);
201         }
202         return;
203 }