view TaskManager/kernel/ppe/TaskManagerImpl.cc @ 807:3763d29f41a3

merge
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 22 May 2010 18:21:13 +0900
parents 974cd68383b3 daab9cd6f91f
children 76a39ad68846
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)
    : machineNum(num) {
    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;
}

/**
 * 終了したタスクから依存の処理とか
 * 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);
}


void
TaskManagerImpl::append_waitTask(HTaskPtr q)
{
    waitTaskQueue ->addLast(q);
}

void
TaskManagerImpl::set_taskList(HTaskPtr htask, TaskListInfoPtr taskList) {
    TaskListPtr 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 = taskListImpl->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;
	*task = *(SimpleTask*)htask;
    } else {
	*task = *(SimpleTask*)htask;
    }
    if (list->length >= TASK_MAX_SIZE) {
	TaskListPtr newList = taskListImpl->create();
	taskList->addLast(newList);
	list = newList;
    }
}



/* end */