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