Mercurial > hg > Members > kono > Cerium
comparison TaskManager/Cell/CellTaskManagerImpl.cc @ 719:cafffff0f45a
clean up scheduler main loop
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 19 Dec 2009 10:34:43 +0900 |
parents | 31eb1f56d986 |
children | dac59b74e02a |
comparison
equal
deleted
inserted
replaced
718:31eb1f56d986 | 719:cafffff0f45a |
---|---|
9 #include "SchedTask.h" | 9 #include "SchedTask.h" |
10 #include "MainScheduler.h" | 10 #include "MainScheduler.h" |
11 #include "types.h" | 11 #include "types.h" |
12 #include "SysFunc.h" | 12 #include "SysFunc.h" |
13 | 13 |
14 static void send_alloc_reply(SpeThreads *speThreads); | |
14 | 15 |
15 CellTaskManagerImpl::~CellTaskManagerImpl() | 16 CellTaskManagerImpl::~CellTaskManagerImpl() |
16 { | 17 { |
17 delete speThreads; | 18 delete speThreads; |
18 delete [] speTaskList; | 19 delete [] speTaskList; |
155 void | 156 void |
156 CellTaskManagerImpl::run() | 157 CellTaskManagerImpl::run() |
157 { | 158 { |
158 TaskListPtr ppeTaskList = NULL; | 159 TaskListPtr ppeTaskList = NULL; |
159 | 160 |
160 // PPE 側で動く TaskList です | |
161 // FifoTaskManagerImpl::run と上手く合うように | |
162 // こんなことやってますよ | |
163 // | |
164 // 本来は、別 thread で動かすべきだろう... | |
165 ppeTaskList = ppeManager->get_runTaskList(); | |
166 if (!ppeTaskList) { | |
167 goto cont; | |
168 } | |
169 | |
170 // SPE からの Mailbox Check は | |
171 // PPE 側の schedule から抜けて来たときに行う | |
172 // (speThreads で Blocking Mailbox read と | |
173 // セマフォとか使ってやってもいいが、今はこの方式で) | |
174 // | |
175 // すべてのspe task が finish task を待つ場合は、ppeTaskList の | |
176 // 判定だけで十分だが、そうでない場合は、spe の task が残っているか | |
177 // どうかを調べる必要がある。 | |
178 // | |
179 do { | 161 do { |
162 // PPE side | |
163 ppeTaskList = ppeManager->get_runTaskList(); | |
180 ppeManager->schedule(ppeTaskList); | 164 ppeManager->schedule(ppeTaskList); |
181 cont: | 165 ppeManager->mail_check(waitTaskQueue); |
182 ppeTaskList = mail_check(waitTaskQueue); | 166 // SPE side |
167 do { | |
168 mail_check(waitTaskQueue); | |
169 // SPE に送る TaskList の準備 | |
170 set_runTaskList(); | |
171 // TaskList 待ちの SPE に TaskList を送る | |
172 for (int i = 0; i < machineNum; i++) { | |
173 if (flag_sendTaskList[i] == 1 && speTaskList_bg[i]->length >= 1 ) { | |
174 send_taskList(i); | |
175 spe_running++; | |
176 } | |
177 } | |
178 } while (ppeManager->activeTaskQueue->empty() && !waitTaskQueue->empty()); | |
183 } while (ppeTaskList || spe_running >0); | 179 } while (ppeTaskList || spe_running >0); |
184 } | 180 } |
185 | 181 |
186 /** | 182 /** |
187 * SPE からのメールをチェックする | 183 * SPE からのメールをチェックする |
188 * | |
189 * @param [mail_list] | |
190 * PPE 側で動く Scheduler からのメールリスト | |
191 * この中で PPE 側の mail check も行う | |
192 * | |
193 * @return PPE Scheduler に対してのメール。 | |
194 * 次に実行する TaskList のアドレスや、終了コマンドを送る | |
195 */ | 184 */ |
196 | 185 |
197 TaskListPtr | 186 void |
198 CellTaskManagerImpl::mail_check(HTaskInfo *wait_queue) | 187 CellTaskManagerImpl::mail_check() |
199 { | 188 { |
200 // PPE Scheduler からの mail check | 189 memaddr data; |
201 ppeManager->mail_check(waitTaskQueue); | 190 |
202 | 191 // SPE Scheduler からの mail check |
203 do { | 192 for (int id = 0; id < machineNum; id++) { |
204 memaddr data; | 193 while (speThreads->has_mail(id, 1, &data)) { |
205 | 194 if (data == (memaddr)MY_SPE_STATUS_READY) { |
206 // SPE Scheduler からの mail check | 195 // MY_SPE_STATUS_READY: SPE が持ってた Task 全て終了 |
207 for (int id = 0; id < machineNum; id++) { | 196 flag_sendTaskList[id] = 1; |
208 while (speThreads->has_mail(id, 1, &data)) { | 197 spe_running--; |
209 /** | 198 } else if (data == (memaddr)MY_SPE_COMMAND_MALLOC) { |
210 * MY_SPE_STATUS_READY: SPE が持ってた Task 全て終了 | 199 // MY_SPE_COMMAND_MALLOC SPE からのmain memory request |
211 * MY_SPE_NOP: 特に意味のないコマンド | 200 send_alloc_reply(speThreads); |
212 * それ以外:終了したタスク(PPEにあるのでアドレス | 201 } else if (data > (memaddr)MY_SPE_NOP) { |
213 * | 202 // 終了したタスク(PPEにあるのでアドレス) |
214 * MY_SPE_NOP が 0 なので、 | 203 HTaskPtr task = (HTaskPtr)data; |
215 * 下のように data > MY_SPE_NOP とかしています。 | 204 task->post_func(schedTaskManager, task->post_arg1, task->post_arg2); |
216 * 一目でよくわからない書き方なんで、直したいところですが。。。 | 205 check_task_finish(task,waitTaskQueue); |
217 */ | |
218 // 名前あとでちゃんと決めよう => MY_SPE_... とかじゃなくて | |
219 if (data == (memaddr)MY_SPE_STATUS_READY) { | |
220 //__debug_ppe("[SPE %d] finish\n", id); | |
221 flag_sendTaskList[id] = 1; | |
222 spe_running--; | |
223 } else if (data == (memaddr)MY_SPE_COMMAND_MALLOC) { | |
224 //__debug_ppe("[PPE] MALLOC COMMAND from [SPE %d]\n", id); | |
225 | |
226 /** | |
227 * info[0] = alloc_id; (CellScheduler::mainMem_alloc 参照) | |
228 * info[1] = alloc_addr; | |
229 */ | |
230 memaddr alloc_info[2]; | |
231 long alloc_size; | |
232 long command; | |
233 | |
234 speThreads->get_mail(id, 2, alloc_info); | |
235 command = (long)alloc_info[0]; | |
236 alloc_size = (long)alloc_info[1]; | |
237 | |
238 | |
239 alloc_info[1] = (memaddr)allocate(alloc_size); | |
240 /* | |
241 * allocate された領域は今の SPE buffer にリンクとして接続する | |
242 * ここでは TaskList を allocate(new) して登録してやろうか | |
243 */ | |
244 | |
245 //__debug_ppe("[PPE] MALLOCED 0x%lx from [SPE %d]\n", alloc_info[1],id); | |
246 // 今のところ何もしてない。どうも、この allocate を free | |
247 // するのは、SPE task が返した値を見て行うらしい。それは、 | |
248 // 忘れやすいのではないか? | |
249 speThreads->add_output_tasklist(command, alloc_info[1], alloc_size); | |
250 | |
251 speThreads->send_mail(id, 2, alloc_info); | |
252 } else if (data > (memaddr)MY_SPE_NOP) { | |
253 //__debug_ppe("[PPE] recv from [SPE %d] : 0x%x\n", id, data); | |
254 HTaskPtr task = (HTaskPtr)data; | |
255 task->post_func(schedTaskManager, task->post_arg1, task->post_arg2); | |
256 check_task_finish(task,waitTaskQueue); | |
257 } | |
258 } | 206 } |
207 // MY_SPE_NOP: 特に意味のないコマンド | |
259 } | 208 } |
260 | 209 } |
261 // 依存関係を満たしたタスクをアクティブに | 210 } |
262 wakeup_waitTask(); | 211 |
263 | 212 static void |
264 // SPE に送る TaskList の準備 | 213 send_alloc_reply(SpeThreads *speThreads) |
265 set_runTaskList(); | 214 { |
266 | 215 |
267 // TaskList 待ちの SPE に TaskList を送る | 216 /** |
268 for (int i = 0; i < machineNum; i++) { | 217 * info[0] = alloc_id; (CellScheduler::mainMem_alloc 参照) |
269 if (flag_sendTaskList[i] == 1 && speTaskList_bg[i]->length >= 1 ) { | 218 * info[1] = alloc_addr; |
270 send_taskList(i); | 219 */ |
271 spe_running++; | 220 memaddr alloc_info[2]; |
272 } | 221 long alloc_size; |
273 } | 222 long command; |
274 } while (ppeManager->activeTaskQueue->empty() && !waitTaskQueue->empty()); | 223 |
275 | 224 speThreads->get_mail(id, 2, alloc_info); |
276 return ppeManager->get_runTaskList(); | 225 command = (long)alloc_info[0]; |
226 alloc_size = (long)alloc_info[1]; | |
227 | |
228 | |
229 alloc_info[1] = (memaddr)allocate(alloc_size); | |
230 //__debug_ppe("[PPE] MALLOCED 0x%lx from [SPE %d]\n", alloc_info[1],id); | |
231 // 今のところ何もしてない。どうも、この allocate を free | |
232 // するのは、SPE task が返した値を見て行うらしい。それは、 | |
233 // 忘れやすいのではないか? | |
234 speThreads->add_output_tasklist(command, alloc_info[1], alloc_size); | |
235 | |
236 speThreads->send_mail(id, 2, alloc_info); | |
277 } | 237 } |
278 | 238 |
279 /** | 239 /** |
280 * 条件を満たしたら SPE に TaskList を送信する | 240 * 条件を満たしたら SPE に TaskList を送信する |
281 * 条件1. SPE が持ってた TaskList を終了して、次の TaskList を待ってる | 241 * 条件1. SPE が持ってた TaskList を終了して、次の TaskList を待ってる |