Mercurial > hg > Game > Cerium
diff TaskManager/kernel/schedule/SchedTask.cc @ 109:028ffc9c0375 draft
Cerium cvs version
author | gongo@gendarme.local |
---|---|
date | Wed, 12 Nov 2008 17:39:33 +0900 |
parents | 3e331f7576a1 |
children | e3b7776b1420 |
line wrap: on
line diff
--- a/TaskManager/kernel/schedule/SchedTask.cc Wed Nov 12 17:29:35 2008 +0900 +++ b/TaskManager/kernel/schedule/SchedTask.cc Wed Nov 12 17:39:33 2008 +0900 @@ -1,29 +1,113 @@ +#include <stdlib.h> +#include <string.h> #include "SchedTask.h" #include "SchedTaskList.h" #include "SchedNop2Ready.h" #include "DmaManager.h" #include "error.h" #include "TaskManager.h" -#include "SymTable.h" + +extern Scheduler::TaskObject task_list[MAX_TASK_OBJECT]; -SymTable *TaskManager::symtb; +SchedTask* +CreateSchedTask(TaskListPtr taskList, Scheduler *sched) +{ + TaskPtr task = &taskList->tasks[sched->curIndex_taskList++]; + + return task_list[task->command](taskList, task, sched->get_curReadBuf(), + sched->get_curWriteBuf(), sched); +} -SchedTask::SchedTask(TaskListPtr _list, TaskPtr _task, void *rbuf, void *wbuf, - DmaManager* cn) +SchedTask::SchedTask(TaskListPtr _list, TaskPtr _task, ListDataPtr rbuf, + ListDataPtr wbuf, Scheduler* sc) { - list = _list; - task = _task; - readbuf = rbuf; - writebuf = wbuf; - connector = cn; + __list = _list; + __task = _task; + __inListData = rbuf; + __outListData = wbuf; + __readbuf = NULL; + __writebuf = NULL; + __scheduler = sc; + __taskGroup = NULL; + __renew_flag = 0; + + smanager = new STaskManager(this); } +SchedTask::~SchedTask(void) +{ + if (__flag_renewTask) { + /** + * __inListData と __outListData はタスク自身のものなので + * 終わったら即 free する。 + */ + free(__inListData); + free(__outListData); + + /** + * __list != NULL の場合、 + * この Task が __list の最後の Task になるので (SchedTask::next 参照) + * このタイミングで __list を解放する + * (free に渡されるアドレスが正しいものとなる)。 + * それ以外の Task では当然解放しない。 + * __list == NULL なので、free に渡しても無問題 + */ + free(__list); + } + + delete smanager; +} + +void +SchedTask::__init__(void) +{ + /** + * task->inData や task->outData が + * PPE のものか、SPE のものかって + * アドレスで判定できれば楽になると思うんだが。。。 + */ + /** + * 関数ポインタでやるか・・? + */ + if (__flag_renewTask == 0) { + __scheduler->dma_load(__inListData, (uint32)__task->inData, + sizeof(ListData), DMA_READ_IN_LIST); + __scheduler->dma_load(__outListData, (uint32)__task->outData, + sizeof(ListData), DMA_READ_OUT_LIST); + + __taskGroup = new TaskGroup; + __taskGroup->command = __task->self; + } else { + __inListData = __task->inData; + __outListData = __task->outData; + __taskGroup = (TaskGroupPtr)__task->self; + } +} + + +/** + * [Todo] + * データの読み込み場所を readbuf ではなく、 + * ユーザ自身で決めれるようになるといいかもしれない。 + * + * # TaskManager が勝手に消すことなく、 + * # ユーザが SPE 上に持ち続けることができるため。 + * # もちろん管理はユーザに任せるわけだ。 + */ void SchedTask::read(void) { __debug("[SchedTask:%s]\n", __FUNCTION__); - connector->dma_load(readbuf, task->in_addr, task->in_size, DMA_READ); + // wait for load inListData + __scheduler->dma_wait(DMA_READ_IN_LIST); + + // 読むデータが一つもなければ無視 + if (__inListData->length < 1 || __inListData->size == 0) return; + + // load Input Data + __readbuf = __scheduler->allocate(__inListData->size); + __scheduler->dma_loadList(__inListData, __readbuf, DMA_READ); } void @@ -31,26 +115,33 @@ { __debug("[SchedTask:%s]\n", __FUNCTION__); - connector->dma_wait(DMA_READ); + // wait for load outListData + __scheduler->dma_wait(DMA_READ_OUT_LIST); + __scheduler->dma_wait(DMA_READ); + + __writebuf = __scheduler->allocate(__outListData->size); - __debug(" task->command = %d\n", task->command); - __debug(" task->in_size = %d\n", task->in_size); - __debug(" task->in_addr = 0x%x\n", task->in_addr); - __debug(" task->out_addr = 0x%x\n", task->out_addr); - __debug(" list->next = 0x%x\n", (unsigned int)list->next); - __debug(" list->length = 0x%x\n", (unsigned int)list->length); + __debug(" task->command = %d\n", __task->command); + __debug(" task->in_size = %d\n", __task->in_size); + __debug(" task->in_addr = 0x%x\n", __task->in_addr); + __debug(" task->out_addr = 0x%x\n", __task->out_addr); + __debug(" list->next = 0x%x\n", (unsigned int)__list->next); + __debug(" list->length = 0x%x\n", (unsigned int)__list->length); - // obsolute - // task->in_size = func_list[task->command](writebuf, readbuf); + run(__readbuf, __writebuf); + + // 書き込む領域が要らなければ無視 + if (__outListData->size > 0) { + __scheduler->dma_storeList(__outListData, __writebuf, DMA_WRITE); + } - // ごちゃごちゃしてるな - // 最初から void* じゃなくて 関数ポインタ としていれるべきか? - //int (*func)(void*, void*) - //= (int (*)(void*,void*))TaskManager::get_address(task->command); - SymTable::FuncObject func = TaskManager::get_address(task->command); - task->in_size = func(readbuf, writebuf); - //task->in_size = func((void*)task->in_addr, (void*)task->out_addr); - connector->dma_store(writebuf, task->out_addr, task->in_size, DMA_WRITE); + if (__taskGroup->status() != 0) { + __task->self = __taskGroup->command; + delete __taskGroup; + __taskGroup = NULL; + } + + free(__readbuf); } void @@ -58,45 +149,174 @@ { __debug("[SchedTask:%s]\n", __FUNCTION__); - connector->dma_wait(DMA_WRITE); - connector->mail_write((unsigned int)task->self); + __scheduler->dma_wait(DMA_WRITE); + + free(__writebuf); + + /** + * タスクが生成されている場合、 + * そのタスクが終わってからこのタスク終了コマンドを送る。 + * # コマンドは生成されたタスクに引き継がれる + */ + if (__task->self == MY_SPE_NOP) return; + + if (__flag_renewTask) { + uint32 cmd; + + __taskGroup->remove(__task); + cmd = __taskGroup->status(); + + if (cmd != 0) { + delete __taskGroup; + __scheduler->mail_write(cmd); + } + } else { + if (__renew_flag == 0) { + __scheduler->mail_write(__task->self); + } + } } - + SchedTaskBase* SchedTask::next(Scheduler *m, SchedTaskBase *p) { __debug("[SchedTask:%s]\n", __FUNCTION__); delete p; - - // ここ直さねば。どうやって if 文消そう? - // オブジェクト増やせばいいのかな - if (list->length == 0) { - if (list->next == 0) { - return new SchedNop2Ready(connector); + + if (__scheduler->curIndex_taskList < __list->length) { + SchedTask* schedTask = CreateSchedTask(__list, __scheduler); + schedTask->__flag_renewTask = this->__flag_renewTask; + schedTask->__init__(); + + /** + * この理由は SchedTask:~SchedTask() で + */ + __list = NULL; + + return schedTask; + } else { + uint32 nextList = (uint32)__list->next; + + if (nextList == 0) { + return new SchedNop2Ready(__scheduler); } else { - return new SchedTaskList((unsigned int)list->next, - m->get_curListBuf(), connector); + return new SchedTaskList(nextList, __scheduler); } - } else { - //return new SchedTask(list, m->get_curReadBuf(), - //m->get_curWriteBuf(), connector); + } +} - // 本当は、ここで task->command に対応する、 - // SchedTask を継承する class を作ればいい。。。はず - return new SchedTask(list, &list->tasks[--list->length], - m->get_curReadBuf(), m->get_curWriteBuf(), - connector); +/** + * task->add_input で与えられた順番に対応する index (0〜n-1) で、 + * buffer から対応するデータを返す。 + */ +void* +SchedTask::get_input(void *buff, int index) +{ + if (buff != NULL) { + return (void*)((int)buff + __inListData->bound[index]); + } else { + return NULL; + } +} + +/** + * write buffer の領域を返す。 + */ +void* +SchedTask::get_output(void *buff, int index) +{ + if (buff != NULL) { + return (void*)((int)buff + __outListData->bound[index]); + } else { + return NULL; } } -#if 0 -SchedTask -createSchedTask(TaskListPtr list, void *rbuf, void *wbuf, DmaManager *cn) +int +SchedTask::get_param(int index) +{ + return __task->param[index]; +} + +TaskPtr +SchedTask::create_task(int cmd) +{ + TaskListPtr taskList = __scheduler->get_renewListBuf(); + TaskPtr p = &taskList->tasks[taskList->length++]; + p->command = cmd; + + p->inData = (ListData*)__scheduler->allocate(sizeof(ListData)); + p->outData = (ListData*)__scheduler->allocate(sizeof(ListData)); + + p->inData->clear(); + p->outData->clear(); + + p->self = MY_SPE_NOP; + p->param_size = 0; + + return p; +} + +/** + * 名前が。。。 + */ +void +SchedTask::wait_task(TaskPtr waitTask) { - TaskPtr task; + waitTask->self = (uint32)__taskGroup; + + __scheduler->add_groupTask(__taskGroup, waitTask); + + __renew_flag++; +} + +void* +SchedTask::global_alloc(int id, int size) { + return __scheduler->global_alloc(id, size); +} + +void* +SchedTask::global_get(int id) { + return __scheduler->global_get(id); +} + +void +SchedTask::global_free(int id) { + __scheduler->global_free(id); +} + +void +SchedTask::mainMem_alloc(int id, int size) { + __scheduler->mainMem_alloc(id, size); +} - task = &list->tasks[--list->length]; - +void +SchedTask::mainMem_wait(void) { + __scheduler->mainMem_wait(); +} + +void* +SchedTask::mainMem_get(int id) { + return __scheduler->mainMem_get(id); +} + +void* +SchedTask::allocate(int size) { + return __scheduler->allocate(size); } -#endif + +void +SchedTask::dma_load(void *buf, uint32 addr, uint32 size, uint32 mask) { + __scheduler->dma_load(buf, addr, size, mask); +} + +void +SchedTask::dma_store(void *buf,uint32 addr, uint32 size, uint32 mask) { + __scheduler->dma_store(buf, addr, size, mask); +} + +void +SchedTask::dma_wait(uint32 mask) { + __scheduler->dma_wait(mask); +}