Mercurial > hg > Members > kono > Cerium
diff TaskManager/Fifo/FifoTaskManagerImpl.cc @ 263:001583879ac3 akira
merge 12 & 122
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 03 Jun 2009 23:55:07 +0900 |
parents | 5c194c71eca8 |
children | 72dcf908ec52 |
line wrap: on
line diff
--- a/TaskManager/Fifo/FifoTaskManagerImpl.cc Thu Feb 07 19:17:06 2008 +0900 +++ b/TaskManager/Fifo/FifoTaskManagerImpl.cc Wed Jun 03 23:55:07 2009 +0900 @@ -2,130 +2,236 @@ #include <stdlib.h> #include <string.h> #include "FifoTaskManagerImpl.h" -#include "ppe_spe.h" +#include "types.h" +#include "error.h" +FifoTaskManagerImpl::~FifoTaskManagerImpl(void) +{ + delete mailManager; + delete scheduler; + delete bufferManager; +} + +/** + * MailManager は PPE スケジューラとのメール交換、 + * FifoScheduler は PPE 側のスケジューラ + * BufferManager は Task、TaskList などのメモリ管理(大層なことしてないが + */ void FifoTaskManagerImpl::init(void) { - taskInfo = new FifoTaskInfo(); - taskInfo->init(); + mailManager = new MailManager(); + mailManager->init(20); - mailManager = new MailManager(); - mailManager->init_pool_mailQueue(20); + scheduler = new MainScheduler(); + scheduler->init(); + scheduler->set_mailManager(mailManager); + + bufferManager = new BufferManager; + bufferManager->init(); + + mainTaskList = bufferManager->create_taskList(); } -TaskListPtr -FifoTaskManagerImpl::set_task(void) +/** + * これは CellTaskManagerImpl から呼ばれる。 + * BufferManager は共用で使うので引数に。 + * CellTaskManagerImpl と FifoTaskManagerImpl が同時に + * 上のデータにアクセスする事は(今は)ないのでこれでおk + */ +void +FifoTaskManagerImpl::init(MainScheduler *_sched, BufferManager *buff) { - // ここ...直すかな - TaskListPtr list = taskInfo->machineTaskList[0]; - TaskQueuePtr queue = taskInfo->activeTaskQueue; + mailManager = new MailManager(); + mailManager->init(20); + + //scheduler = new MainScheduler(); + scheduler = _sched; + scheduler->init(); + scheduler->set_mailManager(mailManager); + + bufferManager = buff; + + mainTaskList = bufferManager->create_taskList(); +} + +/** + * スケジューラに渡す TaskList を取得する。 + * + * @return 実行タスクリスト + * + * ActiveTaskQueue (依存条件は満たし済み) のタスクを + * 実行タスクリストに入れる + */ +TaskListPtr +FifoTaskManagerImpl::get_runTaskList(void) +{ + TaskListPtr list, list_top; + TaskQueuePtr queue; TaskQueuePtr d; - HTaskPtr htask; - TaskPtr task; + HTaskPtr htask; // HTask (PPE にある) + TaskPtr task; // Task (SPE に送る Task) + queue = activeTaskQueue; if (queue == NULL) { return NULL; } - // Fixme - // ここは、clear_taskList とか? - list->length = 0; + // PPE 側で実行される TaskList + list_top = mainTaskList; + + // list_top->clear() とかの方がいいかもしれん。 + list_top = bufferManager->clear_taskList(list_top); + list = list_top; while (queue) { - htask = queue->task; + htask = (HTaskPtr)queue->task; d = queue; queue = queue->next; task = &list->tasks[list->length++]; + +#if 0 task->command = htask->command; - task->in_addr = htask->in_addr; - task->out_addr = htask->out_addr; - task->in_size = htask->in_size; - task->self = htask; + task->inData = htask->inData; + task->outData = htask->outData; + task->self = (unsigned int)htask; +#else + memcpy(task, htask, sizeof(Task)); +#endif - taskInfo->free_taskQueue(d); - } + if (list->length >= TASK_MAX_SIZE) { + TaskListPtr newList = bufferManager->create_taskList(); + list_top = TaskListInfo::append(list_top, newList); + list = newList; + } - taskInfo->activeTaskQueue = NULL; + bufferManager->free_taskQueue(d); + } - return list; + activeTaskQueue = NULL; + mainTaskList = list_top; + + return list_top; } -// ../spe/main.cpp -extern MailQueuePtr spe_main(MailManager*, MailQueuePtr); -/** - * spe 側は MY_SPE_COMMAND_EXIT を受け取るまでは別スレッドで動き続ける。 - * fifo version では sequential に動かすため、 - * mail list の最後に番兵として MY_SPE_COMMAND_EXIT のメールを入れる。 - * これで、fifo での spe 側は、mail で受け取った task_list を処理した後 - * EXIT を受け取って終了する・・・といいな - */ void FifoTaskManagerImpl::run(void) { TaskListPtr list; - MailQueuePtr mail_list = NULL; - MailQueuePtr list_mail = NULL; // task list - MailQueuePtr sentinel = NULL; // 番兵 + MailQueuePtr mail; + + list = get_runTaskList(); - // 暫定 - list = set_task(); + do { + // list を実行する + mail = schedule(list); - list_mail = mailManager->create_mail((unsigned int)list); - mail_list = append_mailQueue(mail_list, list_mail); - - do { - sentinel = mailManager->create_mail(MY_SPE_COMMAND_EXIT); - mail_list = append_mailQueue(mail_list, sentinel); + // mail には、ppe scheduler からの mail がある + mail_check(mail); - // 返って来た mail_list には、spe からの mail がある - mail_list = spe_main(mailManager, mail_list); - mail_list = mail_check(mail_list); - } while (mail_list); + // 依存関係を満たしたものは実行可能キューへ + wakeup_waitTask(); + list = get_runTaskList(); + } while (list); } +/** + * @param [list] 実行タスクリスト + * @return FifoScheduler からのメール + * + * [Tasklist] -> [番兵] -> scheduler->run を抜ける + */ MailQueuePtr +FifoTaskManagerImpl::schedule(TaskListPtr list) +{ + MailQueuePtr list_mail; // task list + MailQueuePtr sentinel; // 番兵 + MailQueuePtr in_mail_list = NULL; + MailQueuePtr out_mail_list = NULL; + + // TaskList のアドレス + list_mail = mailManager->create((unsigned int)list); + in_mail_list = MailManager::append_mailQueue(in_mail_list, list_mail); + + // EXIT_COMMAND (番兵的な意味で) + sentinel = mailManager->create(MY_SPE_COMMAND_EXIT); + in_mail_list = MailManager::append_mailQueue(in_mail_list, sentinel); + + // scheduler は受け取ったメールを元に実行する + scheduler->send_mailList(in_mail_list); + scheduler->run(); + out_mail_list = scheduler->recv_mailList(); + + return out_mail_list; +} + +/** + * PPE Scheduler からのメールをチェックする + * + * @param [mail_list] + * PPE 側で動く Scheduler からのメールリスト + * 終了した Task や、その他(今はまだ実装してないけど)の情報が入ってる + * + * @return Scheduler が次に実行する Task List + * NULL なら全てのタスクが実行終了したということ + */ +void FifoTaskManagerImpl::mail_check(MailQueuePtr mail_list) { MailQueuePtr q = mail_list; MailQueuePtr d; - MailQueuePtr ret = NULL; unsigned int data; - TaskListPtr next_list; while (q) { data = q->data; + /** + * MY_SPE_STATUS_READY: SPE が持ってた Task 全て終了 + * MY_SPE_NOP: 特に意味のないコマンド + * それ以外:終了したタスク(PPEにあるのでアドレス + * + * MY_SPE_NOP が 0 なので、 + * 下のように data > MY_SPE_NOP とかしています。 + * 一目でよくわからない書き方なんで、直したいところですが。。。 + */ if (data == MY_SPE_STATUS_READY) { -#ifdef _PPE_DEBUG - printf("[FIFO] finish\n"); -#endif - next_list = set_task(); - if (next_list != NULL) { - d = mailManager->create_mail((unsigned int)next_list); - ret = append_mailQueue(ret, d); - } - } else { -#ifdef _PPE_DEBUG - printf("[PPE] recv from : 0x%x\n", data); -#endif - taskInfo->check_task_finish((HTaskPtr)data); + __debug_ppe("mail_check(): Task List finish\n"); + } else if (data > MY_SPE_NOP) { + __debug_ppe("mail_check(): recv from 0x%x\n", data); + check_task_finish((HTaskPtr)data); } d = q; q = q->next; - mailManager->free_mailQueue(d); + mailManager->free(d); } +} - return ret; +void +FifoTaskManagerImpl::mail_check(MailQueuePtr mail_list, TaskQueuePtr *wait) +{ + waitTaskQueue = *wait; + mail_check(mail_list); } +void* +FifoTaskManagerImpl::allocate(int size) +{ + return malloc(size); +} -TaskManagerImpl* +/** + * こういう使い方を + * Abstract Factory Pattern + * というらしい。 + */ +#ifdef __CERIUM_FIFO__ +TaskManagerImpl* create_impl(int num) { return new FifoTaskManagerImpl(); } +#endif // __CERIUM_FIFO__