view TaskManager/Fifo/FifoTaskManagerImpl.cc @ 674:bde5f13adf10

fix many task example (sort). Dummy task is now system supported.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 06 Dec 2009 00:54:10 +0900
parents d9111086b2c4
children b386522827ae
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "FifoTaskManagerImpl.h"
#include "Scheduler.h"
#include "SchedTask.h"
#include "types.h"
#include "error.h"

FifoTaskManagerImpl::~FifoTaskManagerImpl()
{
    delete mainScheduler;

    delete taskListImpl  ;
    delete taskQueueImpl ;
    delete htaskImpl     ;

}

/**
 * MailManager は PPE スケジューラとのメール交換、
 * FifoScheduler は PPE 側のスケジューラ
 * BufferManager は Task、TaskList などのメモリ管理(大層なことしてないが
 */
void
FifoTaskManagerImpl::init()
{
    mainScheduler = new MainScheduler();
    mainScheduler->init(this);
    mainScheduler->id = 0;
    set_scheduler(mainScheduler);

    taskListImpl  = new TaskListInfo;
    taskQueueImpl = new TaskQueueInfo;
    htaskImpl     = new HTaskInfo();

    mainTaskList = taskListImpl->create();

    schedTaskManager = new SchedTask();
    schedTaskManager->init(0,0,0,mainScheduler);

}

/**
 * これは CellTaskManagerImpl から呼ばれる。
 * TaskList等 は共用で使うので引数に。
 * CellTaskManagerImpl と FifoTaskManagerImpl が同時に
 * 上のデータにアクセスする事は(今は)ないのでこれでおk
 */
void
FifoTaskManagerImpl::init(MainScheduler *_sched, TaskManagerImpl *tm)
{

    mainScheduler = _sched;
    mainScheduler->init(this);
    set_scheduler(mainScheduler);

    taskListImpl  = tm-> taskListImpl  ;
    taskQueueImpl = tm-> taskQueueImpl ;
    htaskImpl     = tm-> htaskImpl     ;
    waitTaskQueue     = NULL;   // mail_check で外から設定される

    mainTaskList = taskListImpl->create();

    schedTaskManager = new SchedTask();
    schedTaskManager->init(0,0,0,mainScheduler);

}

void FifoTaskManagerImpl::show_profile() {
    printf("HEHEHEHEH\n");
}
void FifoTaskManagerImpl::start_profile() {}

/**
 * スケジューラに渡す TaskList を取得する。
 *
 * @return 実行タスクリスト
 *
 * ActiveTaskQueue (依存条件は満たし済み) のタスクを
 * 実行タスクリストに入れる
 */
TaskListPtr
FifoTaskManagerImpl::get_runTaskList()
{
    TaskListPtr list, list_top;
#ifdef SIMPLE_TASK
    SimpleTaskPtr task; // Task (SPE に送る Task)
#else
    TaskPtr task; // Task (SPE に送る Task)
#endif

    if (activeTaskQueue->empty()) {
        return NULL;
    }

    // PPE 側で実行される TaskList
    list_top = mainTaskList;

    // list_top->clear() とかの方がいいかもしれん。
    list_top = taskListImpl->clear_taskList(list_top);
    list = list_top;

    // printf("active task queue length = %d\n",activeTaskQueue->length());
    while (HTaskPtr htask = activeTaskQueue->poll()) {
        task = &list->tasks[list->length++];
#ifdef SIMPLE_TASK
	*task = *(SimpleTask*)htask;
#else
        memcpy(task, (Task*)htask, sizeof(Task));
#endif
        if (list->length >= TASK_MAX_SIZE) {
            TaskListPtr newList = taskListImpl->create();
            list_top = TaskListInfo::append(list_top, newList);
            list = newList;
        }
        // activeTaskQueue->free_(htask); ここで free しないで、
        // mail を待つ
    }

    mainTaskList = list_top;

    return list_top;
}


void
FifoTaskManagerImpl::run()
{
    TaskListPtr list;

    list = get_runTaskList();

    do {
        // list を実行する
        schedule(list);

        // ppe scheduler からの mail を調べる
        mail_check(waitTaskQueue);

        // 依存関係を満たしたものは実行可能キューへ
        wakeup_waitTask();
        list = get_runTaskList();
    } while (list);
}

/**
 * @param [list] 実行タスクリスト
 * @return FifoScheduler からのメール
 *
 * [Tasklist] -> [番兵] -> scheduler->run を抜ける
 */
void
FifoTaskManagerImpl::schedule(TaskListPtr list)
{
    if (list) {
	// TaskList のアドレスを送る
	mainScheduler->mail_write_from_host((memaddr)list);

	// EXIT_COMMAND (番兵的な意味で)
	//   これを読むと、mainScheduler->run() から抜けて来る。
	mainScheduler->mail_write_from_host((memaddr)MY_SPE_COMMAND_EXIT);

	// scheduler は受け取ったメールを元に実行する
	mainScheduler->run();
    }
}

/**
 * PPE Scheduler からのメールをチェックする
 *
 * @param [mail_list]
 *        PPE 側で動く Scheduler からのメールリスト
 *        終了した Task や、その他(今はまだ実装してないけど)の情報が入ってる
 *
 * @return Scheduler が次に実行する Task List
 *         NULL なら全てのタスクが実行終了したということ
 */
void
FifoTaskManagerImpl::mail_check(HTaskInfo *wait_queue)
{
    while (mainScheduler->has_mail_from_host()) {
	memaddr data = mainScheduler->mail_read_from_host();

        if (data == (memaddr)MY_SPE_STATUS_READY) {
            __debug_ppe("mail_check(): Task List finish\n");
        } else if (data == (memaddr)MY_SPE_COMMAND_EXIT) {
            __debug_ppe("mail_check(): Task List finish COMMAND\n");
        } else if (data != (memaddr)MY_SPE_NOP) {
            __debug_ppe("mail_check(): recv from 0x%x\n", data);
	    // post_func を先に実行しないと、systask_finish が active_queue
	    // 移されてから、wait_for されるという事態が起きることがある。
            HTaskPtr task = (HTaskPtr)data;
            task->post_func(schedTaskManager, task->post_arg1, task->post_arg2);
            check_task_finish(task, wait_queue);
        }
    }
}


/**
 * # # # # # # # # 
 *   Abstract Factory Pattern
 * # # # # # # # 
 */
#ifdef __CERIUM_FIFO__
TaskManagerImpl*
create_impl(int num)
{
    return new FifoTaskManagerImpl();
}
#endif // __CERIUM_FIFO__