Mercurial > hg > Members > kono > Cerium
annotate TaskManager/kernel/schedule/SchedTask.cc @ 387:5e2d30bfbf23
no compile error but not worked.
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 06 Aug 2009 22:40:52 +0900 |
parents | eab18aa0c7f6 |
children | 8c5fa57128cb |
rev | line source |
---|---|
308 | 1 #include <stdlib.h> |
2 #include <string.h> | |
42 | 3 #include "SchedTask.h" |
308 | 4 #include "SchedTaskList.h" |
5 #include "SchedNop2Ready.h" | |
6 #include "DmaManager.h" | |
7 #include "error.h" | |
8 #include "TaskManager.h" | |
180
5cde66c926b4
いろいろ fix 。詳しくは TaskManager/Changelog、test_render/Changelog を
gongo@localhost.localdomain
parents:
109
diff
changeset
|
9 |
308 | 10 extern Scheduler::TaskObject task_list[MAX_TASK_OBJECT]; |
11 | |
373 | 12 //#define NO_PIPELINE |
308 | 13 |
14 SchedTask * | |
302 | 15 createSchedTask(TaskPtr task) |
16 { | |
308 | 17 return task_list[task->command](); |
18 } | |
19 | |
373 | 20 |
308 | 21 SchedTask::SchedTask() |
22 { | |
23 __list = NULL; | |
24 __task = NULL; | |
25 __inListData = NULL; | |
26 __outListData = NULL; | |
27 __readbuf = NULL; | |
28 __writebuf = NULL; | |
29 __scheduler = NULL; | |
30 __taskGroup = NULL; | |
31 __renew_flag = 0; | |
32 __cur_index = 0; | |
33 __flag_renewTask = SCHED_TASK_NORMAL; | |
373 | 34 |
308 | 35 ex_init = &SchedTask::ex_init_normal; |
36 ex_read = &SchedTask::ex_read_normal; | |
37 ex_exec = &SchedTask::ex_exec_normal; | |
38 ex_write = &SchedTask::ex_write_normal; | |
39 ex_next = &SchedTask::ex_next_normal; | |
40 | |
41 run_func = &SchedTask::run; | |
373 | 42 run_func1 = &SchedTask::run; |
308 | 43 } |
44 | |
45 /** | |
46 * dma_store の wait を行う | |
47 * このタスクが RenewTask だった場合、 | |
48 * __inListData や __outListData は | |
49 * Scheduler の持つ、使い回しの buffer ではなく | |
50 * 新たに allocate されたものなので、ここで free する | |
51 */ | |
52 SchedTask::~SchedTask(void) | |
53 { | |
54 if (__flag_renewTask == SCHED_TASK_RENEW) { | |
373 | 55 free(__inListData); |
308 | 56 free(__outListData); |
373 | 57 |
58 /** | |
59 * __list != NULL の場合、 | |
60 * この Task が __list の最後の Task になるので (SchedTask::next 参照) | |
61 * このタイミングで __list を解放する | |
62 * (free に渡されるアドレスが正しいものとなる)。 | |
63 * それ以外の Task では当然解放しない。 | |
64 * __list == NULL なので、free に渡しても無問題 | |
65 */ | |
66 free(__list); | |
308 | 67 } |
68 | |
321 | 69 |
308 | 70 } |
71 | |
373 | 72 /** |
308 | 73 * このタスクを Renew Task とし、それに応じた関数をセットする |
74 */ | |
75 void | |
76 SchedTask::__setRenew(void) | |
77 { | |
78 __flag_renewTask = SCHED_TASK_RENEW; | |
79 | |
80 ex_init = &SchedTask::ex_init_renew; | |
81 ex_read = &SchedTask::ex_read_renew; | |
82 ex_exec = &SchedTask::ex_exec_renew; | |
373 | 83 ex_write = &SchedTask::ex_write_renew; |
308 | 84 ex_next = &SchedTask::ex_next_renew; |
85 } | |
86 | |
87 void | |
88 SchedTask::__init__(TaskListPtr _list, TaskPtr _task, int index, | |
373 | 89 ListDataPtr rbuf, ListDataPtr wbuf, Scheduler* sc) |
308 | 90 { |
91 __list = _list; | |
92 __task = _task; | |
93 __inListData = rbuf; | |
94 __outListData = wbuf; | |
95 __scheduler = sc; | |
96 __cur_index = index; | |
97 | |
311
b09784a9cb09
add smanager interface for test_nogl
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
310
diff
changeset
|
98 smanager = this; |
308 | 99 |
100 __scheduler->mainMem_wait(); | |
101 | |
102 (this->*ex_init)(); | |
103 } | |
104 | |
105 /** | |
106 * PPE 内で生成されたタスクの ex_init() | |
107 */ | |
108 void | |
109 SchedTask::ex_init_normal(void) | |
110 { | |
111 __scheduler->dma_load(__inListData, (uint32)__task->inData, | |
373 | 112 sizeof(ListData), DMA_READ_IN_LIST); |
308 | 113 __scheduler->dma_load(__outListData, (uint32)__task->outData, |
373 | 114 sizeof(ListData), DMA_READ_OUT_LIST); |
308 | 115 #if defined(NO_PIPELINE) |
116 __scheduler->dma_wait(DMA_READ_IN_LIST); | |
117 __scheduler->dma_wait(DMA_READ_OUT_LIST); | |
118 #endif | |
373 | 119 |
308 | 120 __taskGroup = new TaskGroup; |
121 __taskGroup->command = __task->self; | |
122 } | |
123 | |
124 /** | |
125 * SPE 内で生成されたタスクの ex_init() | |
126 * 各データは SPE 内の create_task 時に生成もしくは引き継がれているので | |
127 * ex_init_normal() と違い、ここでは値を渡すだけ | |
128 */ | |
129 void | |
130 SchedTask::ex_init_renew(void) | |
131 { | |
132 __inListData = __task->inData; | |
133 __outListData = __task->outData; | |
373 | 134 __taskGroup = (TaskGroupPtr)__task->self; |
308 | 135 } |
136 | |
137 /** | |
138 * [Todo] | |
139 * データの読み込み場所を readbuf ではなく、 | |
140 * ユーザ自身で決めれるようになるといいかもしれない。 | |
141 * | |
142 * # TaskManager が勝手に消すことなく、 | |
143 * # ユーザが SPE 上に持ち続けることができるため。 | |
144 * # もちろん管理はユーザに任せるわけだ。 | |
145 */ | |
146 void | |
147 SchedTask::read(void) | |
373 | 148 { |
308 | 149 __debug("[SchedTask:%s]\n", __FUNCTION__); |
150 | |
151 #if !defined(NO_PIPELINE) | |
152 __scheduler->dma_wait(DMA_READ_IN_LIST); | |
153 __scheduler->dma_wait(DMA_READ_OUT_LIST); | |
154 #endif | |
155 | |
156 __writebuf = __scheduler->allocate(__outListData->size); | |
373 | 157 |
308 | 158 // 読むデータが一つもなければ無視 |
159 if (__inListData->length == 0) return; | |
160 | |
161 // load Input Data | |
162 __readbuf = __scheduler->allocate(__inListData->size); | |
163 __scheduler->dma_loadList(__inListData, __readbuf, DMA_READ); | |
164 | |
165 #if defined(NO_PIPELINE) | |
166 __scheduler->dma_wait(DMA_READ); | |
167 #endif | |
168 | |
169 (this->*ex_read)(); | |
170 } | |
171 | |
172 void | |
173 SchedTask::exec(void) | |
174 { | |
175 __debug("[SchedTask:%s]\n", __FUNCTION__); | |
176 | |
177 #if !defined(NO_PIPELINE) | |
178 __scheduler->dma_wait(DMA_READ); | |
179 #endif | |
180 | |
181 //run(__readbuf, __writebuf); | |
182 (this->*run_func)(__readbuf, __writebuf); | |
316 | 183 (this->*run_func1)(this, __readbuf, __writebuf); |
308 | 184 |
185 free(__readbuf); | |
186 | |
187 if (__taskGroup->status() != 0) { | |
373 | 188 __task->self = __taskGroup->command; |
189 delete __taskGroup; | |
190 __taskGroup = NULL; | |
308 | 191 } |
192 | |
193 | |
194 // 書き込む領域がなければ無視 | |
195 if (__outListData->length > 0) { | |
373 | 196 __scheduler->dma_storeList(__outListData, __writebuf, DMA_WRITE); |
308 | 197 |
198 #if defined(NO_PIPELINE) | |
373 | 199 __scheduler->dma_wait(DMA_WRITE); |
200 free(__writebuf); | |
308 | 201 #endif |
202 } | |
203 | |
204 (this->*ex_exec)(); | |
205 } | |
206 | |
207 void | |
208 SchedTask::write(void) | |
209 { | |
210 __debug("[SchedTask:%s]\n", __FUNCTION__); | |
373 | 211 |
308 | 212 #if !defined(NO_PIPELINE) |
213 __scheduler->dma_wait(DMA_WRITE); | |
214 free(__writebuf); | |
215 #endif | |
216 | |
217 if (__task->self == MY_SPE_NOP) return; | |
218 | |
219 (this->*ex_write)(); | |
220 } | |
221 | |
222 /** | |
223 * PPE 内で生成されたタスクの ex_read() | |
224 */ | |
225 void | |
226 SchedTask::ex_read_normal(void) | |
227 { | |
228 } | |
229 | |
230 /** | |
231 * SPE 内で生成されたタスクの ex_read() | |
232 */ | |
233 void | |
234 SchedTask::ex_read_renew(void) | |
235 { | |
236 } | |
237 | |
238 /** | |
239 * PPE 内で生成されたタスクの ex_exec() | |
240 */ | |
241 void | |
242 SchedTask::ex_exec_normal(void) | |
243 { | |
244 } | |
245 | |
246 /** | |
247 * SPE 内で生成されたタスクの ex_exec() | |
248 */ | |
249 void | |
250 SchedTask::ex_exec_renew(void) | |
251 { | |
252 } | |
253 | |
254 | |
255 | |
256 /** | |
257 * PPE 内で生成されたタスクの ex_write() | |
373 | 258 * |
308 | 259 * このタスク内で新たにタスクが生成され、 |
260 * 且つそのタスクの終了を待つ必要がある場合、 | |
261 * PPE に終了したことは知らせない(command は送信しない) | |
262 */ | |
263 void | |
264 SchedTask::ex_write_normal(void) | |
265 { | |
266 /** | |
267 * このタスク内で新たにタスクが生成されなかった | |
268 * or 生成されたが、そのタスクの終了を待つ必要は無い | |
269 */ | |
270 if (__renew_flag == 0) { | |
373 | 271 __scheduler->mail_write(__task->self); |
308 | 272 } |
302 | 273 } |
274 | |
308 | 275 /** |
276 * SPE 内で生成されたタスクの ex_write() | |
277 * | |
278 * A <- 親タスク | |
279 * | \ | |
280 * B C <- SPE 内で生成されたタスク | |
281 * | |
282 * A は SPE 内で B, C を生成したとする。 | |
283 * B と C が終了したら、A が PPE に送るはずだったコマンドが | |
284 * 子タスクに引き継がれているので、最後に実行された子タスクが | |
285 * PPE に mail 送信する。 | |
286 */ | |
287 void | |
288 SchedTask::ex_write_renew(void) | |
289 { | |
290 uint32 cmd; | |
373 | 291 |
308 | 292 __taskGroup->remove(__task); |
373 | 293 cmd = __taskGroup->status(); |
308 | 294 |
295 // タスク内で作られた全てのタスクが終了した | |
296 if (cmd != 0) { | |
373 | 297 delete __taskGroup; |
298 __scheduler->mail_write(cmd); | |
308 | 299 } |
300 } | |
373 | 301 |
308 | 302 SchedTaskBase* |
303 SchedTask::next(Scheduler *m, SchedTaskBase *p) | |
304 { | |
305 __debug("[SchedTask:%s]\n", __FUNCTION__); | |
306 | |
307 delete p; | |
308 | |
309 return (this->*ex_next)(); | |
310 } | |
311 | |
312 SchedTaskBase* | |
313 SchedTask::ex_next_normal(void) | |
314 { | |
315 if (__cur_index < __list->length) { | |
373 | 316 SchedTaskBase *nextSched; |
317 | |
318 nextSched = __scheduler->get_nextRenewTaskList(); | |
308 | 319 |
373 | 320 // RenewTask がある |
321 if (nextSched) { | |
322 __scheduler->set_backupTaskList(__list); | |
323 __scheduler->set_backupTaskListIndex(__cur_index); | |
324 return nextSched; | |
325 } else { | |
326 TaskPtr nextTask = &__list->tasks[__cur_index++]; | |
327 nextSched = createSchedTask(nextTask); | |
328 ((SchedTask*)nextSched)->__init__(__list, nextTask, __cur_index, | |
329 __scheduler->get_curReadBuf(), | |
330 __scheduler->get_curWriteBuf(), | |
331 __scheduler); | |
332 return nextSched; | |
333 } | |
308 | 334 } else { |
373 | 335 uint32 nextList = (uint32)__list->next; |
336 | |
337 if (nextList == 0) { | |
338 return new SchedNop2Ready(__scheduler); | |
339 } else { | |
340 return createSchedTaskList(nextList, __scheduler, | |
341 SCHED_TASKLIST_NORMAL); | |
342 } | |
308 | 343 } |
344 } | |
345 | |
346 /** | |
347 * | |
348 */ | |
349 SchedTaskBase* | |
350 SchedTask::ex_next_renew(void) | |
351 { | |
352 TaskPtr nextTask; | |
353 SchedTask *nextSched; | |
354 | |
355 if (__cur_index < __list->length) { | |
373 | 356 nextTask = &__list->tasks[__cur_index++]; |
357 nextSched = createSchedTask(nextTask); | |
308 | 358 |
373 | 359 // RenewTaskList を実行中なので |
360 nextSched->__setRenew(); | |
361 nextSched->__init__(__list, nextTask, __cur_index, | |
362 __scheduler->get_curReadBuf(), | |
363 __scheduler->get_curWriteBuf(), | |
364 __scheduler); | |
308 | 365 |
373 | 366 /** |
367 * この理由は SchedTask:~SchedTask() で | |
368 */ | |
369 __list = NULL; | |
370 return nextSched; | |
308 | 371 } else { |
373 | 372 SchedTaskBase *nextList; |
373 | |
374 nextList = __scheduler->get_nextRenewTaskList(); | |
375 | |
376 if (nextList) { | |
377 return nextList; | |
378 } else { | |
379 TaskListPtr nextList = __scheduler->get_backupTaskList(); | |
380 | |
381 // 中断した TaskList がある | |
382 if (nextList) { | |
383 __cur_index = __scheduler->get_backupTaskListIndex(); | |
308 | 384 |
373 | 385 nextTask = &nextList->tasks[__cur_index++]; |
386 nextSched = createSchedTask(nextTask); | |
387 | |
388 nextSched->__init__(nextList, nextTask, __cur_index, | |
389 __scheduler->get_curReadBuf(), | |
390 __scheduler->get_curWriteBuf(), | |
391 __scheduler); | |
392 return nextSched; | |
393 } else { | |
394 return new SchedNop2Ready(__scheduler); | |
395 } | |
396 } | |
308 | 397 } |
398 } | |
399 | |
400 int | |
401 SchedTask::get_cpuid(void) | |
402 { | |
403 return __scheduler->id; | |
404 } | |
405 | |
406 /** | |
407 * task->add_inData で与えられた順番に対応する index (0〜n-1) で、 | |
408 * buffer から対応するデータを返す。 | |
409 */ | |
410 void* | |
411 SchedTask::get_input(void *buff, int index) | |
412 { | |
413 if (buff != NULL) { | |
373 | 414 return (void*)((int)buff + __inListData->bound[index]); |
308 | 415 } else { |
373 | 416 return NULL; |
308 | 417 } |
418 } | |
419 | |
420 /** | |
421 * get_input(index) のアドレスを返す | |
422 */ | |
423 uint32 | |
424 SchedTask::get_inputAddr(int index) | |
425 { | |
426 return __inListData->element[index].addr; | |
427 } | |
428 | |
429 /** | |
430 * get_input(index) のサイズを返す | |
431 */ | |
432 int | |
433 SchedTask::get_inputSize(int index) | |
434 { | |
435 return __inListData->element[index].size; | |
436 } | |
437 | |
438 /** | |
439 * write buffer の領域を返す。 | |
440 */ | |
441 void* | |
442 SchedTask::get_output(void *buff, int index) | |
443 { | |
444 if (buff != NULL) { | |
373 | 445 return (void*)((int)buff + __outListData->bound[index]); |
308 | 446 } else { |
373 | 447 return NULL; |
308 | 448 } |
449 } | |
450 | |
451 /** | |
452 * get_output(index) のアドレスを返す | |
453 */ | |
454 uint32 | |
455 SchedTask::get_outputAddr(int index) | |
456 { | |
457 return __outListData->element[index].addr; | |
458 } | |
459 | |
460 /** | |
461 * get_output(index) のサイズを返す | |
462 */ | |
463 int | |
464 SchedTask::get_outputSize(int index) | |
465 { | |
466 return __outListData->element[index].size; | |
467 } | |
468 | |
469 int | |
470 SchedTask::get_param(int index) | |
471 { | |
472 return __task->param[index]; | |
473 } | |
474 | |
475 TaskPtr | |
476 SchedTask::create_task(int cmd) | |
477 { | |
478 TaskListPtr taskList = __scheduler->get_renewListBuf(); | |
479 TaskPtr p = &taskList->tasks[taskList->length++]; | |
480 p->command = cmd; | |
481 | |
482 p->inData = (ListData*)__scheduler->allocate(sizeof(ListData)); | |
483 p->outData = (ListData*)__scheduler->allocate(sizeof(ListData)); | |
484 | |
485 p->inData->clear(); | |
486 p->outData->clear(); | |
487 | |
488 p->self = MY_SPE_NOP; | |
489 p->param_size = 0; | |
490 | |
491 return p; | |
492 } | |
493 | |
494 /** | |
495 * 生成したタスクが終了してから、メインスケジューラ(PPE) に | |
496 * タスクが終了した旨を知らせる。 | |
497 * | |
498 * @param[in] waitTask タスク内で生成したタスク | |
499 */ | |
500 void | |
501 SchedTask::wait_task(TaskPtr waitTask) | |
502 { | |
503 waitTask->self = (uint32)__taskGroup; | |
504 | |
505 __scheduler->add_groupTask(__taskGroup, waitTask); | |
506 | |
507 __renew_flag++; | |
508 } | |
509 | |
510 void* | |
511 SchedTask::global_alloc(int id, int size) { | |
512 return __scheduler->global_alloc(id, size); | |
513 } | |
514 | |
515 void* | |
516 SchedTask::global_get(int id) { | |
517 return __scheduler->global_get(id); | |
518 } | |
519 | |
520 void | |
373 | 521 SchedTask::global_set(int id, void *addr) { |
522 __scheduler->global_set(id, addr); | |
523 } | |
524 | |
525 void | |
308 | 526 SchedTask::global_free(int id) { |
527 __scheduler->global_free(id); | |
528 } | |
529 | |
373 | 530 MemList* |
531 SchedTask::createMemList(int size, int count) { | |
532 return __scheduler->createMemList(size, count); | |
533 } | |
534 | |
308 | 535 void |
536 SchedTask::mainMem_alloc(int id, int size) { | |
537 __scheduler->mainMem_alloc(id, size); | |
538 } | |
539 | |
540 void | |
541 SchedTask::mainMem_wait(void) { | |
542 __scheduler->mainMem_wait(); | |
543 } | |
544 | |
545 void* | |
546 SchedTask::mainMem_get(int id) { | |
547 return __scheduler->mainMem_get(id); | |
548 } | |
549 | |
550 void* | |
551 SchedTask::allocate(int size) { | |
552 return __scheduler->allocate(size); | |
553 } | |
554 | |
555 void | |
556 SchedTask::dma_load(void *buf, uint32 addr, uint32 size, uint32 mask) { | |
557 __scheduler->dma_load(buf, addr, size, mask); | |
558 } | |
559 | |
560 void | |
561 SchedTask::dma_store(void *buf,uint32 addr, uint32 size, uint32 mask) { | |
562 __scheduler->dma_store(buf, addr, size, mask); | |
563 } | |
564 | |
565 void | |
566 SchedTask::dma_wait(uint32 mask) { | |
567 __scheduler->dma_wait(mask); | |
568 } | |
569 | |
334
20f2459041cb
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
570 void |
20f2459041cb
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
571 SchedTask::show_dma_wait() { |
20f2459041cb
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
572 __scheduler->show_dma_wait(); |
20f2459041cb
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
573 } |
20f2459041cb
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
574 |
387
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
575 |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
576 MemorySegment * SchedTask::get_segment(memaddr addr, MemList *m) { |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
577 return __scheduler->get_segment(addr,m); |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
578 } |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
579 |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
580 void SchedTask::put_segment(MemorySegment *s) { |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
581 __scheduler->put_segment(s); |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
582 } |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
583 |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
584 void SchedTask::wait_segment(MemorySegment *s) { |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
585 __scheduler->wait_segment(s); |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
586 } |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
587 |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
588 |
5e2d30bfbf23
no compile error but not worked.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
373
diff
changeset
|
589 |
308 | 590 /* end */ |