Mercurial > hg > Game > Cerium
annotate TaskManager/Cell/CellTaskManagerImpl.cc @ 481:f9ffcffb6d09 draft
Double linked list modification done (tested on Mac OS X)
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 05 Oct 2009 16:46:46 +0900 |
parents | bf2d2625485e |
children | d6245cb38028 |
rev | line source |
---|---|
321 | 1 #define DEBUG |
2 #include "error.h" | |
57 | 3 #include <stdio.h> |
4 #include <stdlib.h> | |
5 #include <string.h> | |
6 #include "CellTaskManagerImpl.h" | |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
7 #include "CellTaskListInfo.h" |
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
8 #include "CellHTaskInfo.h" |
109 | 9 #include "PpeScheduler.h" |
57 | 10 #include "types.h" |
11 | |
109 | 12 CellTaskManagerImpl::~CellTaskManagerImpl(void) |
67 | 13 { |
109 | 14 delete speThreads; |
15 delete [] speTaskList; | |
16 delete [] speTaskList_bg; | |
17 /** | |
321 | 18 * bufferManager は |
19 * ppeManager のなかで delete してもらう | |
109 | 20 */ |
21 // delete bufferManager; | |
22 delete [] flag_sendTaskList; | |
23 | |
24 delete ppeManager; | |
67 | 25 } |
26 | |
57 | 27 void |
28 CellTaskManagerImpl::init(void) | |
29 { | |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
30 taskQueueImpl = new TaskQueueInfo; |
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
31 taskQueueImpl->init(TASK_MAX_SIZE*4); |
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
32 |
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
33 taskListImpl = new CellTaskListInfo; |
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
34 taskListImpl->init(machineNum*2); |
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
35 |
481
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
36 activeTaskQueue = new TaskQueueInfo(); |
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
37 |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
38 htaskImpl = new CellHTaskInfo; |
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
39 htaskImpl->init(TASK_MAX_SIZE*2); |
65 | 40 |
41 speThreads = new SpeThreads(machineNum); | |
42 speThreads->init(); | |
109 | 43 |
44 speTaskList = new TaskListPtr[machineNum]; | |
45 speTaskList_bg = new TaskListPtr[machineNum]; | |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
46 |
109 | 47 for (int i = 0; i < machineNum; i++) { |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
48 speTaskList[i] = taskListImpl->create(); |
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
49 speTaskList_bg[i] = taskListImpl->create(); |
109 | 50 } |
51 | |
52 flag_sendTaskList = new int[machineNum]; | |
53 for (int i = 0; i < machineNum; i++) { | |
54 flag_sendTaskList[i] = 1; | |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
55 } |
321 | 56 // PPE 側の管理をする Manager |
109 | 57 ppeManager = new FifoTaskManagerImpl(machineNum); |
479
bf2d2625485e
Double Linked List base TaskQueue
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
476
diff
changeset
|
58 // 大半のTaskQueueInfoは、共有される |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
59 ppeManager->init(new PpeScheduler, this); |
57 | 60 } |
61 | |
109 | 62 void |
63 CellTaskManagerImpl::append_activeTask(HTaskPtr task) | |
64 { | |
65 if (task->cpu_type == CPU_PPE) { | |
66 ppeManager->append_activeTask(task); | |
67 } else { | |
481
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
68 TaskQueuePtr q = taskQueueImpl->create(task); |
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
69 activeTaskQueue->addLast(q); |
109 | 70 } |
71 } | |
72 | |
321 | 73 // SPE_ANY が指定されていた時に |
74 // これをインクリメントしつつ呼ぶことにする。 | |
75 // 乱数使ってもいいけどさ。 | |
109 | 76 int cur_anySpeid = 0; |
77 | |
78 /** | |
321 | 79 * ActiveTaskQueue から Task を |
80 * 各 SPE に渡す TaskList に入れる | |
109 | 81 * |
321 | 82 * ここの activeTaskQueue は FifoTaskManagerImpl のと意味が違い、 |
83 * spe に渡される Task だけ入っている | |
109 | 84 */ |
85 void | |
86 CellTaskManagerImpl::set_runTaskList(void) | |
70 | 87 { |
321 | 88 // ここ...直すかな |
70 | 89 TaskListPtr list; |
481
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
90 |
70 | 91 TaskQueuePtr d; |
92 HTaskPtr htask; | |
93 TaskPtr task; | |
109 | 94 int speid; |
70 | 95 |
481
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
96 if (activeTaskQueue->empty()) { |
109 | 97 return ; |
70 | 98 } |
99 | |
481
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
100 while (TaskQueuePtr queue = activeTaskQueue->poll()) { |
109 | 101 htask = (HTaskPtr)queue->task; |
70 | 102 |
109 | 103 if (htask->cpu_type == SPE_ANY) { |
104 speid = cur_anySpeid++; | |
105 cur_anySpeid = (cur_anySpeid < machineNum) | |
106 ? cur_anySpeid : 0; | |
70 | 107 } else { |
321 | 108 // -1 してるのは |
109 // htask->cpu_type - CPU_SPE で | |
110 // SPE0 = 1, SPE1 = 2, ... SPE5 = 6 ってなってるので | |
111 // 配列的 (SPE0 = arr[0], SPE1 = arr[1]) にするため | |
109 | 112 speid = htask->cpu_type - CPU_SPE - 1; |
113 | |
321 | 114 // SPU の数以上が指定されていれば |
115 // とりあえず MAX_USE_SPE_NUM (実際に動く SPE の最大数) で | |
116 // あまり求めてそれを使うことにする。 | |
117 // ここで判定するもんでもないか? | |
109 | 118 if (speid >= machineNum) { |
119 speid %= machineNum; | |
120 } | |
70 | 121 } |
109 | 122 |
123 list = speTaskList_bg[speid]; | |
124 | |
125 if (list->length >= TASK_MAX_SIZE) { | |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
126 TaskListPtr newList = taskListImpl->create(); |
109 | 127 newList = TaskListInfo::append(newList, speTaskList_bg[speid]); |
128 speTaskList_bg[speid] = newList; | |
129 list = newList; | |
130 } | |
131 | |
132 task = &list->tasks[list->length++]; | |
133 #if 0 | |
134 task->command = htask->command; | |
135 task->inData = htask->inData; | |
136 task->outData = htask->outData; | |
137 task->self = (unsigned int)htask; | |
79 | 138 #else |
481
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
139 memcpy(task, (Task*)htask, sizeof(Task)); |
79 | 140 #endif |
70 | 141 |
481
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
142 activeTaskQueue->free(queue); |
70 | 143 } |
144 | |
109 | 145 activeTaskQueue = NULL; |
146 } | |
147 | |
148 void | |
149 CellTaskManagerImpl::run(void) | |
150 { | |
151 TaskListPtr ppeTaskList = NULL; | |
152 MailQueuePtr ppeMail = NULL; | |
70 | 153 |
321 | 154 // PPE 側で動く TaskList です |
155 // FifoTaskManagerImpl::run と上手く合うように | |
156 // こんなことやってますよ | |
109 | 157 ppeTaskList = ppeManager->get_runTaskList(); |
158 if (!ppeTaskList) { | |
159 goto cont; | |
160 } | |
70 | 161 |
321 | 162 // SPE からの Mailbox Check は |
163 // PPE 側の schedule から抜けて来たときに行う | |
164 // (speThreads で Blocking Mailbox read と | |
165 // セマフォとか使ってやってもいいが、今はこの方式で) | |
109 | 166 do { |
167 ppeMail = ppeManager->schedule(ppeTaskList); | |
168 cont: | |
169 ppeTaskList = mail_check(ppeMail); | |
170 } while (ppeTaskList); | |
70 | 171 } |
172 | |
65 | 173 /** |
321 | 174 * SPE からのメールをチェックする |
109 | 175 * |
176 * @param [mail_list] | |
321 | 177 * PPE 側で動く Scheduler からのメールリスト |
178 * この中で PPE 側の mail check も行う | |
109 | 179 * |
321 | 180 * @return PPE Scheduler に対してのメール。 |
181 * 次に実行する TaskList のアドレスや、終了コマンドを送る | |
109 | 182 */TaskListPtr |
65 | 183 CellTaskManagerImpl::mail_check(MailQueuePtr mail_list) |
57 | 184 { |
321 | 185 // PPE Scheduler からの mail check |
479
bf2d2625485e
Double Linked List base TaskQueue
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
476
diff
changeset
|
186 ppeManager->mail_check(mail_list); |
65 | 187 |
70 | 188 do { |
244 | 189 unsigned int data; |
109 | 190 |
321 | 191 // SPE Scheduler からの mail check |
244 | 192 for (int id = 0; id < machineNum; id++) { |
193 while (speThreads->check_mail(id, 1, &data)) { | |
70 | 194 |
109 | 195 /** |
321 | 196 * MY_SPE_STATUS_READY: SPE が持ってた Task 全て終了 |
197 * MY_SPE_NOP: 特に意味のないコマンド | |
198 * それ以外:終了したタスク(PPEにあるのでアドレス | |
109 | 199 * |
321 | 200 * MY_SPE_NOP が 0 なので、 |
201 * 下のように data > MY_SPE_NOP とかしています。 | |
202 * 一目でよくわからない書き方なんで、直したいところですが。。。 | |
109 | 203 */ |
321 | 204 // 名前あとでちゃんと決めよう => MY_SPE_... とかじゃなくて |
70 | 205 if (data == MY_SPE_STATUS_READY) { |
334
7bc5cbc5fe04
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
206 //__debug_ppe("[SPE %d] finish\n", id); |
109 | 207 flag_sendTaskList[id] = 1; |
208 } else if (data == MY_SPE_COMMAND_MALLOC) { | |
334
7bc5cbc5fe04
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
209 //__debug_ppe("[PPE] MALLOC COMMAND from [SPE %d]\n", id); |
109 | 210 |
211 /** | |
321 | 212 * info[0] = alloc_id; (CellScheduler::mainMem_alloc 参照) |
109 | 213 * info[1] = alloc_addr; |
214 */ | |
244 | 215 unsigned int alloc_info[3]; |
109 | 216 int alloc_size; |
244 | 217 int command; |
109 | 218 |
244 | 219 speThreads->get_mail(id, 2, alloc_info); |
220 command = alloc_info[0]; | |
253
0c9c9906d777
usr_help_str is nessesary for example
tkaito@localhost.localdomain
parents:
244
diff
changeset
|
221 alloc_size = alloc_info[1]; |
244 | 222 |
109 | 223 |
224 alloc_info[1] = (unsigned int)allocate(alloc_size); | |
244 | 225 /* |
321 | 226 * allocate された領域は今の SPE buffer にリンクとして接続する |
227 * ここでは TaskList を allocate(new) して登録してやろうか | |
244 | 228 */ |
109 | 229 |
334
7bc5cbc5fe04
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
230 //__debug_ppe("[PPE] MALLOCED 0x%x from [SPE %d]\n", alloc_info[1],id); |
300
68d4267cb4a4
remove TaskManager/Fifo/MainScheduler.o TaskManeger/Test/test_render/test_nogl
tkaito@localhost.localdomain
parents:
298
diff
changeset
|
231 speThreads->add_output_tasklist(command, alloc_info[1], alloc_size); |
275 | 232 |
244 | 233 speThreads->send_mail(id, 2, alloc_info); |
109 | 234 } else if (data > MY_SPE_NOP) { |
334
7bc5cbc5fe04
[in test_render] push L key , call show_dma_wait, but incomplete.
e065746@localhost.localdomain
parents:
321
diff
changeset
|
235 //__debug_ppe("[PPE] recv from [SPE %d] : 0x%x\n", id, data); |
109 | 236 check_task_finish((HTaskPtr)data); |
70 | 237 } |
65 | 238 } |
239 } | |
109 | 240 |
321 | 241 // 依存関係を満たしたタスクをアクティブに |
109 | 242 wakeup_waitTask(); |
243 | |
321 | 244 // SPE に送る TaskList の準備 |
109 | 245 set_runTaskList(); |
246 | |
321 | 247 // TaskList 待ちの SPE に TaskList を送る |
109 | 248 for (int i = 0; i < machineNum; i++) { |
249 if (flag_sendTaskList[i] == 1 && speTaskList_bg[i]->length >= 1 ) { | |
250 send_taskList(i); | |
251 } | |
252 } | |
70 | 253 |
321 | 254 // 現在の FifoTaskManager の仕様では |
255 // ・PPE で実行するタスクが無くなれば終了する | |
256 // であり、この場合もし SPE にタスクが残っていても | |
257 // メインループから抜けてプログラム終了となってしまうので | |
258 // ここでストップかけてます。 | |
481
f9ffcffb6d09
Double linked list modification done (tested on Mac OS X)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
479
diff
changeset
|
259 } while (ppeManager->activeTaskQueue->empty() && !waitTaskQueue->empty()); |
109 | 260 |
261 return ppeManager->get_runTaskList(); | |
262 } | |
66 | 263 |
109 | 264 /** |
321 | 265 * 条件を満たしたら SPE に TaskList を送信する |
266 * 条件1. SPE が持ってた TaskList を終了して、次の TaskList を待ってる | |
267 * 条件2. SPE に送る TaskList に Task がある | |
109 | 268 * |
321 | 269 * SPE で実行終了した TaskList [speTaskList] と |
270 * これから実行する TaskList [speTaskList_bg] のバッファを入れ替える | |
271 * ついでに実行終了したやつは clear しておく。 | |
109 | 272 */ |
273 void | |
274 CellTaskManagerImpl::send_taskList(int id) | |
275 { | |
276 TaskListPtr tmp; | |
277 | |
278 tmp = speTaskList[id]; | |
279 speTaskList[id] = speTaskList_bg[id]; | |
280 speTaskList_bg[id] = tmp; | |
281 | |
476
5fc79ff9c257
CellBufferManager removed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
380
diff
changeset
|
282 taskListImpl->clear_taskList(speTaskList_bg[id]); |
109 | 283 |
244 | 284 speThreads->send_mail(id, 1, (unsigned int *)&speTaskList[id]); |
109 | 285 flag_sendTaskList[id] = 0; |
57 | 286 } |
287 | |
65 | 288 |
109 | 289 void* |
290 CellTaskManagerImpl::allocate(int size) | |
291 { | |
292 void *buff; | |
293 | |
294 posix_memalign(&buff, DEFAULT_ALIGNMENT, size); | |
244 | 295 |
321 | 296 // bzero はコストが高いのでやりたくない |
109 | 297 bzero(buff, size); |
298 | |
299 return buff; | |
300 } | |
301 | |
380 | 302 Scheduler* |
303 CellTaskManagerImpl::get_scheduler() | |
304 { | |
305 return ppeManager->get_scheduler(); | |
306 } | |
307 | |
109 | 308 #ifdef __CERIUM_CELL__ |
57 | 309 TaskManagerImpl* |
310 create_impl(int num) | |
311 { | |
67 | 312 return new CellTaskManagerImpl(num); |
57 | 313 } |
109 | 314 #endif // __CERIUM_CELL |