view TaskManager/Fifo/FifoTaskManagerImpl.cc @ 603:42c94f85c779

long -> memaddr (64 or 32)
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 07 Nov 2009 14:13:29 +0900
parents 1733f3cbfa28
children 0decff4e867b
line wrap: on
line source

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

FifoTaskManagerImpl::~FifoTaskManagerImpl()
{
    delete mailManager;
    delete scheduler;

    delete taskListImpl  ;
    delete taskQueueImpl ;
    delete htaskImpl     ;

}

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

    scheduler = new MainScheduler();
    scheduler->init();
    scheduler->set_mailManager(mailManager);
    scheduler->id = 0;

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

    mainTaskList = taskListImpl->create();

}

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

    //scheduler = new MainScheduler();
    scheduler = _sched;
    scheduler->init();
    scheduler->set_mailManager(mailManager);

    taskListImpl  = tm-> taskListImpl  ;
    taskQueueImpl = tm-> taskQueueImpl ;
    htaskImpl     = tm-> htaskImpl     ;
    waitTaskQueue     = NULL;   // mail_check で外から設定される
//    waitTaskQueue     = tm->waitTaskQueue; 
//    activeTaskQueue     = NULL; // CellTaskManagerImple 側を使う

    // waitTaskQueue     = tm->waitTaskQueue; 
    // activeQueue は?

    mainTaskList = taskListImpl->create();


}

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

    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++];
#if 0
        task->command  = htask->command;
        task->inData   = htask->inData;
        task->outData  = htask->outData;
        task->self     = (unsigned int)htask;
	// param は?
#else
	// inData, outData を内蔵にしたので実は、結構でかくない?
	// 268 byte 程度だが... 不要な分(設定してない inData, outData, param 
        // とかもコピーしてるね。rbuf/wbuf の意味を変えてしまったわけか。
        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;
    MailQueuePtr mail;

    list = get_runTaskList();

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

        // mail には、ppe scheduler からの mail がある
        mail_check(mail);

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

/**
 * @param [list] 実行タスクリスト
 * @return FifoScheduler からのメール
 *
 * [Tasklist] -> [番兵] -> scheduler->run を抜ける
 */
MailQueuePtr
FifoTaskManagerImpl::schedule(TaskListPtr list)
{
    MailQueuePtr list_mail; // task list
    MailQueuePtr sentinel;  // 番兵
    MailQueuePtr in_mail_list = NULL;
    MailQueuePtr out_mail_list = NULL;

    // TaskList のアドレス
    list_mail = mailManager->create((memaddr)list);
    in_mail_list = MailManager::append_mailQueue(in_mail_list, list_mail);

    // EXIT_COMMAND (番兵的な意味で)
    sentinel  = mailManager->create(MY_SPE_COMMAND_EXIT);
    in_mail_list = MailManager::append_mailQueue(in_mail_list, sentinel);

    // scheduler は受け取ったメールを元に実行する
    scheduler->send_mailList(in_mail_list);
    scheduler->run();
    out_mail_list = scheduler->recv_mailList();

    return out_mail_list;
}

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

void
FifoTaskManagerImpl::mail_check(MailQueuePtr mail_list)
{
    MailQueuePtr q = mail_list;
    MailQueuePtr d;
    unsigned int data;

    while (q) {
        data = q->data;

        /**
         * MY_SPE_STATUS_READY: SPE が持ってた Task 全て終了
         * MY_SPE_NOP: 特に意味のないコマンド
         * それ以外:終了したタスク(PPEにあるのでアドレス
         *
         * MY_SPE_NOP が 0 なので、
         * 下のように data > MY_SPE_NOP とかしています。
         * 一目でよくわからない書き方なんで、直したいところですが。。。
         */
        if (data == MY_SPE_STATUS_READY) {
            __debug_ppe("mail_check(): Task List finish\n");
        } else if (data > MY_SPE_NOP) {
            __debug_ppe("mail_check(): recv from 0x%x\n", data);
            check_task_finish((HTaskPtr)data);
        }

        d = q;
        q = q->next;

        mailManager->free(d);
    }
}

void*
FifoTaskManagerImpl::allocate(int size, int alignment)
{
#ifdef __APPLE__
    return malloc(size);
#else
    void *buff;
    posix_memalign(&buff, alignment, size);
    return buff;
#endif
}

void*
FifoTaskManagerImpl::allocate(int size)
{
#ifdef __APPLE__
    return malloc(size);
#else
    void *buff;
    posix_memalign(&buff, DEFAULT_ALIGNMENT, size);
    return buff;
#endif
}

Scheduler*
FifoTaskManagerImpl::get_scheduler() {
    return scheduler;
}

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