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 を待ってる