Mercurial > hg > Game > Cerium
view TaskManager/kernel/ppe/TaskManagerImpl.cc @ 1142:801d57ae1e29 draft
cut compile CreatePolygonTask on spe side because not enough spe memory. We have to use code loading.
And I found light error. see you tomorrow. (This version can work Mac OSX and Cell arch.)
author | yutaka@localhost.localdomain |
---|---|
date | Thu, 17 Feb 2011 05:23:34 +0900 |
parents | 23dab670c5aa |
children | 279b41354753 |
line wrap: on
line source
//#include <stdio.h> #include "TaskManagerImpl.h" #include "types.h" #include "error.h" #include "SchedTask.h" #include "Scheduler.h" #include "SysTask.h" #include "SysFunc.h" #include <string.h> // singleton QueueInfo<TaskQueue> *taskQueuePool = new QueueInfo<TaskQueue>() ; QueueInfo<HTask> *htaskPool = new QueueInfo<HTask>() ; QueueInfo<TaskList> *taskListPool = new QueueInfo<TaskList>() ; static HTaskPtr systask_start; static HTaskPtr systask_finish; static void noaction(SchedTask *s, void *read, void *write) { } TaskManagerImpl::TaskManagerImpl(int num) : machineNum(num){ // 実行可能なHTaskのリスト activeTaskQueue = new QueueInfo<HTask>(htaskPool); // wait_forで止まっているHTaskのリスト。必要ないが、Dead lock detection に使う waitTaskQueue = new QueueInfo<HTask>(htaskPool); // HTask の factory. QueueInfo<HTask> ならなんでもいい。 htaskImpl = waitTaskQueue ; // any QueueInfo<HTask> // Task の dependency を表現する double linked list. QueueInfo<HTask> とは別に必要。 taskQueueImpl = new QueueInfo<TaskQueue>(taskQueuePool); } /** * 一番最初に PPE で実行される systask_start */ void TaskManagerImpl::systask_init() { systask_register(); systask_start = create_task(StartTask,0,0,0,0,__builtin_return_address(0)); systask_finish = create_task(FinishTask,0,0,0,0,__builtin_return_address(0)); systask_start->spawn(); // すべての Task が FinishTask を wait_for すると、 // あらゆる Task が FinishTask の waiting task queue を操作する // ことになる。それは、重すぎる。PPE/SPE Task が終了した時点で、 // TaskManager が実行する方が安い。 // append_waitTask(systask_finish); } /** * Create Simple Task */ HTaskPtr TaskManagerImpl::create_task(int cmd,memaddr rbuf, long r_size, memaddr wbuf, long w_size, void *from) { HTaskPtr new_task; new_task = htaskImpl->create(); new_task->init(cmd, rbuf, r_size, wbuf, w_size); new_task->post_func = noaction; new_task->mimpl = this; new_task->from = (memaddr)from; #ifdef EARLY_TOUCH if (rbuf) { if ((unsigned long)rbuf&0xf) { this->printf("Data is not aligned. command = %d, addr = 0x%lx, size = %ld\n", cmd, (unsigned long)rbuf, r_size); } char *p = (char *)rbuf; char b = *p; p = (char *)(rbuf+r_size-1); b += *p; } if (wbuf) { if ((unsigned long)wbuf&0xf) { this->printf("Data is not aligned. command = %d, addr = 0x%lx, size = %ld\n", cmd, (unsigned long)wbuf, w_size); } char *p = (char *)wbuf; char b = *p; p = (char *)(wbuf+w_size-1); b += *p; } #endif return new_task; } /** * Create Compatible Task (TaskArray1) */ HTaskPtr TaskManagerImpl::create_task(int cmd,void *from) { HTaskPtr new_task; // for compatibility new_task = htaskImpl->create(); new_task->init(TaskArray1); new_task->post_func = noaction; new_task->mimpl = this; new_task->create_task_array(cmd,1,8,8,8); // rbuf, r_size were set new_task->command = TaskArray1; new_task->from = (memaddr)from; return new_task; } /** * Create Task Array */ HTaskPtr TaskManagerImpl::create_task_array(int id, int num_task, int num_param, int num_inData, int num_outData, void *from) { HTaskPtr ta = create_task(TaskArray,0,0,0,0, from); ta->create_task_array(id, num_task, num_param, num_inData, num_outData) ; return ta; } /* call get_task_name from ppu only */ const char * TaskManagerImpl::get_task_name(int cmd) { if (0 <= cmd && cmd < MAX_TASK_OBJECT) return task_list[cmd].name; else return NULL; } const char * TaskManagerImpl::get_task_name(TaskPtr task) { return task != NULL ? get_task_name(task->command) : NULL; } const char * TaskManagerImpl::get_task_name(SimpleTaskPtr simple_task) { return simple_task != NULL ? get_task_name(simple_task->command) : NULL; } const char * TaskManagerImpl::get_task_name(SchedTaskBase *sched_task) { if (sched_task == NULL) return NULL; if (sched_task->task != NULL) { return get_task_name(sched_task->task->command); } else if (sched_task->atask != NULL) { return get_task_name(sched_task->atask->command); } return NULL; } const char * TaskManagerImpl::get_task_name(HTaskPtr htask) { return get_task_name(htask, 0); } const char * TaskManagerImpl::get_task_name(HTaskPtr htask, int index) { if (!htask) return NULL; switch (htask->command) { case TaskArray1: return get_task_name((TaskPtr)htask->rbuf); break; case TaskArray: { HTaskPtr t = htask->next; for (int i = 0; i < index; i++) { if (!t->next) return NULL; t = t->next; } return get_task_name(t->command); break; } default: return get_task_name(htask->command); } return NULL; } /** * task の依存関係を設定 * master task が終わってから、slave task を実行するように * master->wait_for(slave); */ void TaskManagerImpl::set_task_depend(HTaskPtr master, HTaskPtr slave) { TaskQueuePtr m, s; if (!master->self) return; m = taskQueueImpl->create(); m->init(master); s = taskQueueImpl->create(); s->init(slave); master->wait_me->addLast(s); slave->wait_i->addLast(m); s->waiter = m; } /** * タスクを実行可能キューまたは待機キューへ追加する。 * 依存関係が満たされていれば active, まだだったら wait へ。 * task->spawn(); */ void TaskManagerImpl::spawn_task(HTaskPtr task) { // waiter // master // waitee // slave if (task->wait_i->empty()) { append_activeTask(task); } else { append_waitTask(task); } } /** * Task を実行可能キューに追加する */ void TaskManagerImpl::append_activeTask(HTaskPtr q) { activeTaskQueue->addLast(q); } /** * タスクが実行する CPU を選択する * * 現在は CPU_PPE, CPU_SPE, SPE_ANY, SPE_0, SPE_1, ..., SPE_5 * types.h に書いてます。 */ void TaskManagerImpl::set_task_cpu(HTaskPtr task, CPU_TYPE type) { if (machineNum==0) task->cpu_type = CPU_PPE ; else task->cpu_type = type; } #if 0 static void check_wait(TaskManagerImpl *tm, QueueInfo<TaskQueue> *wait_i) { for(TaskQueue *t = wait_i->getFirst(); t; t = wait_i->getNext(t)) { if (!tm->waitTaskQueue->find(t->task)) { this->printf("stray waiting task%d %lx\n",t->task->command, (long)t->task); } else if (tm->activeTaskQueue->find(t->task)) { this->printf(" active task%d in waiting queue %lx\n",t->task->command, (long)t->task); } else this->printf("."); } } #endif /** * @brief 終了したタスクから依存の処理とか * post_func() はこのタスクが終了したら実行する関数。 * * @param [task] 終了したタスク */ void TaskManagerImpl::check_task_finish(HTaskPtr me, QueueInfo<HTask> *wait_queue) { while(TaskQueue *p = me->wait_me->poll()) { HTaskPtr you = p->task; QueueInfo<TaskQueue> *wait_i = you->wait_i; // 相手の wait queue から自分(を指しているTaskQueue)を削除 wait_i->remove(p->waiter); // queue を free する wait_i->free_(p->waiter); if (wait_i->empty()) { wait_queue->remove(you); append_activeTask(you); } wait_i->free_(p); // p->wait_i, p->wait_me は再利用される } // me を誰かが持っていて、me が finish した後に、 // me->wait_for(i) とか、やられると気まずい。 // 特に、me が他人に再利用されていると。そういう時には、 // このfreeをコメントアウトしてみる。 // id かななんかでチェックした方が良いが... me->self = 0; if (!me->flag.no_auto_free) htaskImpl->free_(me); } /** * @brief 終了したタスクリストの依存の処理 * @param [task] 終了したタスク */ void TaskManagerImpl::check_task_list_finish(SchedTask *s, TaskListPtr list, QueueInfo<HTask> *wait_queue) { for(int i = 0;i<list->length;i++) { SimpleTaskPtr task = &list->tasks[i]; HTask *me = (HTask*)task->self; me->post_func(s, me->post_arg1, me->post_arg2); if (task->command==TaskArray1) { int next = ((task->r_size)/sizeof(SimpleTask))+1; // assert(next<list->length); i+=next; } s->polling(); check_task_finish(me, wait_queue); } } /** * @brief waitTaskqueue への挿入 。必須ではない。 * 現状では、dead lock 検出にしか使ってない * * @param [task] 終了したタスク */ void TaskManagerImpl::append_waitTask(HTaskPtr q) { waitTaskQueue ->addLast(q); } /** @brief htask を DMA でCPUに渡すための TaskList に入れる (copy) @param htask @param taskList TaskList は自動的に延長される */ void TaskManagerImpl::set_taskList(HTaskPtr htask, QueueInfo<TaskList> * taskList) { TaskListPtr list ; if ( taskList->empty() ) { list = taskList->create(); taskList->addLast(list); } else list = taskList->getLast(); SimpleTaskPtr task = &list->tasks[list->length++]; if (htask->command==TaskArray1) { // compatibility int next = ((htask->r_size)/sizeof(SimpleTask))+1; if (list->length+next>=TASK_MAX_SIZE) { list->length--; TaskListPtr newList = taskList->create(); taskList->addLast(newList); list = newList; task = &list->tasks[list->length++]; } Task *array = (Task*)&list->tasks[list->length]; list->length += next; if (list->length>=TASK_MAX_SIZE) { perror("task array1 overflow\n"); } memcpy(array, htask->rbuf, htask->r_size); free(htask->rbuf); // htask->rbuf = 0; htask->r_size = 0; we need this... *task = *(SimpleTask*)htask; } else { *task = *(SimpleTask*)htask; } if (list->length >= TASK_MAX_SIZE) { TaskListPtr newList = taskList->create(); taskList->addLast(newList); list = newList; } } /* end */