comparison TaskManager/Cell/spe/SchedTask.cc @ 109:028ffc9c0375 draft

Cerium cvs version
author gongo@gendarme.local
date Wed, 12 Nov 2008 17:39:33 +0900
parents 504899860e66
children e3b7776b1420
comparison
equal deleted inserted replaced
108:6f3b3dd3c095 109:028ffc9c0375
1 #include <stdlib.h>
2 #include <string.h>
1 #include "SchedTask.h" 3 #include "SchedTask.h"
2 #include "SchedTaskList.h" 4 #include "SchedTaskList.h"
3 #include "SchedNop2Ready.h" 5 #include "SchedNop2Ready.h"
4 #include "DmaManager.h" 6 #include "DmaManager.h"
5 #include "error.h" 7 #include "error.h"
6 #include "TaskManager.h" 8 #include "TaskManager.h"
7 9
8 extern SchedTask::TaskObject task_list[16]; 10 extern Scheduler::TaskObject task_list[MAX_TASK_OBJECT];
9 11
10 SchedTask* 12 SchedTask*
11 CreateSchedTask(TaskListPtr taskList, void *readbuf, void *writebuf, 13 CreateSchedTask(TaskListPtr taskList, Scheduler *sched)
12 DmaManager* dma) 14 {
13 { 15 TaskPtr task = &taskList->tasks[sched->curIndex_taskList++];
14 TaskPtr task = &taskList->tasks[--taskList->length]; 16
15 17 return task_list[task->command](taskList, task, sched->get_curReadBuf(),
16 return task_list[task->command](taskList, task, readbuf, writebuf, dma); 18 sched->get_curWriteBuf(), sched);
17 } 19 }
18 20
19 21 SchedTask::SchedTask(TaskListPtr _list, TaskPtr _task, ListDataPtr rbuf,
20 SchedTask::SchedTask(TaskListPtr _list, TaskPtr _task, void *rbuf, void *wbuf, 22 ListDataPtr wbuf, Scheduler* sc)
21 DmaManager* cn) 23 {
22 : list(_list), task(_task), readbuf(rbuf), writebuf(wbuf), connector(cn) {} 24 __list = _list;
23 25 __task = _task;
26 __inListData = rbuf;
27 __outListData = wbuf;
28 __readbuf = NULL;
29 __writebuf = NULL;
30 __scheduler = sc;
31 __taskGroup = NULL;
32 __renew_flag = 0;
33
34 smanager = new STaskManager(this);
35 }
36
37 SchedTask::~SchedTask(void)
38 {
39 if (__flag_renewTask) {
40 /**
41 * __inListData と __outListData はタスク自身のものなので
42 * 終わったら即 free する。
43 */
44 free(__inListData);
45 free(__outListData);
46
47 /**
48 * __list != NULL の場合、
49 * この Task が __list の最後の Task になるので (SchedTask::next 参照)
50 * このタイミングで __list を解放する
51 * (free に渡されるアドレスが正しいものとなる)。
52 * それ以外の Task では当然解放しない。
53 * __list == NULL なので、free に渡しても無問題
54 */
55 free(__list);
56 }
57
58 delete smanager;
59 }
60
61 void
62 SchedTask::__init__(void)
63 {
64 /**
65 * task->inData や task->outData が
66 * PPE のものか、SPE のものかって
67 * アドレスで判定できれば楽になると思うんだが。。。
68 */
69 if (__flag_renewTask == 0) {
70 __scheduler->dma_load(__inListData, (uint32)__task->inData,
71 sizeof(ListData), DMA_READ_IN_LIST);
72 __scheduler->dma_load(__outListData, (uint32)__task->outData,
73 sizeof(ListData), DMA_READ_OUT_LIST);
74
75 __taskGroup = new TaskGroup;
76 __taskGroup->command = __task->self;
77 } else {
78 __inListData = __task->inData;
79 __outListData = __task->outData;
80 __taskGroup = (TaskGroupPtr)__task->self;
81 }
82 }
83
84
85 /**
86 * [Todo]
87 * データの読み込み場所を readbuf ではなく、
88 * ユーザ自身で決めれるようになるといいかもしれない。
89 *
90 * # TaskManager が勝手に消すことなく、
91 * # ユーザが SPE 上に持ち続けることができるため。
92 * # もちろん管理はユーザに任せるわけだ。
93 */
24 void 94 void
25 SchedTask::read(void) 95 SchedTask::read(void)
26 { 96 {
27 __debug("[SchedTask:%s]\n", __FUNCTION__); 97 __debug("[SchedTask:%s]\n", __FUNCTION__);
28 98
29 connector->dma_load(readbuf, task->in_addr, task->in_size, DMA_READ); 99 // wait for load inListData
100 __scheduler->dma_wait(DMA_READ_IN_LIST);
101
102 // 読むデータが一つもなければ無視
103 if (__inListData->length < 1 || __inListData->size == 0) return;
104
105 // load Input Data
106 __readbuf = __scheduler->allocate(__inListData->size);
107 __scheduler->dma_loadList(__inListData, __readbuf, DMA_READ);
30 } 108 }
31 109
32 void 110 void
33 SchedTask::exec(void) 111 SchedTask::exec(void)
34 { 112 {
35 __debug("[SchedTask:%s]\n", __FUNCTION__); 113 __debug("[SchedTask:%s]\n", __FUNCTION__);
36 114
37 connector->dma_wait(DMA_READ); 115 // wait for load outListData
38 116 __scheduler->dma_wait(DMA_READ_OUT_LIST);
39 __debug(" task->command = %d\n", task->command); 117
40 __debug(" task->in_size = %d\n", task->in_size); 118 __writebuf = __scheduler->allocate(__outListData->size);
41 __debug(" task->in_addr = 0x%x\n", task->in_addr); 119
42 __debug(" task->out_addr = 0x%x\n", task->out_addr); 120 __debug(" task->command = %d\n", __task->command);
43 __debug(" list->next = 0x%x\n", (unsigned int)list->next); 121 __debug(" task->in_size = %d\n", __task->in_size);
44 __debug(" list->length = 0x%x\n", (unsigned int)list->length); 122 __debug(" task->in_addr = 0x%x\n", __task->in_addr);
45 123 __debug(" task->out_addr = 0x%x\n", __task->out_addr);
46 task->in_size = run(readbuf, writebuf); 124 __debug(" list->next = 0x%x\n", (unsigned int)__list->next);
47 connector->dma_store(writebuf, task->out_addr, task->in_size, DMA_WRITE); 125 __debug(" list->length = 0x%x\n", (unsigned int)__list->length);
126
127 __scheduler->dma_wait(DMA_READ);
128
129 run(__readbuf, __writebuf);
130
131 free(__readbuf);
132
133 // 書き込む領域が要らなければ無視
134 if (__outListData->size > 0) {
135 __scheduler->dma_storeList(__outListData, __writebuf, DMA_WRITE);
136 __scheduler->dma_wait(DMA_WRITE);
137 }
138
139 if (__taskGroup->status() != 0) {
140 __task->self = __taskGroup->command;
141 delete __taskGroup;
142 __taskGroup = NULL;
143 }
48 } 144 }
49 145
50 void 146 void
51 SchedTask::write(void) 147 SchedTask::write(void)
52 { 148 {
53 __debug("[SchedTask:%s]\n", __FUNCTION__); 149 __debug("[SchedTask:%s]\n", __FUNCTION__);
54 150
55 connector->dma_wait(DMA_WRITE); 151 __scheduler->dma_wait(DMA_WRITE);
56 connector->mail_write((unsigned int)task->self); 152
57 } 153 free(__writebuf);
58 154
155 /**
156 * タスクが生成されている場合、
157 * そのタスクが終わってからこのタスク終了コマンドを送る。
158 * # コマンドは生成されたタスクに引き継がれる
159 */
160 if (__task->self == MY_SPE_NOP) return;
161
162 if (__flag_renewTask) {
163 uint32 cmd;
164
165 __taskGroup->remove(__task);
166 cmd = __taskGroup->status();
167
168 if (cmd != 0) {
169 delete __taskGroup;
170 __scheduler->mail_write(cmd);
171 }
172 } else {
173 if (__renew_flag == 0) {
174 __scheduler->mail_write(__task->self);
175 }
176 }
177 }
178
59 SchedTaskBase* 179 SchedTaskBase*
60 SchedTask::next(Scheduler *m, SchedTaskBase *p) 180 SchedTask::next(Scheduler *m, SchedTaskBase *p)
61 { 181 {
62 __debug("[SchedTask:%s]\n", __FUNCTION__); 182 __debug("[SchedTask:%s]\n", __FUNCTION__);
63 183
64 delete p; 184 delete p;
65 185
66 // ここ直さねば。どうやって if 文消そう? 186 if (__scheduler->curIndex_taskList < __list->length) {
67 // オブジェクト増やせばいいのかな 187 SchedTask* schedTask = CreateSchedTask(__list, __scheduler);
68 if (list->length == 0) { 188 schedTask->__flag_renewTask = this->__flag_renewTask;
69 if (list->next == 0) { 189 schedTask->__init__();
70 return new SchedNop2Ready(connector); 190
191 /**
192 * この理由は SchedTask:~SchedTask() で
193 */
194 __list = NULL;
195
196 return schedTask;
197 } else {
198 uint32 nextList = (uint32)__list->next;
199
200 if (nextList == 0) {
201 return new SchedNop2Ready(__scheduler);
71 } else { 202 } else {
72 return new SchedTaskList((unsigned int)list->next, 203 return new SchedTaskList(nextList, __scheduler);
73 m->get_curListBuf(), connector);
74 } 204 }
75 } else { 205 }
76 return CreateSchedTask(list, m->get_curReadBuf(), m->get_curWriteBuf(), 206 }
77 connector); 207
78 } 208 /**
79 } 209 * task->add_input で与えられた順番に対応する index (0〜n-1) で、
210 * buffer から対応するデータを返す。
211 */
212 void*
213 SchedTask::get_input(void *buff, int index)
214 {
215 if (buff != NULL) {
216 return (void*)((int)buff + __inListData->bound[index]);
217 } else {
218 return NULL;
219 }
220 }
221
222 /**
223 * write buffer の領域を返す。
224 */
225 void*
226 SchedTask::get_output(void *buff, int index)
227 {
228 if (buff != NULL) {
229 return (void*)((int)buff + __outListData->bound[index]);
230 } else {
231 return NULL;
232 }
233 }
234
235 int
236 SchedTask::get_param(int index)
237 {
238 return __task->param[index];
239 }
240
241 TaskPtr
242 SchedTask::create_task(int cmd)
243 {
244 TaskListPtr taskList = __scheduler->get_renewListBuf();
245 TaskPtr p = &taskList->tasks[taskList->length++];
246 p->command = cmd;
247
248 p->inData = (ListData*)__scheduler->allocate(sizeof(ListData));
249 p->outData = (ListData*)__scheduler->allocate(sizeof(ListData));
250
251 p->inData->clear();
252 p->outData->clear();
253
254 p->self = MY_SPE_NOP;
255 p->param_size = 0;
256
257 return p;
258 }
259
260 /**
261 * 名前が。。。
262 */
263 void
264 SchedTask::wait_task(TaskPtr waitTask)
265 {
266 waitTask->self = (uint32)__taskGroup;
267
268 __scheduler->add_groupTask(__taskGroup, waitTask);
269
270 __renew_flag++;
271 }
272
273 void*
274 SchedTask::global_alloc(int id, int size) {
275 return __scheduler->global_alloc(id, size);
276 }
277
278 void*
279 SchedTask::global_get(int id) {
280 return __scheduler->global_get(id);
281 }
282
283 void
284 SchedTask::global_free(int id) {
285 __scheduler->global_free(id);
286 }
287
288 void
289 SchedTask::mainMem_alloc(int id, int size) {
290 __scheduler->mainMem_alloc(id, size);
291 }
292
293 void
294 SchedTask::mainMem_wait(void) {
295 __scheduler->mainMem_wait();
296 }
297
298 void*
299 SchedTask::mainMem_get(int id) {
300 return __scheduler->mainMem_get(id);
301 }
302
303 void*
304 SchedTask::allocate(int size) {
305 return __scheduler->allocate(size);
306 }
307
308 void
309 SchedTask::dma_load(void *buf, uint32 addr, uint32 size, uint32 mask) {
310 __scheduler->dma_load(buf, addr, size, mask);
311 }
312
313 void
314 SchedTask::dma_store(void *buf,uint32 addr, uint32 size, uint32 mask) {
315 __scheduler->dma_store(buf, addr, size, mask);
316 }
317
318 void
319 SchedTask::dma_wait(uint32 mask) {
320 __scheduler->dma_wait(mask);
321 }