view TaskManager/kernel/schedule/Scheduler.cc @ 356:b89ba1d96fff

merge heads
author aaa
date Fri, 17 Jul 2009 15:04:02 +0900
parents 81b25e5d5379 c9f8cfcdc5c2
children eab18aa0c7f6
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include "Scheduler.h"
#include "SchedNop.h"
#include "error.h"

/*
 * Edit kernel/schedule/xx.cc, Cell/spe/xx.cc will be over writen by this.
 * Do not edit Cell/spe/xx.cc unless there is no kernel/schedule/xx.cc files.
 */

Scheduler::TaskObject task_list[MAX_TASK_OBJECT];

Scheduler::~Scheduler(void)
{
    delete connector;
}

/*! @brief speTaskの入出力のパイプラインバッファを確保する
 */

void
Scheduler::init(void)
{
    init_impl();

    for (int i = 0; i < 2; i++) {
	buff_taskList[i]    = (TaskListPtr)allocate(sizeof(TaskList));
	buff_inListData[i]  = (ListDataPtr)allocate(sizeof(ListData));
	buff_outListData[i] = (ListDataPtr)allocate(sizeof(ListData));
    }
    
    buffFlag_taskList = 0;
    buffFlag_inListData = 0;
    buffFlag_outListData = 0;
    flag_renewTaskList = 0;

    // bzero でもいいけど
    for (int i = 0; i < MAX_GLOBAL_AREA; i++) {
	globalList[i] = NULL;
    }

    for (int i = 0; i < MAX_MAINMEM_AREA; i++) {
	mainMemList[i] = NULL;
    }
    

    taskGroup = new TaskGroup;
    renewTop_taskList = NULL;
    renewCur_taskList = NULL;
}

void
Scheduler::run(void)
{
    SchedTaskBase* taskTmp;

    task1 = new SchedNop();
    task2 = new SchedNop();
    task3 = new SchedNop();

    // main loop
    do {
	__debug("----------\n");
	task3->write();
	task2->exec();
	task1->read();

	taskTmp = task3;
	task3 = task2;
	task2 = task1;
	task1 = task1->next(this, taskTmp);
    } while (task1);

    delete task3;
    delete task2;
}


void
Scheduler::finish(void)
{
    free(buff_taskList[0]);
    free(buff_taskList[1]);
    free(buff_inListData[0]);
    free(buff_inListData[1]);
    free(buff_outListData[0]);
    free(buff_outListData[1]);
}

/**
 * あらかじめ memory allocte してある TaskList の領域を
 * パイプラインの各処理が交代して使う。
 */
TaskListPtr
Scheduler::get_curListBuf(void)
{
    buffFlag_taskList ^= 1;

    return buff_taskList[buffFlag_taskList];
}


/**
 * あらかじめ memory allocte してある ListData の領域を
 * パイプラインの各処理が交代して使う。
 */
ListDataPtr
Scheduler::get_curWriteBuf(void)
{
    buffFlag_outListData ^= 1;
    return buff_outListData[buffFlag_outListData];
}


ListDataPtr
Scheduler::get_curReadBuf(void)
{
    buffFlag_inListData ^= 1;
    return buff_inListData[buffFlag_inListData];
}

/**
 * タスク内で生成されたタスクを格納する TaskList を取得する
 * 現在格納に使っている TaskList (renewCur_taskList) が使えるならそれを返す
 * もしそうでないなら、新しく TaskList を allocate してそれを返す
 * コード中で renewCur_taskList が NULL になるのは
 *   - プログラム開始時
 *   - タスク内生成タスクがある TaskList の実行を新しく始める (Nop2Ready 参照)
 * 以上の場合です
 */
TaskListPtr
Scheduler::get_renewListBuf(void)
{
    if (renewCur_taskList && renewCur_taskList->length < TASK_MAX_SIZE) {
	return renewCur_taskList;
    } else {
	TaskListPtr newList = (TaskListPtr)allocate(sizeof(TaskList));
	newList->length = 0;
	newList->next = NULL;
	renewTop_taskList = TaskList::append(renewTop_taskList, newList);
	renewCur_taskList = newList;
	return newList;
    }
}

/**
 * 次に実行する Renew Task List を返す
 *
 * @param[in] curList 現在実行中の TaskList
 *                    中断して RenewTaskList を行うため
 *                    バックアップを取っておく
 * @return next RenewTaskList
 */
SchedTaskList*
Scheduler::get_nextRenewTaskList(void)
{
    if (renewTop_taskList) {
	TaskListPtr list  = renewTop_taskList;
	renewTop_taskList = renewTop_taskList->next;
	renewCur_taskList = NULL;

	list->next = NULL;
	SchedTaskList *sched
	    = createSchedTaskList((uint32)list, this, SCHED_TASKLIST_RENEW);
	return sched;
    } else {
	return NULL;
    }
}

void
Scheduler::set_backupTaskList(TaskListPtr cur_taskList)
{
    bak_curTaskList = cur_taskList;
}

void
Scheduler::set_backupTaskListIndex(int cur_index)
{
    bakIndex_taskList = cur_index;
}

/**
 * RenewTaskList 実行前に中断した TaskList を返す
 * NULL の場合、中断した TaskList は無い。
 *
 * @return TaskList
 */
TaskListPtr
Scheduler::get_backupTaskList(void)
{
    TaskListPtr ret = bak_curTaskList;
    
    bak_curTaskList = NULL;
    return ret;
}

int
Scheduler::get_backupTaskListIndex(void)
{
    int ret = bakIndex_taskList;

    bakIndex_taskList = 0;
    return ret;
}

void
Scheduler::dma_load(void *buf, uint32 addr, uint32 size, uint32 mask)
{
    connector->dma_load(buf, addr, size, mask);
}

void
Scheduler::dma_store(void *buf, uint32 addr, uint32 size, uint32 mask)
{
    connector->dma_store(buf, addr, size, mask);
}

void
Scheduler::dma_wait(uint32 mask)
{
    connector->dma_wait(mask);
}

void
Scheduler::dma_loadList(ListDataPtr list, void *buff, uint32 mask)
{
    connector->dma_loadList(list, buff, mask);
}


void
Scheduler::dma_storeList(ListDataPtr list, void *buff, uint32 mask)
{
    return connector->dma_storeList(list, buff, mask);
}

void
Scheduler::mail_write(uint32 data)
{
    connector->mail_write(data);
}

uint32
Scheduler::mail_read(void)
{
    return connector->mail_read();
}

TaskGroupPtr
Scheduler::set_groupTask(uint32 command)
{
    TaskGroupPtr ret = taskGroup;

    reload_groupTask();

    ret->command = command;
    return ret;
}

void
Scheduler::add_groupTask(TaskGroupPtr group, TaskPtr task)
{
    group->add(task);
}

void
Scheduler::remove_groupTask(TaskGroupPtr group, TaskPtr task)
{
    group->remove(task);
}

void
Scheduler::reload_groupTask(void)
{
    taskGroup = new TaskGroup;
}

uint32
Scheduler::status_groupTask(TaskGroupPtr group)
{
    return group->status();
}

void*
Scheduler::global_alloc(int id, int size)
{
    globalList[id] = allocate(size);
    return globalList[id];
}

void*
Scheduler::global_get(int id)
{
    return globalList[id];
}

void
Scheduler::global_free(int id)
{
    free(globalList[id]);
    globalList[id] = NULL;
}

/**
 * mainMem_alloc で確保したメインメモリの領域アドレスを返す。
 * これは Fifo, Cell で共通
 */
void*
Scheduler::mainMem_get(int id)
{
    return mainMemList[id];
}


/**
 * 本当は Scheduler クラスに入れるべきなんだろうか。。。
 * なんか手抜きの感がある
 */
void
register_task(int cmd, Scheduler::TaskObject task)
{
    task_list[cmd] = task;
}