Mercurial > hg > Game > Cerium
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 } |