Mercurial > hg > Members > kono > Cerium
comparison TaskManager/kernel/schedule/SchedTask.cc @ 619:0decff4e867b
RenewTask removal
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 15 Nov 2009 02:02:30 +0900 |
parents | 42c94f85c779 |
children | 60aa3f241b10 |
comparison
equal
deleted
inserted
replaced
618:360032cc500e | 619:0decff4e867b |
---|---|
8 #include "TaskManager.h" | 8 #include "TaskManager.h" |
9 #include <stdarg.h> | 9 #include <stdarg.h> |
10 | 10 |
11 extern Scheduler::TaskObject task_list[MAX_TASK_OBJECT]; | 11 extern Scheduler::TaskObject task_list[MAX_TASK_OBJECT]; |
12 | 12 |
13 //#define NO_PIPELINE | |
14 | |
15 /** | 13 /** |
16 Task Object を作る | 14 Task Object を作る |
17 */ | 15 */ |
18 | 16 |
19 | 17 |
44 inListData = NULL; | 42 inListData = NULL; |
45 outListData = NULL; | 43 outListData = NULL; |
46 readbuf = NULL; | 44 readbuf = NULL; |
47 writebuf = NULL; | 45 writebuf = NULL; |
48 scheduler = NULL; | 46 scheduler = NULL; |
49 taskGroup = NULL; | |
50 renew_flag = 0; | |
51 cur_index = 0; | 47 cur_index = 0; |
52 flag_renewTask = SCHED_TASK_NORMAL; | |
53 this->stdout_ = stdout; | 48 this->stdout_ = stdout; |
54 this->stderr_ = stderr; | 49 this->stderr_ = stderr; |
55 this->stdin_ = stdin; | 50 this->stdin_ = stdin; |
56 | 51 |
57 ex_init = &SchedTask::ex_init_normal; | |
58 ex_read = &SchedTask::ex_read_normal; | |
59 ex_exec = &SchedTask::ex_exec_normal; | |
60 ex_write = &SchedTask::ex_write_normal; | |
61 ex_next = &SchedTask::ex_next_normal; | |
62 | 52 |
63 } | 53 } |
64 | 54 |
65 /** | 55 /** |
66 * dma_store の wait を行う | 56 * dma_store の wait を行う |
67 */ | 57 */ |
68 SchedTask::~SchedTask() | 58 SchedTask::~SchedTask() |
69 { | 59 { |
70 if (flag_renewTask == SCHED_TASK_RENEW) { | 60 } |
71 /** | 61 |
72 * list != NULL の場合、 | |
73 * この Task が list の最後の Task になるので (SchedTask::next 参照) | |
74 * このタイミングで list を解放する | |
75 * (free に渡されるアドレスが正しいものとなる)。 | |
76 * それ以外の Task では当然解放しない。 | |
77 * list == NULL なので、free に渡しても無問題 | |
78 */ | |
79 free(list); | |
80 } | |
81 | |
82 | |
83 } | |
84 | |
85 /** | |
86 * このタスクを Renew Task とし、それに応じた関数をセットする | |
87 */ | |
88 void | |
89 SchedTask::setRenew() | |
90 { | |
91 flag_renewTask = SCHED_TASK_RENEW; | |
92 | |
93 ex_init = &SchedTask::ex_init_renew; | |
94 ex_read = &SchedTask::ex_read_renew; | |
95 ex_exec = &SchedTask::ex_exec_renew; | |
96 ex_write = &SchedTask::ex_write_renew; | |
97 ex_next = &SchedTask::ex_next_renew; | |
98 } | |
99 | 62 |
100 void | 63 void |
101 SchedTask::init(TaskListPtr _list, TaskPtr _task, int index, | 64 SchedTask::init(TaskListPtr _list, TaskPtr _task, int index, |
102 // ListDataPtr rbuf, ListDataPtr wbuf, | 65 // ListDataPtr rbuf, ListDataPtr wbuf, |
103 Scheduler* sc) | 66 Scheduler* sc) |
109 scheduler = sc; | 72 scheduler = sc; |
110 cur_index = index; | 73 cur_index = index; |
111 | 74 |
112 scheduler->mainMem_wait(); | 75 scheduler->mainMem_wait(); |
113 | 76 |
114 (this->*ex_init)(); | 77 } |
115 } | 78 |
116 | |
117 /** | |
118 * PPE 内で生成されたタスクの ex_init() | |
119 */ | |
120 void | |
121 SchedTask::ex_init_normal() | |
122 { | |
123 #if 0 | |
124 // task list に入れたので既に読んでいる? | |
125 // | |
126 scheduler->dma_load(inListData, (uint32)&task->inData, | |
127 sizeof(ListData), DMA_READ_IN_LIST); | |
128 scheduler->dma_load(outListData, (uint32)&task->outData, | |
129 sizeof(ListData), DMA_READ_OUT_LIST); | |
130 #if defined(NO_PIPELINE) | |
131 scheduler->dma_wait(DMA_READ_IN_LIST); | |
132 scheduler->dma_wait(DMA_READ_OUT_LIST); | |
133 #endif | |
134 #endif | |
135 | |
136 taskGroup = new TaskGroup; | |
137 taskGroup->command = (int)task->self; | |
138 } | |
139 | |
140 /** | |
141 * SPE 内で生成されたタスクの ex_init() | |
142 * 各データは SPE 内の create_task 時に生成もしくは引き継がれているので | |
143 * ex_init_normal() と違い、ここでは値を渡すだけ | |
144 */ | |
145 void | |
146 SchedTask::ex_init_renew() | |
147 { | |
148 inListData = &task->inData; | |
149 outListData = &task->outData; | |
150 taskGroup = (TaskGroupPtr)task->self; | |
151 } | |
152 | 79 |
153 void | 80 void |
154 SchedTask::read() | 81 SchedTask::read() |
155 { | 82 { |
156 __debug("[SchedTask:%s]\n", __FUNCTION__); | 83 __debug("[SchedTask:%s]\n", __FUNCTION__); |
157 | 84 |
158 #if 0 | |
159 #if !defined(NO_PIPELINE) | |
160 scheduler->dma_wait(DMA_READ_IN_LIST); | |
161 scheduler->dma_wait(DMA_READ_OUT_LIST); | |
162 #endif | |
163 #endif | |
164 // object creation をSchedTask生成時にやらないので、 | 85 // object creation をSchedTask生成時にやらないので、 |
165 // exec の直前のread で十分に間に合う | 86 // exec の直前のread で十分に間に合う |
166 if (cur_index < list->length) { | 87 if (cur_index < list->length) { |
167 // load next task | 88 // load next task |
168 loadSchedTask(scheduler, &list->tasks[cur_index]); | 89 loadSchedTask(scheduler, &list->tasks[cur_index]); |
175 | 96 |
176 // load Input Data | 97 // load Input Data |
177 readbuf = scheduler->allocate(inListData->size); | 98 readbuf = scheduler->allocate(inListData->size); |
178 scheduler->dma_loadList(inListData, readbuf, DMA_READ); | 99 scheduler->dma_loadList(inListData, readbuf, DMA_READ); |
179 | 100 |
180 #if defined(NO_PIPELINE) | 101 |
181 scheduler->dma_wait(DMA_READ); | 102 } |
182 #endif | 103 |
183 | |
184 (this->*ex_read)(); | |
185 } | |
186 | |
187 /** | |
188 * PPE 内で生成されたタスクの ex_read() | |
189 * | |
190 * [Todo] | |
191 * データの読み込み場所を readbuf ではなく、 | |
192 * ユーザ自身で決めれるようになるといいかもしれない。 | |
193 * | |
194 * # TaskManager が勝手に消すことなく、 | |
195 * # ユーザが SPE 上に持ち続けることができるため。 | |
196 * # もちろん管理はユーザに任せるわけだ。 | |
197 */ | |
198 void | |
199 SchedTask::ex_read_normal() | |
200 { | |
201 } | |
202 | 104 |
203 void | 105 void |
204 SchedTask::exec() | 106 SchedTask::exec() |
205 { | 107 { |
206 __debug("[SchedTask:%s]\n", __FUNCTION__); | 108 __debug("[SchedTask:%s]\n", __FUNCTION__); |
207 | 109 |
208 #if !defined(NO_PIPELINE) | |
209 scheduler->dma_wait(DMA_READ); | 110 scheduler->dma_wait(DMA_READ); |
210 task_list[task->command].wait(scheduler,task->command); | 111 task_list[task->command].wait(scheduler,task->command); |
211 #endif | |
212 | |
213 task_list[task->command].run(this, readbuf, writebuf); | 112 task_list[task->command].run(this, readbuf, writebuf); |
214 | |
215 free(readbuf); | 113 free(readbuf); |
216 | |
217 if (taskGroup->status() != 0) { | |
218 task->self = (int)taskGroup->command; | |
219 delete taskGroup; | |
220 taskGroup = NULL; | |
221 } | |
222 | |
223 | 114 |
224 // 書き込む領域がなければ無視 | 115 // 書き込む領域がなければ無視 |
225 if (outListData->length > 0) { | 116 if (outListData->length > 0) { |
226 scheduler->dma_storeList(outListData, writebuf, DMA_WRITE); | 117 scheduler->dma_storeList(outListData, writebuf, DMA_WRITE); |
227 | 118 } |
228 #if defined(NO_PIPELINE) | |
229 scheduler->dma_wait(DMA_WRITE); | |
230 free(writebuf); | |
231 #endif | |
232 } | |
233 | |
234 (this->*ex_exec)(); | |
235 } | 119 } |
236 | 120 |
237 void | 121 void |
238 SchedTask::write() | 122 SchedTask::write() |
239 { | 123 { |
240 __debug("[SchedTask:%s]\n", __FUNCTION__); | 124 __debug("[SchedTask:%s]\n", __FUNCTION__); |
241 | 125 |
242 #if !defined(NO_PIPELINE) | |
243 scheduler->dma_wait(DMA_WRITE); | 126 scheduler->dma_wait(DMA_WRITE); |
244 free(writebuf); | 127 free(writebuf); |
245 #endif | 128 |
246 | 129 scheduler->mail_write((int)task->self); |
247 if ((int)task->self == MY_SPE_NOP) return; | 130 } |
248 | 131 |
249 (this->*ex_write)(); | |
250 } | |
251 | |
252 | |
253 /** | |
254 * SPE 内で生成されたタスクの ex_read() | |
255 */ | |
256 void | |
257 SchedTask::ex_read_renew() | |
258 { | |
259 writebuf = scheduler->allocate(outListData->size); | |
260 } | |
261 | |
262 /** | |
263 * PPE 内で生成されたタスクの ex_exec() | |
264 */ | |
265 void | |
266 SchedTask::ex_exec_normal() | |
267 { | |
268 } | |
269 | |
270 /** | |
271 * SPE 内で生成されたタスクの ex_exec() | |
272 */ | |
273 void | |
274 SchedTask::ex_exec_renew() | |
275 { | |
276 } | |
277 | |
278 | |
279 | |
280 /** | |
281 * PPE 内で生成されたタスクの ex_write() | |
282 * | |
283 * このタスク内で新たにタスクが生成され、 | |
284 * 且つそのタスクの終了を待つ必要がある場合、 | |
285 * PPE に終了したことは知らせない(command は送信しない) | |
286 */ | |
287 void | |
288 SchedTask::ex_write_normal() | |
289 { | |
290 /** | |
291 * このタスク内で新たにタスクが生成されなかった | |
292 * or 生成されたが、そのタスクの終了を待つ必要は無い | |
293 */ | |
294 if (renew_flag == 0) { | |
295 scheduler->mail_write((int)task->self); | |
296 } | |
297 } | |
298 | |
299 /** | |
300 * SPE 内で生成されたタスクの ex_write() | |
301 * | |
302 * A <- 親タスク | |
303 * | \ | |
304 * B C <- SPE 内で生成されたタスク | |
305 * | |
306 * A は SPE 内で B, C を生成したとする。 | |
307 * B と C が終了したら、A が PPE に送るはずだったコマンドが | |
308 * 子タスクに引き継がれているので、最後に実行された子タスクが | |
309 * PPE に mail 送信する。 | |
310 */ | |
311 void | |
312 SchedTask::ex_write_renew() | |
313 { | |
314 uint32 cmd; | |
315 | |
316 taskGroup->remove(task); | |
317 cmd = taskGroup->status(); | |
318 | |
319 // タスク内で作られた全てのタスクが終了した | |
320 if (cmd != 0) { | |
321 delete taskGroup; | |
322 scheduler->mail_write(cmd); | |
323 } | |
324 } | |
325 | 132 |
326 SchedTaskBase* | 133 SchedTaskBase* |
327 SchedTask::next(Scheduler *scheduler, SchedTaskBase *p) | 134 SchedTask::next(Scheduler *scheduler, SchedTaskBase *p) |
328 { | 135 { |
329 __debug("[SchedTask:%s]\n", __FUNCTION__); | 136 __debug("[SchedTask:%s]\n", __FUNCTION__); |
330 | 137 |
331 // delete p; move to Scheduler | |
332 | |
333 return (this->*ex_next)(); | |
334 } | |
335 | |
336 SchedTaskBase* | |
337 SchedTask::ex_next_normal() | |
338 { | |
339 if (cur_index < list->length) { | 138 if (cur_index < list->length) { |
340 SchedTaskBase *nextSched; | 139 // Task List が残っているので、次を準備 |
341 | 140 |
342 nextSched = scheduler->get_nextRenewTaskList(); | 141 TaskPtr nextTask = &list->tasks[cur_index++]; |
343 | 142 SchedTaskBase *nextSched = createSchedTask(scheduler, nextTask); |
344 // RenewTask がある | 143 // この up cast は汚い... |
345 if (nextSched) { | 144 ((SchedTask*)nextSched)->init(list, nextTask, cur_index, |
346 scheduler->set_backupTaskList(list); | 145 scheduler); |
347 scheduler->set_backupTaskListIndex(cur_index); | 146 return nextSched; |
348 return nextSched; | |
349 } else { | |
350 TaskPtr nextTask = &list->tasks[cur_index++]; | |
351 nextSched = createSchedTask(scheduler, nextTask); | |
352 ((SchedTask*)nextSched)->init(list, nextTask, cur_index, | |
353 // scheduler->get_curReadBuf(), | |
354 // scheduler->get_curWriteBuf(), | |
355 scheduler); | |
356 return nextSched; | |
357 } | |
358 } else { | 147 } else { |
359 memaddr nextList = (memaddr)list->next; | 148 memaddr nextList = (memaddr)list->next; |
360 | |
361 if (nextList == 0) { | 149 if (nextList == 0) { |
150 // もう何もする必要がない | |
362 return new SchedNop2Ready(scheduler); | 151 return new SchedNop2Ready(scheduler); |
363 } else { | 152 } else { |
153 // 新しいリストに取り掛かる | |
364 return createSchedTaskList(nextList, scheduler, | 154 return createSchedTaskList(nextList, scheduler, |
365 SCHED_TASKLIST_NORMAL); | 155 SCHED_TASKLIST_NORMAL); |
366 } | 156 } |
367 } | 157 } |
368 } | 158 } |
369 | 159 |
370 /** | |
371 * | |
372 */ | |
373 SchedTaskBase* | |
374 SchedTask::ex_next_renew() | |
375 { | |
376 TaskPtr nextTask; | |
377 SchedTask *nextSched; | |
378 | |
379 if (cur_index < list->length) { | |
380 nextTask = &list->tasks[cur_index++]; | |
381 nextSched = createSchedTask(scheduler, nextTask); | |
382 | |
383 // RenewTaskList を実行中なので | |
384 nextSched->setRenew(); | |
385 nextSched->init(list, nextTask, cur_index, | |
386 // scheduler->get_curReadBuf(), | |
387 // scheduler->get_curWriteBuf(), | |
388 scheduler); | |
389 | |
390 /** | |
391 * この理由は SchedTask:~SchedTask() で | |
392 */ | |
393 list = NULL; | |
394 return nextSched; | |
395 } else { | |
396 SchedTaskBase *nextList; | |
397 | |
398 nextList = scheduler->get_nextRenewTaskList(); | |
399 | |
400 if (nextList) { | |
401 return nextList; | |
402 } else { | |
403 TaskListPtr nextList = scheduler->get_backupTaskList(); | |
404 | |
405 // 中断した TaskList がある | |
406 if (nextList) { | |
407 cur_index = scheduler->get_backupTaskListIndex(); | |
408 | |
409 nextTask = &nextList->tasks[cur_index++]; | |
410 nextSched = createSchedTask(scheduler, nextTask); | |
411 | |
412 nextSched->init(nextList, nextTask, cur_index, | |
413 // scheduler->get_curReadBuf(), | |
414 // scheduler->get_curWriteBuf(), | |
415 scheduler); | |
416 return nextSched; | |
417 } else { | |
418 return new SchedNop2Ready(scheduler); | |
419 } | |
420 } | |
421 } | |
422 } | |
423 | 160 |
424 int | 161 int |
425 SchedTask::get_cpuid() | 162 SchedTask::get_cpuid() |
426 { | 163 { |
427 return scheduler->id; | 164 return scheduler->id; |
494 SchedTask::get_param(int index) | 231 SchedTask::get_param(int index) |
495 { | 232 { |
496 return task->param[index]; | 233 return task->param[index]; |
497 } | 234 } |
498 | 235 |
499 TaskPtr | |
500 SchedTask::create_task(int cmd) | |
501 { | |
502 TaskListPtr taskList = scheduler->get_renewListBuf(); | |
503 TaskPtr p = &taskList->tasks[taskList->length++]; | |
504 p->command = cmd; | |
505 | |
506 // already allocated | |
507 // p->inData = (ListData*)scheduler->allocate(sizeof(ListData)); | |
508 // p->outData = (ListData*)scheduler->allocate(sizeof(ListData)); | |
509 | |
510 p->inData.clear(); | |
511 p->outData.clear(); | |
512 | |
513 p->self = (int)MY_SPE_NOP; | |
514 p->param_size = 0; | |
515 | |
516 return p; | |
517 } | |
518 | |
519 /** | |
520 * | |
521 * @param[in] waitTask タスク内で生成したタスクの登録(spawn()に相当) | |
522 */ | |
523 void | |
524 SchedTask::wait_task(TaskPtr waitTask) | |
525 { | |
526 waitTask->self = (memaddr)taskGroup; | |
527 | |
528 scheduler->add_groupTask(taskGroup, waitTask); | |
529 | |
530 renew_flag++; | |
531 } | |
532 | 236 |
533 void* | 237 void* |
534 SchedTask::global_alloc(int id, int size) { | 238 SchedTask::global_alloc(int id, int size) { |
535 return scheduler->global_alloc(id, size); | 239 return scheduler->global_alloc(id, size); |
536 } | 240 } |
568 void* | 272 void* |
569 SchedTask::mainMem_get(int id) { | 273 SchedTask::mainMem_get(int id) { |
570 return scheduler->mainMem_get(id); | 274 return scheduler->mainMem_get(id); |
571 } | 275 } |
572 | 276 |
573 void* | |
574 SchedTask::allocate(int size) { | |
575 return scheduler->allocate(size); | |
576 } | |
577 | |
578 | 277 |
579 void | 278 void |
580 SchedTask::dma_load(void *buf, uint32 addr, uint32 size, uint32 mask) { | 279 SchedTask::dma_load(void *buf, uint32 addr, uint32 size, uint32 mask) { |
581 scheduler->dma_load(buf, addr, size, mask); | 280 scheduler->dma_load(buf, addr, size, mask); |
582 } | 281 } |
604 scheduler->put_segment(s); | 303 scheduler->put_segment(s); |
605 } | 304 } |
606 | 305 |
607 void SchedTask::wait_segment(MemorySegment *s) { | 306 void SchedTask::wait_segment(MemorySegment *s) { |
608 scheduler->wait_segment(s); | 307 scheduler->wait_segment(s); |
308 } | |
309 | |
310 | |
311 HTaskPtr SchedTask::create_task(int cmd) | |
312 { | |
313 return scheduler->create_task(cmd); | |
314 } | |
315 | |
316 void SchedTask::set_task_depend(HTaskPtr master, HTaskPtr slave) | |
317 { | |
318 scheduler->set_task_depend(master, slave); | |
319 } | |
320 | |
321 void SchedTask::spawn_task(HTaskPtr t) | |
322 { | |
323 scheduler->spawn_task(t); | |
324 } | |
325 | |
326 void SchedTask::set_task_cpu(HTaskPtr t, CPU_TYPE cpu) | |
327 { | |
328 scheduler->set_task_cpu(t, cpu); | |
329 } | |
330 | |
331 void* SchedTask::allocate(int size) | |
332 { | |
333 return scheduler->allocate(size) ; | |
334 } | |
335 | |
336 void* SchedTask::allocate(int size,int align) | |
337 { | |
338 return scheduler->allocate(size,align) ; | |
339 } | |
340 | |
341 Scheduler* SchedTask::get_scheduler() | |
342 { | |
343 return scheduler; | |
609 } | 344 } |
610 | 345 |
611 /* system call */ | 346 /* system call */ |
612 | 347 |
613 int | 348 int |