view TaskManager/kernel/schedule/Scheduler.h @ 426:58fee2fce1bd

minor fix.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 24 Sep 2009 17:44:30 +0900
parents 799071db126e
children fb62b7acc92b
line wrap: on
line source

#ifndef INCLUDED_SCHEDULER
#define INCLUDED_SCHEDULER

#include "base.h"
#include "TaskList.h"
#include "ListData.h"
#include "DmaManager.h"
#include "SchedTaskBase.h"
#include "SchedTaskList.h"
#include "TaskGroup.h"
#include "MemList.h"
#include "MemHash.h"

#define MAX_USER_TASK 32
#define MAX_SYSTEM_TASK 2
#define MAX_TASK_OBJECT MAX_USER_TASK + MAX_SYSTEM_TASK
#define MAX_GLOBAL_AREA 32
#define MAX_MAINMEM_AREA 32

class SchedTaskBase;
class SchedTask;
class SchedTaskList;

typedef	SchedTask* (*TaskObjectCreator)(Scheduler *);

class Scheduler {
public:
    virtual ~Scheduler();

    BASE_NEW_DELETE(Scheduler);

    /* variables */
    int id;
    MemHash *hash;

    // double buffering
    TaskListPtr buff_taskList[2];
    ListDataPtr buff_inListData[2];
    ListDataPtr buff_outListData[2];

    int buffFlag_taskList;
    int buffFlag_inListData;
    int buffFlag_outListData;

    /* TaskList 関連 */

    /**
     * 実行中 TaskList の現在の位置 (list->tasks[index])
     *
     * bakIndex_taskList がある理由
     * taskList の途中で renew task が作られたとき、
     * 即座に実行するため、TaskList -> RenewTaskList と移って処理する。
     * RenewTaskList が終了したとき、再び TaskList に戻ってくるが
     * Renew Task を生成した所から再スタートするため、
     * taskList の index を覚えておく (backup)
     * 同様に TaskList も覚えておく
     */
    int bakIndex_taskList;
    TaskListPtr bak_curTaskList;


    /**
     * タスク内で生成されたタスクを入れる
     * Linked List で管理
     */
    TaskListPtr renewCur_taskList;
    TaskListPtr renewTop_taskList;

    /**
     * 実行中 TaskList が Renew されたものかどうかのフラグ
     * Renew の場合、ListData は DMA する必要ないとか
     * いろいろな判定に使えるかもしれん
     * if (flag == 1) taskList is Renew
     */
    int flag_renewTaskList;

    /**
     * タスク内 (T1) でタスク (Tc = T2, T3, ..) が複数生成された場合、
     * Tc が全て終わってから、T1 の終了コマンドを PPE に送る。
     * なので、Tc を process group として記憶しておく。
     *
     * Tc が taskGroup のアドレスを持つので
     * Scheduler が持つ taskGroup 変数は一つだけで(多分)おk
     */
    TaskGroupPtr taskGroup;

    /* GlobalMemoryList */
    void* globalList[MAX_GLOBAL_AREA];

    /* MainMemory Allocate Command List */
    void* mainMemList[MAX_MAINMEM_AREA];

    /* Code Area */
    MemList *code_segment_pool;

    // Task Object Table
    //  this is named TaskObject but it is not an object.
    //  It is a pointer to an object creation function
    //  大きいので、SPEには置かない方が本当は良い...
    typedef struct {
	TaskObjectCreator creator;
	uint64 location;            // location address in a.out
	uint64 end;            
	uint32 entry_offset;        // offset for create();
	MemorySegment *segment;
	void (*load)(Scheduler *,int);
	void (*wait)(Scheduler *,int);
    } TaskObject, *TaskObjectPtr;

    DmaManager* connector;

    // Pipeline Stage
    SchedTaskBase* task1;
    SchedTaskBase* task2;
    SchedTaskBase* task3;

    /* functions */
    void init();
    void run();
    virtual void init_impl() {};
    void finish();

    TaskListPtr get_curListBuf();
    ListDataPtr get_curReadBuf();
    ListDataPtr get_curWriteBuf();
    TaskListPtr get_renewListBuf();

    void set_backupTaskList(TaskListPtr cur_taskList);
    void set_backupTaskListIndex(int cur_index);
    SchedTaskList* get_nextRenewTaskList();
    TaskListPtr get_backupTaskList();
    int get_backupTaskListIndex();

    // なんか名前が変だが。。。
    /* TaskGroup */
    TaskGroupPtr set_groupTask(uint32 command);
    void add_groupTask(TaskGroupPtr group, TaskPtr task);
    void remove_groupTask(TaskGroupPtr group, TaskPtr task);
    void reload_groupTask();
    uint32 status_groupTask(TaskGroupPtr group);

    /* GlobalMemory */
    void* global_alloc(int id, int size);
    void* global_get(int id);
    void global_set(int id, void *addr);
    void global_free(int id);
    MemList* createMemList(int size, int count);
    virtual void *allocate(int size) { return NULL; };

    virtual void mainMem_alloc(int id, int size) {};
    virtual void mainMem_wait() {};
    void *mainMem_get(int id);

    MemorySegment * get_segment(memaddr addr, MemList *m);
    void allocate_code_segment(int count, int size);

    virtual uint32 get_tag();
    void put_segment(MemorySegment *s);
    void wait_segment(MemorySegment *s);

    /* DMA Transfer */
    void dma_load(void *buf, uint32 addr, uint32 size, uint32 mask);
    void dma_store(void *buf,uint32 addr, uint32 size, uint32 mask);
    void dma_wait(uint32 mask);
    void show_dma_wait() { connector->show_dma_wait(id); };
    void show_dma_wait(int id) { connector->show_dma_wait(id); };
    void mail_write(uint32 data);
    uint32 mail_read();
    void dma_loadList(ListDataPtr list, void *, uint32 mask);
    void dma_storeList(ListDataPtr list, void *, uint32 mask);
};

extern void register_task(int cmd, TaskObjectCreator creator);
extern void register_dynamic_task(int cmd, TaskObjectCreator creator,
    memaddr start, memaddr end, int entry_offset);

#endif


#define SchedConstructor(str)                                           \
    str() {}                                                            \
    BASE_NEW_DELETE(str)                                                \

#define SchedDefineTask(str)                                            \
    SchedTask* createTask_##str(Scheduler *manager)   \
    {                                                                   \
        return new str();                                               \
    }

#define SchedExternTask(str)                                            \
    extern SchedTask* createTask_##str(Scheduler *manager)   ;

#define SchedRegisterTask(cmd, str)             \
    register_task(cmd, createTask_##str);

#define SchedDefineDynamicTask(str,segment)                             \
    SchedTask* createTask_##str(Scheduler *manager)    \
    {                                                                   \
        return new str();                                               \
    }

#define SchedExternDynamicTask(str,segment)                             \
    extern memaddr __load_start_##segment,                             \
           memaddr __loat_stop_##segment,                              \
           spe_load_entry;                                             \
    extern SchedTask* createTask_##str(Scheduler *manager);


#define SchedRegisterDynamicTask(cmd, str, segment)                    \
    register_dynamic_task(cmd,  __load_start_##segment, __load_stop_##segment, createTask__##str-spe_load_entry);


/* end */