Mercurial > hg > Game > Cerium
view TaskManager/Cell/spe/SchedTask.cc @ 143:9588726193e1 draft
add xml
author | gongo@charles.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Sat, 29 Nov 2008 03:36:11 +0900 |
parents | 028ffc9c0375 |
children | e3b7776b1420 |
line wrap: on
line source
#include <stdlib.h> #include <string.h> #include "SchedTask.h" #include "SchedTaskList.h" #include "SchedNop2Ready.h" #include "DmaManager.h" #include "error.h" #include "TaskManager.h" extern Scheduler::TaskObject task_list[MAX_TASK_OBJECT]; 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, ListDataPtr rbuf, ListDataPtr wbuf, Scheduler* sc) { __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__); // 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 SchedTask::exec(void) { __debug("[SchedTask:%s]\n", __FUNCTION__); // wait for load outListData __scheduler->dma_wait(DMA_READ_OUT_LIST); __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); __scheduler->dma_wait(DMA_READ); run(__readbuf, __writebuf); free(__readbuf); // 書き込む領域が要らなければ無視 if (__outListData->size > 0) { __scheduler->dma_storeList(__outListData, __writebuf, DMA_WRITE); __scheduler->dma_wait(DMA_WRITE); } if (__taskGroup->status() != 0) { __task->self = __taskGroup->command; delete __taskGroup; __taskGroup = NULL; } } void SchedTask::write(void) { __debug("[SchedTask:%s]\n", __FUNCTION__); __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 (__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(nextList, __scheduler); } } } /** * 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; } } 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) { 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); } 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); } 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); }