view TaskManager/kernel/schedule/SchedTask.cc @ 1474:b158873485f6 draft

fix simple task
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 16 Jul 2012 11:01:40 +0900
parents d585a7614cd5
children eee4f68409dd
line wrap: on
line source


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


extern TaskObject task_list[MAX_TASK_OBJECT];

SchedTask::SchedTask()
{
    list        = NULL;
    atask       = NULL;
    readbuf     = NULL;
    writebuf    = NULL;
    scheduler   = NULL;
    cur_index   = 0;
    din[0] = dout[0] = 0;
    this->stdout_ = stdout;
    this->stderr_ = stderr;
    this->stdin_ = stdin;
}

SchedTask::~SchedTask()
{
}

void
SchedTask::init(TaskListPtr _list, TaskPtr _task, Scheduler* sc, int tag)
{
    list        = _list;
    atask        = _task;
    scheduler   = sc;
    this->tag = tag;

    // scheduler->mainMem_wait();   // これはなんで?
    manager = sc->manager;
    connector = sc->connector;

    inListData.bound = din;
    inListData.size = 0;
    inListData.length = 0;
    inListData.element = 0;
    outListData.bound = dout;
    outListData.size = 0;
    outListData.length = 0;
    outListData.element = 0;

    cur_index = _task;
    this->tag = tag;

#ifdef TASK_LIST_MAIL
    if (list)
       waiter = (memaddr) list->waiter;
#else
    if (task)
       waiter = (memaddr) task->self;
#endif

}


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

    // object creation をSchedTask生成時にやらないので、
    // exec の直前のread で十分に間に合う
    loadSchedTask(scheduler, atask->command);

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

    inListData.length = atask->inData_count;
    inListData.size = atask->inData_total_size();
    inListData.element = atask->inData(0);
    inListData.bound = (int*)manager->allocate(inListData.length*sizeof(int));

    // load Input Data
    // inListData.print();
    readbuf = connector->dma_loadList(scheduler, &inListData, (DMA_READ + this->tag));
    connector->bound(&inListData);
}

void
SchedTask::setup_outputData()
{
    // allocate write buffer
    outListData.length = atask->outData_count;
    outListData.size = atask->outData_total_size();
    // atask->outData_offset += cur_index + 1 ;  // to avoid compiler bug
    outListData.element = atask->outData(0);
    // if (outListData.bound!=dout) free(outListData.bound);
    outListData.bound = (int*)manager->allocate(outListData.length*sizeof(int));
    connector->bound(&outListData);
    writebuf = connector->get_writebuf(scheduler, (memaddr)outListData.element[0].addr, outListData.size);
}

void
SchedTask::exec()
{
    task_list[atask->command].wait(scheduler,atask->command);
    TaskObjectRun run = task_list[atask->command].run;
    if (atask->outData_count > 0) {
        setup_outputData(); // we need write buffer before run()
    }
    connector->dma_wait((DMA_READ + this->tag));
    void *read = get_input(readbuf, 0); void *write =  get_output(writebuf, 0);
    run(this, read,write);
    connector->free_(readbuf);
    // User 側で作る方法が必要...
    // 書き込む領域がなければ無視
    if (atask->outData_count > 0) {
        // outListData.print();
        connector->dma_storeList(&outListData, writebuf, DMA_WRITE);
    }
}

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

    connector->dma_wait(DMA_WRITE);
    connector->free_(writebuf);
    if (inListData.bound != din) free(inListData.bound);
    if (outListData.bound != dout) free(outListData.bound);
#ifdef TASK_LIST_MAIL
    if ((cur_index->next() >= list->last()) )
	connector->mail_write(waiter);
#else
    connector->mail_write(waiter);
#endif
}

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

    if (cur_index == 0) { // 最初の一つ
        SchedTask *nextSched = new SchedTask();
	nextSched->init(list, &list->tasks[0], scheduler, this->tag^1);
	return nextSched;
    }
    TaskPtr nextTask = cur_index->next();
    if (nextTask < list->last()) {
	// Task List が残っているので、次を準備

	TaskPtr nextTask = cur_index->next();
	
        SchedTask *nextSched = new SchedTask();
	nextSched->init(list, nextTask, scheduler, this->tag^1);
	return nextSched;
    } else {
        memaddr nextList = (memaddr)list->next;
        if (nextList == 0) {
	    // もう何もする必要がない
	    
            return new SchedNop2Ready(scheduler);
        } else {
	    // 新しいリストに取り掛かる
  	    int dma_tag_switch = 0;
	    return new SchedTaskList(nextList, scheduler, dma_tag_switch);
        }
    }
}


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

void SchedTask::free_(void *p) {
    scheduler->free_(p);
}

/**
 *    SimpleTask has one parameter , one input, one output
 */

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

/**
 * 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;
}

int
SchedTask::read_size()
{
    return get_inputSize(0);
}

/**
 * write buffer の領域を返す。
 */
void*
SchedTask::get_output(void *buff, int index)
{
    return (void*)((char *)writebuf + outListData.bound[index]);
}

/**
 * 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;
}

int
SchedTask::write_size()
{
    return get_outputSize(0);
}


void
SchedTask::set_outputSize(int index, int size)
{
    outListData.element[index].size = size;
}

memaddr
SchedTask::get_param(int index)
{
    return *atask->param(index);
}



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) {
    return connector->dma_load1(buf, addr, size, mask); // direct DMA API (should be purged )
}

void *
SchedTask::get_load_buf(uint32 size) {
    return connector->get_writebuf(scheduler, 0, size); // direct DMA API (should be purged )
}

void
SchedTask::free_load_buf(void *buf) {
    return connector->free_(buf); // direct DMA API (should be purged )
}

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

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

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


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

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

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

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

void SchedTask::overwrite_segment(MemorySegment *s, memaddr addr) {
    return scheduler->overwrite_segment(s,addr);
}


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 manager->create_task(cmd, __builtin_return_address(0));
}

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

HTaskPtr
SchedTask::create_task_array(int id, int num_task, int num_param, int num_inData, int num_outData)
{
  return manager->create_task_array(id, num_task, num_param, num_inData, num_outData, __builtin_return_address(0));
}

void SchedTask::free_htask(HTask *p) {
#if  !defined(__SPU__)
    manager->free_htask(p);
#endif
}


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

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

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

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

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

void SchedTask::polling()
{
    manager->polling();
}

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

/* system call */

int 
SchedTask::printf(const char * format, ...)
{
    va_list ap;
    va_start(ap,format);
    int ret= scheduler->vprintf0(format, ap);
    va_end(ap);
    return ret;
}


/* end */