view TaskManager/kernel/schedule/SchedTask.cc @ 2030:258498680128 draft

indent-region
author Yuhi TOMARI <yuhi@cr.ie.u-ryukyu.ac.jp>
date Tue, 25 Nov 2014 05:08:50 +0900
parents f82bb7393c4d
children f7969d7f5605
line wrap: on
line source

//#define DEBUG
#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>
#include "gettime.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)
{  
    // do not modify these, all shared among read/exec/write pipeline
    list        = _list;  
    atask        = _task;
    scheduler   = sc;
    this->tag = tag;

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

    taskPool = new QueueInfo<TaskObject>();

    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;

    if (list)
        waiter = (memaddr) list->waiter;
}

void
SchedTask::read()
{
    __debug(this->scheduler, "[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);
    if (inListData.length>DefaultBoundSize)
        inListData.bound = (long*)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);
    if (outListData.length>DefaultBoundSize)
        outListData.bound = (long*)manager->allocate(outListData.length*sizeof(int));
    connector->bound(&outListData);
    writebuf = connector->get_writebuf(scheduler, (memaddr)outListData.element[0].addr, outListData.size);
}

void
SchedTask::exec()
{
    taskPool->get(atask->command)->wait(scheduler,atask->command);
    TaskObjectRun run = taskPool->get(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);
    // set param (if exist dim )
    list->task_start_time = gettime();
    (*connector->start_dmawait_profile)(&connector->start_time);
    if (list->dim) {
        multi_dimension(list, read, write,run);
    } else {
        run(this, read,write);
    }
    (*connector->end_dmawait_profile)(&connector->global_busy_time,&connector->start_time,&connector->stop_time);
    list->task_end_time = gettime();
    __debug(this->scheduler,"cpuid %ld %s\t0x%p time %lld\n",scheduler->id,(char *)(taskPool->get(atask->command)->name),(void*)list, list->task_end_time-list->task_start_time);
    connector->free_(readbuf);
    // User 側で作る方法が必要...
    // 書き込む領域がなければ無視
    if (atask->outData_count > 0) {
        // outListData.print();
        connector->dma_storeList(&outListData, writebuf, DMA_WRITE);
    }
}

void
SchedTask::multi_dimension(TaskListPtr list, void* read, void* write,TaskObjectRun run) {
    long min = scheduler->min_cpu(); 
    long max = scheduler->max_cpu(); 
    long id = scheduler->id; 
    long lx = list->x; 
    long ly = list->y; 
    long lz = list->z; 

    x=y=z=0;
    
    long cpu=min;
    for (;;cpu++) {
        if (cpu>max) cpu = min;
        if (cpu==id) {
            run(this, read,write);
        }
        if (++x>=lx) {
            x=0;
            if (++y>=ly) {
                y=0;
                if (++z>=lz) {
                    break;		
                }
            }
        }
    }
}

void
SchedTask::write()
{
    __debug(this->scheduler, "[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);
    if ((cur_index->next() >= list->last()) )
        connector->mail_write(waiter);
}

SchedTaskBase*
SchedTask::next(Scheduler *scheduler, SchedTaskBase *p)
{
    TaskList *nextList = list; // do not modify list
    __debug(this->scheduler, "[SchedTask:%s]\n", __FUNCTION__);

    if (cur_index == 0) { // 最初の一つ
        SchedTask *nextSched = new SchedTask();
        nextSched->init(nextList, &nextList->tasks[0], scheduler, this->tag^1);
        return nextSched;
    }
    TaskPtr nextTask = cur_index->next(); // ここで一個一個のtaskを取ってきてる
    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 {
        nextList = list->next;
        if (nextList == 0) {
            // もう何もする必要がない
            return new SchedNop2Ready(scheduler);
        } else {
            // 新しいリストに取り掛かる
            int dma_tag_switch = 0;
            return new SchedTaskList((memaddr)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 */