Mercurial > hg > Members > kono > Cerium
diff TaskManager/Fifo/FifoTaskManagerImpl.cc @ 109:5c194c71eca8
Cerium cvs version
author | gongo@gendarme.local |
---|---|
date | Wed, 12 Nov 2008 17:39:33 +0900 |
parents | 7492eb28b577 |
children | 72dcf908ec52 |
line wrap: on
line diff
--- a/TaskManager/Fifo/FifoTaskManagerImpl.cc Wed Nov 12 17:29:35 2008 +0900 +++ b/TaskManager/Fifo/FifoTaskManagerImpl.cc Wed Nov 12 17:39:33 2008 +0900 @@ -3,25 +3,235 @@ #include <string.h> #include "FifoTaskManagerImpl.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) { - TaskManagerImpl::init(); + mailManager = new MailManager(); + mailManager->init(20); + + scheduler = new MainScheduler(); + scheduler->init(); + scheduler->set_mailManager(mailManager); bufferManager = new BufferManager; bufferManager->init(); + + mainTaskList = bufferManager->create_taskList(); +} + +/** + * これは CellTaskManagerImpl から呼ばれる。 + * BufferManager は共用で使うので引数に。 + * CellTaskManagerImpl と FifoTaskManagerImpl が同時に + * 上のデータにアクセスする事は(今は)ないのでこれでおk + */ +void +FifoTaskManagerImpl::init(MainScheduler *_sched, BufferManager *buff) +{ + 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; // HTask (PPE にある) + TaskPtr task; // Task (SPE に送る Task) + + queue = activeTaskQueue; + if (queue == NULL) { + return NULL; + } + + // PPE 側で実行される TaskList + list_top = mainTaskList; + + // list_top->clear() とかの方がいいかもしれん。 + list_top = bufferManager->clear_taskList(list_top); + list = list_top; + + while (queue) { + htask = (HTaskPtr)queue->task; + d = queue; + queue = queue->next; + + task = &list->tasks[list->length++]; + +#if 0 + task->command = htask->command; + task->inData = htask->inData; + task->outData = htask->outData; + task->self = (unsigned int)htask; +#else + memcpy(task, htask, sizeof(Task)); +#endif + + if (list->length >= TASK_MAX_SIZE) { + TaskListPtr newList = bufferManager->create_taskList(); + list_top = TaskListInfo::append(list_top, newList); + list = newList; + } + + bufferManager->free_taskQueue(d); + } + + activeTaskQueue = NULL; + mainTaskList = list_top; + + return list_top; +} + + +void +FifoTaskManagerImpl::run(void) +{ + TaskListPtr list; + MailQueuePtr mail; + + list = get_runTaskList(); + + do { + // list を実行する + mail = schedule(list); + + // mail には、ppe scheduler からの mail がある + mail_check(mail); + + // 依存関係を満たしたものは実行可能キューへ + 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; + unsigned int data; + + 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) { + __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(d); + } } void -FifoTaskManagerImpl::spawn_task(HTaskPtr task) +FifoTaskManagerImpl::mail_check(MailQueuePtr mail_list, TaskQueuePtr *wait) { - TaskManagerImpl::spawn_task(task); - //run(); + waitTaskQueue = *wait; + mail_check(mail_list); } -TaskManagerImpl* +void* +FifoTaskManagerImpl::allocate(int size) +{ + return malloc(size); +} + +/** + * こういう使い方を + * Abstract Factory Pattern + * というらしい。 + */ +#ifdef __CERIUM_FIFO__ +TaskManagerImpl* create_impl(int num) { return new FifoTaskManagerImpl(); } +#endif // __CERIUM_FIFO__