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