view TaskManager/Fifo/FifoTaskManagerImpl.cc @ 0:04e28d8d3c6f

first commit
author Daiki KINJYO <e085722@ie.u-ryukyu.ac.jp>
date Mon, 08 Nov 2010 01:23:25 +0900
parents
children
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "FifoTaskManagerImpl.h"
#include "QueueInfo.h"
#include "TaskList.h"
#include "Scheduler.h"
#include "SchedTask.h"
#include "types.h"
#include "error.h"
#include "SchedNop.h"
#include "SysFunc.h"

extern  QueueInfo<TaskList> *taskListPool;

// static void send_alloc_reply(FifoTaskManagerImpl *tm, int id, MainScheduler *s);

FifoTaskManagerImpl::~FifoTaskManagerImpl()
{
    delete mainScheduler;

    delete taskQueueImpl ;
    delete htaskImpl     ;

}

/**
 * FifoTaskManager 単独で走るときの初期化
 * MailManager は PPE スケジューラとのメール交換、
 * FifoScheduler は PPE 側のスケジューラ
 */
void
FifoTaskManagerImpl::init()
{
    // TaskManager から呼ばれるので、かなりの部分は初期化されている。

    mainScheduler = new MainScheduler();
    mainScheduler->init(this);
    mainScheduler->id = 0;
    set_scheduler(mainScheduler);

    taskListInfo  = new QueueInfo<TaskList>(taskListPool);
    ppeTaskList  = new QueueInfo<TaskList>(taskListPool);

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

}

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

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

    taskQueueImpl = tm-> taskQueueImpl ;
    htaskImpl     = tm-> htaskImpl     ;
    waitTaskQueue     = tm->waitTaskQueue;   

    taskListInfo  = new QueueInfo<TaskList>(taskListPool);
    ppeTaskList  = new QueueInfo<TaskList>(taskListPool);

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

}

// void FifoTaskManagerImpl::show_profile() {}
// void FifoTaskManagerImpl::start_profile() {}

/**
 * スケジューラに渡す TaskList を取得する。
 *
 * @return 実行タスクリスト
 *
 * ActiveTaskQueue (依存条件は満たし済み) のタスクを
 * 実行タスクリストに入れる
 */
void
FifoTaskManagerImpl::set_runTaskList()
{
    // printf("active task queue length = %d\n",activeTaskQueue->length());
    while (HTaskPtr htask = activeTaskQueue->poll()) {
	set_taskList(htask, taskListInfo );
    }
}

void
FifoTaskManagerImpl::poll()
{
    set_runTaskList();
    // list を実行する
    sendTaskList();
    // ppe scheduler からの mail を調べる
    mail_check();
}

void
FifoTaskManagerImpl::run()
{
    do {
	poll();
    } while(!activeTaskQueue->empty()) ;

    if (!waitTaskQueue->empty()) {
        get_scheduler()->printf("Dead lock detected\n");
    }
}

/**
 * @param [list] 実行タスクリスト
 * @return FifoScheduler からのメール
 *
 * [Tasklist] -> [番兵] -> scheduler->run を抜ける
 */
void
FifoTaskManagerImpl::sendTaskList()
{
    if (taskListInfo->empty()) return;
    // ppeTaskList は走り終わった ppe の Task の List. 
    // taskListInfo はこれから走る Task の List. 
    // 交換して実行する
    QueueInfo<TaskList>* tmp = ppeTaskList;
    ppeTaskList = taskListInfo;
    taskListInfo = tmp;
    // ppeTaskList は本来は循環リストなのだけど、実行中は線形リストである。
    // なので、最後に 0 を代入する. 後でなおす。
    ppeTaskList->getLast()->next = 0;
    // TaskList のアドレスを送る
    mainScheduler->mail_write_from_host((memaddr)ppeTaskList->getFirst());

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

    // scheduler は受け取ったメールを元に実行する
    mainScheduler->run(new SchedNop());
    // すべてのlistを実行するまで戻らない

    ppeTaskList->getLast()->next = ppeTaskList;

}

/**
 * PPE Scheduler からのメールをチェックする
 *
 * @param [mail_list]
 *        PPE 側で動く Scheduler からのメールリスト
 *        終了した Task や、その他(今はまだ実装してないけど)の情報が入ってる
 *
 * @return Scheduler が次に実行する Task List
 *         NULL なら全てのタスクが実行終了したということ
 */
void
FifoTaskManagerImpl::mail_check()
{
    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");
	    ppeTaskList->freeAll(); 
        } else if (data == (memaddr)MY_SPE_COMMAND_EXIT) {
            __debug_ppe("mail_check(): Task List finish COMMAND\n");
	} else if (data == (memaddr)MY_SPE_COMMAND_MALLOC) {
	    // MY_SPE_COMMAND_MALLOC   PPE からのmain memory request
	    // 本来は呼ばれないはず...
	    get_scheduler()->printf("error: MY_SPE_COMMAND_MALLOC from PPE\n");
	    // send_alloc_reply(this, 0, mainScheduler);
        } 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 されるという事態が起きることがある。
#ifdef TASK_LIST_MAIL
            TaskListPtr list = (TaskListPtr)data;
            check_task_list_finish(schedTaskManager, list, waitTaskQueue);
#else
            HTaskPtr task = (HTaskPtr)data;
            task->post_func(schedTaskManager, task->post_arg1, task->post_arg2);
            check_task_finish(task, waitTaskQueue);
#endif
        }
    }
}

void
FifoTaskManagerImpl::polling()
{
    if (others!=0)
	others->polling();
}

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