view TaskManager/kernel/schedule/SchedTask.cc @ 699:7e937a1cd121

....
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 13 Dec 2009 22:46:15 +0900
parents dcaa40ec963d
children 61b59376aec5
line wrap: on
line source

#include <stdlib.h>
#include <string.h>
#include "SchedTask.h"
#include "SysFunc.h"
#include "SchedTaskList.h"
#include "SchedTaskArrayLoad.h"
#include "SchedNop2Ready.h"
#include "DmaManager.h"
#include "error.h"
#include "TaskManager.h"
#include <stdarg.h>

#ifdef SIMPLE_TASK
#define Task SimpleTask
#define TaskPtr SimpleTaskPtr
#endif

extern TaskObject task_list[MAX_TASK_OBJECT];

/**
   Task Object を作る
 */


SchedTask *
createSchedTask(Scheduler *scheduler, TaskPtr task)
{
    return new SchedTask();
}

#if 0
/**
   code load を始める。既に get_segment hash に入っていれば何もしない。
 */
extern void
loadSchedTask(Scheduler *scheduler,TaskPtr task)
{
// fprintf(stderr,"loadSchedTask %d\n",task->command);
    task_list[task->command].load(scheduler,task->command);
}
#endif


SchedTask::SchedTask()
{
    list        = NULL;
    task        = NULL;
#ifndef SIMPLE_TASK
    inListData  = NULL;
    outListData = NULL;
#endif
    readbuf     = NULL;
    writebuf    = NULL;
    scheduler   = NULL;
    cur_index   = 0;
    this->stdout_ = stdout;
    this->stderr_ = stderr;
    this->stdin_ = stdin;


}

/**
 * dma_store の wait を行う
 */
SchedTask::~SchedTask()
{
}


void
SchedTask::init(TaskListPtr _list, TaskPtr _task, int index,
                    // ListDataPtr rbuf, ListDataPtr wbuf, 
		    Scheduler* sc)
{
    list        = _list;
    task        = _task;
#ifndef SIMPLE_TASK
    inListData  = &_task->inData;
    outListData = &_task->outData;
#endif
    scheduler   = sc;
    cur_index   = index;

    scheduler->mainMem_wait();

}


void
SchedTask::read()
{
    __debug("[SchedTask:%s]\n", __FUNCTION__);

    // object creation をSchedTask生成時にやらないので、
    // exec の直前のread で十分に間に合う
    if (cur_index < list->length) { // if 文は要らないのでは?
	// load next task
	loadSchedTask(scheduler, list->tasks[cur_index].command);
    }
#ifdef SIMPLE_TASK
    // 読むデータが一つもなければ無視
    if (task->r_size == 0) return;
    // load Input Data
    readbuf = scheduler->allocate(task->r_size);
    scheduler->dma_load(readbuf, task->rbuf,task->r_size, DMA_READ);
#else

    // 読むデータが一つもなければ無視
    if (inListData->length == 0) return;

    // load Input Data
    readbuf = scheduler->allocate(inListData->size);
    scheduler->dma_loadList(inListData, readbuf, DMA_READ);
#endif


}


void
SchedTask::exec()
{
    __debug("[SchedTask:%s]\n", __FUNCTION__);

#ifdef SIMPLE_TASK
    if (task->w_size > 0) {
	writebuf = scheduler->allocate(task->w_size);
    }
#else
    if (outListData->length > 0) {
	writebuf = scheduler->allocate(outListData->size);
    }
#endif
    scheduler->dma_wait(DMA_READ);
    task_list[task->command].wait(scheduler,task->command);
    task_list[task->command].run(this, readbuf, writebuf);
    free(readbuf);

    // 書き込む領域がなければ無視
#ifdef SIMPLE_TASK
    if (task->w_size > 0) {
	writebuf = scheduler->allocate(task->w_size);
	scheduler->dma_store(writebuf, task->wbuf,task->w_size, DMA_WRITE);
    }
#else
    if (outListData->length > 0) {
	writebuf = scheduler->allocate(outListData->size);
        scheduler->dma_storeList(outListData, writebuf, DMA_WRITE);
    }
#endif
}

void
SchedTask::write()
{
    __debug("[SchedTask:%s]\n", __FUNCTION__);

    scheduler->dma_wait(DMA_WRITE);
    free(writebuf);

    scheduler->mail_write((memaddr)task->self);
}


SchedTaskBase*
SchedTask::next(Scheduler *scheduler, SchedTaskBase *p)
{
    __debug("[SchedTask:%s]\n", __FUNCTION__);

    if (cur_index < list->length) {
	// Task List が残っているので、次を準備

	TaskPtr nextTask = &list->tasks[cur_index++];
        SchedTaskBase *nextSched = createSchedTask(scheduler, nextTask);
	// この up cast は汚い...
	((SchedTask*)nextSched)->init(list, nextTask, cur_index,
					  scheduler);
	if (nextTask->command==TaskArray) {
	    // Start Task Array
	    return (SchedTaskBase*)(new SchedTaskArrayLoad(scheduler, nextSched));
	}

	return nextSched;
    } else {
        memaddr nextList = (memaddr)list->next;
        if (nextList == 0) {
	    // もう何もする必要がない
            return new SchedNop2Ready(scheduler);
        } else {
	    // 新しいリストに取り掛かる
            return createSchedTaskList(nextList, scheduler, 0);
        }
    }
}


int
SchedTask::get_cpuid()
{
    return scheduler->id;
}

#ifndef SIMPLE_TASK
/**
 * task->add_inData で与えられた順番に対応する index (0〜n-1) で、
 * buffer から対応するデータを返す。
 */
void*
SchedTask::get_input(void *buff, int index)
{
    if (buff != NULL) {
        return (void*)((char*)buff + inListData->bound[index]);
    } else {
        return NULL;
    }
}

/**
 * get_input(index) のアドレスを返す
 */
memaddr
SchedTask::get_inputAddr(int index)
{
#ifdef __CERIUM_CELL__
    return (memaddr)inListData->element[index].addr;
#else
    return inListData->element[index].addr;
#endif
}

/**
 * get_input(index) のサイズを返す
 */
int
SchedTask::get_inputSize(int index)
{
    return inListData->element[index].size;
}

/**
 * write buffer の領域を返す。
 */
void*
SchedTask::get_output(void *buff, int index)
{
    if (buff != NULL) {
        return (void*)((char *)buff + outListData->bound[index]);
    } else {
        return NULL;
    }
}

/**
 * get_output(index) のアドレスを返す
 */
memaddr
SchedTask::get_outputAddr(int index)
{
#ifdef __CERIUM_CELL__
    return (memaddr)outListData->element[index].addr;
#else
    return outListData->element[index].addr;
#endif
}

/**
 * get_output(index) のサイズを返す
 */
int
SchedTask::get_outputSize(int index)
{
    return outListData->element[index].size;
}

memaddr
SchedTask::get_param(int index)
{
    return task->param[index];
}

#else

void* SchedTask::get_input(void *buff, int index) {
  printf("Cannot use inData in SimpleTask use TaskArray\n");
  return NULL; }
memaddr SchedTask::get_inputAddr(int index) { return NULL; }
int SchedTask::get_inputSize(int index) {return 0; }
void* SchedTask::get_output(void *buff, int index) {return 0; }
memaddr SchedTask::get_outputAddr(int index) { return NULL; }
int SchedTask::get_outputSize(int index) { return 0; }
memaddr SchedTask::get_param(int index) { return 0; }

#endif

void*
SchedTask::global_alloc(int id, int size) {
    return scheduler->global_alloc(id, size);
}

void*
SchedTask::global_get(int id) {
    return scheduler->global_get(id);
}

void
SchedTask::global_set(int id, void *addr) {
    scheduler->global_set(id, addr);
}

void
SchedTask::global_free(int id) {
    scheduler->global_free(id);
}

MemList*
SchedTask::createMemList(int size, int count) {
    return scheduler->createMemList(size, count);
}

void
SchedTask::mainMem_alloc(int id, int size) {
    scheduler->mainMem_alloc(id, size);
}

void
SchedTask::mainMem_wait() {
    scheduler->mainMem_wait();
}

memaddr
SchedTask::mainMem_get(int id) {
    return scheduler->mainMem_get(id);
}


void
SchedTask::dma_load(void *buf, memaddr addr, uint32 size, uint32 mask) {
    scheduler->dma_load(buf, addr, size, mask);
}

void
SchedTask::dma_store(void *buf,memaddr addr, uint32 size, uint32 mask) {
    scheduler->dma_store(buf, addr, size, mask);
}

void
SchedTask::dma_wait(uint32 mask) {
    scheduler->dma_wait(mask);
}

void
SchedTask::show_dma_wait() {
    scheduler->show_dma_wait();
}

long
SchedTask::get_random() {
    return scheduler->get_random();
}

void
SchedTask::start_profile() {
    scheduler->start_profile();
}

MemorySegment * SchedTask::get_segment(memaddr addr, MemList *m) {
    return scheduler->get_segment(addr,m);
}

void SchedTask::put_segment(MemorySegment *s) {
    scheduler->put_segment(s);
}

void SchedTask::wait_segment(MemorySegment *s) {
    scheduler->wait_segment(s);
}


HTaskPtr
SchedTask::create_task(int cmd)
{
    return scheduler->create_task(cmd);
}

HTaskPtr 
SchedTask::create_task(int cmd, memaddr r, long rs, memaddr w, long ws)
{
    return scheduler->create_task(cmd,r,rs,w,ws);
}


void SchedTask::set_task_depend(HTaskPtr master, HTaskPtr slave)
{
    scheduler->set_task_depend(master, slave);
}

void SchedTask::spawn_task(HTaskPtr t)
{
    scheduler->spawn_task(t);
}

void SchedTask::set_task_cpu(HTaskPtr t, CPU_TYPE cpu)
{
    scheduler->set_task_cpu(t, cpu);
}

void* SchedTask::allocate(int size) 
{
    return scheduler->allocate(size) ;
}

void* SchedTask::allocate(int size,int align) 
{
    return scheduler->allocate(size,align) ;
}

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

/* system call */

int 
SchedTask::fprintf(FILE * stream, const char * format, ...)
{
    va_list ap;
    va_start(ap,format);
    int ret = vfprintf(stream,format, ap);
    va_end(ap);
    return ret;
}

int 
SchedTask::printf(const char * format, ...)
{
    va_list ap;
    va_start(ap,format);
    int ret= vfprintf(stdout,format, ap);
    va_end(ap);
    return ret;
}



/* end */