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