view TaskManager/kernel/ppe/TaskManagerImpl.cc @ 518:125a72948e44

....
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 16 Oct 2009 17:57:17 +0900
parents 735f76483bb2
children 5c76db2a07fa
line wrap: on
line source

#include <stdio.h>
#include "TaskManagerImpl.h"
#include "SchedTask.h"
#include "SchedTaskManager.h"
#include "types.h"
#include "error.h"
#include "../sys_task/SysTask.h"

static HTaskPtr systask_start;
static HTaskPtr systask_finish;

TaskManagerImpl::TaskManagerImpl(int num)
    : machineNum(num) {
    activeTaskQueue = new HTaskInfo();
    waitTaskQueue = new HTaskInfo();
    htaskImpl = waitTaskQueue ;             // any HTaskInfo
    taskQueueImpl = new TaskQueueInfo(); 
}

static void
noaction(SchedTask *s, void *read, void *write)
{
}

/**
 * 一番最初に PPE で実行される systask_start
 * 一番最後に、全てのタスクの終了を待つ systask_finish
 * 番兵的な意味で実装
 */
void
TaskManagerImpl::systask_init()
{
    systask_register();

    schedTaskManager = new SchedTaskManager(this);

    systask_start = create_task(SYSTASK_START);
    systask_finish = create_task(SYSTASK_FINISH);

    systask_start->spawn();

    // systask_finish で spawn すると
    //   systask_finish->wait_for(systask_finish);
    // とかなって無限ループになるので、
    // これだけは明示的に append_waitTask() で
    append_waitTask(systask_finish);
}

HTaskPtr
TaskManagerImpl::create_task(int cmd)
{
    HTaskPtr new_task;

    new_task = htaskImpl->create(cmd);
    new_task->post_func = noaction;
    new_task->mimpl = this;

    return new_task;
}

/**
 * タスクを実行可能キューまたは待機キューへ追加する。
 * 依存関係が満たされていれば 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);
}

/**
 * 終了したタスクから依存の処理とか
 * post_func() はこのタスクが終了したら実行する関数。
 *
 * @param [task] 終了したタスク
 */
void
TaskManagerImpl::check_task_finish(HTaskPtr me)
{
    // post_func を先に実行しないと、systask_finish が active_queue
    // 移されてから、wait_for されるという事態が起きることがある。

    me->post_func(schedTaskManager, me->post_arg1,me->post_arg2);

    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()) {
	    waitTaskQueue->remove(you);
	    append_activeTask(you);
	}

	wait_i->free_(p);
    }

    htaskImpl->free_(me);
}


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

/**
 * waitQueue の中で依存関係を満たしたタスクは
 * activeQueue へ移す
 */
void
TaskManagerImpl::wakeup_waitTask()
{
  // done in check_task_finish   
}

/* end */