Mercurial > hg > Game > Cerium
view TaskManager/kernel/ppe/TaskManagerImpl.cc @ 833:577bde5d0cec draft
poling (may recurse..)
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 25 May 2010 18:22:59 +0900 |
parents | b3c004fe6bc3 |
children | beccb8a8bc69 |
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> static HTaskPtr systask_start; static HTaskPtr systask_finish; static void noaction(SchedTask *s, void *read, void *write) { } TaskManagerImpl::TaskManagerImpl(int num, TaskManagerImpl* o) : machineNum(num), others(o) { activeTaskQueue = new HTaskInfo(); waitTaskQueue = new HTaskInfo(); htaskImpl = waitTaskQueue ; // any HTaskInfo taskQueueImpl = new TaskQueueInfo(); } /** * 一番最初に PPE で実行される systask_start */ void TaskManagerImpl::systask_init() { systask_register(); systask_start = create_task(StartTask,0,0,0,0); systask_finish = create_task(FinishTask,0,0,0,0); systask_start->spawn(); // すべての Task が FinishTask を wait_for すると、 // あらゆる Task が FinishTask の waiting task queue を操作する // ことになる。それは、重すぎる。PPE/SPE Task が終了した時点で、 // TaskManager が実行する方が安い。 // append_waitTask(systask_finish); } HTaskPtr TaskManagerImpl::create_task(int cmd,memaddr rbuf, long r_size, memaddr wbuf, long w_size) { HTaskPtr new_task; new_task = htaskImpl->create(cmd, rbuf, r_size, wbuf, w_size); new_task->post_func = noaction; new_task->mimpl = this; return new_task; } HTaskPtr TaskManagerImpl::create_task(int cmd) { HTaskPtr new_task; // for compatibility new_task = htaskImpl->create(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; return new_task; } HTaskPtr TaskManagerImpl::create_task_array(int id, int num_task, int num_param, int num_inData, int num_outData) { HTaskPtr ta = create_task(TaskArray,0,0,0,0); ta->create_task_array(id, num_task, num_param, num_inData, num_outData) ; return ta; } /** * task の依存関係を設定 * master task が終わってから、slave task を実行するように * master->wait_for(slave); */ void TaskManagerImpl::set_task_depend(HTaskPtr master, HTaskPtr slave) { TaskQueuePtr m, s; m = taskQueueImpl->create(master); s = taskQueueImpl->create(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); } // systask_finish->wait_for(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; } /** * @brief 終了したタスクから依存の処理とか * post_func() はこのタスクが終了したら実行する関数。 * * @param [task] 終了したタスク */ void TaskManagerImpl::check_task_finish(HTaskPtr me, HTaskInfo *wait_queue) { while(TaskQueue *p = me->wait_me->poll()) { HTaskPtr you = p->task; TaskQueueInfo *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); } htaskImpl->free_(me); } /** * @brief 終了したタスクリストの依存の処理 * @param [task] 終了したタスク */ void TaskManagerImpl::check_task_list_finish(SchedTask *s, TaskListPtr list, HTaskInfo *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, TaskListInfoPtr 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 */