Mercurial > hg > Members > kono > Cerium
view TaskManager/kernel/schedule/Scheduler.cc @ 684:458a1ad91427
Task Array generation worked.
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 06 Dec 2009 23:03:28 +0900 |
parents | 7405d92733a8 |
children | b386522827ae |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include "Scheduler.h" #include "SchedNop.h" #include "error.h" #include <assert.h> #include "TaskManagerImpl.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() { delete connector; } static int null_run(SchedTask* smanager, void* r, void *w) { printf("Calling Undefined Task\n"); return 0; } static void null_loader(Scheduler *m, int task_id); /*! @brief speTaskの入出力のパイプラインバッファを確保する */ void Scheduler::init(TaskManagerImpl *m) { hash = 0; for (int i = 0; i< MAX_TASK_OBJECT; i++) { task_list[i].run = null_run; task_list[i].load = null_loader; task_list[i].wait = null_loader; } set_manager(m); init_impl(); for (int i = 0; i < 2; i++) { buff_taskList[i] = (TaskListPtr)allocate(sizeof(TaskList)); } buffFlag_taskList = 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] = (memaddr)NULL; } } void Scheduler::run() { task1 = new SchedNop(); task2 = new SchedNop(); task3 = new SchedNop(); // main loop do { __debug("----------\n"); task3->write(); task2->exec(); task1->read(); delete task3; task3 = task2; task2 = task1; task1 = task1->next(this, 0); } while (task1); delete task3; delete task2; } void Scheduler::finish() { free(buff_taskList[0]); free(buff_taskList[1]); } /** * あらかじめ memory allocte してある TaskList の領域を * パイプラインの各処理が交代して使う。 */ TaskListPtr Scheduler::get_curListBuf() { buffFlag_taskList ^= 1; return buff_taskList[buffFlag_taskList]; } void Scheduler::dma_load(void *buf, memaddr addr, uint32 size, uint32 mask) { connector->dma_load(buf, addr, size, mask); } void Scheduler::dma_store(void *buf, memaddr 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(memaddr data) { connector->mail_write(data); } memaddr Scheduler::mail_read() { return connector->mail_read(); } /* ここから下は、memory 以下にあるべき */ 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_set(int id, void *addr) { globalList[id] = addr; } void Scheduler::global_free(int id) { free(globalList[id]); globalList[id] = NULL; } /** * mainMem_alloc で確保したメインメモリの領域アドレスを返す。 * これは Fifo, Cell で共通 */ memaddr Scheduler::mainMem_get(int id) { return mainMemList[id]; } /** * Task load API */ void Scheduler::allocate_code_segment(int size, int count) { // 既に overlay 領域があるので、それを追加する必要がある... code_segment_pool = createMemList(size, count); } static void load_task(Scheduler *m, int task_id) { MemorySegment *s = m->get_segment( task_list[task_id].location, m->code_segment_pool, task_list[task_id].end-task_list[task_id].location); task_list[task_id].segment = s; #if 0 fprintf(stderr,"loadng task id %d at 0x%x entry 0x%x\n",task_id, (unsigned int)(task_list[task_id].segment->data ), (unsigned int)( (char*)task_list[task_id].segment->data + task_list[task_id].entry_offset)); #endif } static void null_loader(Scheduler *m, int task_id) { } static void wait_load(Scheduler *m, int task_id) { #if 0 MemorySegment *s = task_list[task_id].segment; if (s) fprintf(stderr,"wait load task id %d 0x%x\n",task_id,(int)s->data); else fprintf(stderr,"wait load task id %d 000000\n",task_id); #endif // wait for code segment load m->wait_segment(task_list[task_id].segment); // calcurate call address TaskObjectRun run = (TaskObjectRun)( (char*)task_list[task_id].segment->data + task_list[task_id].entry_offset); task_list[task_id].run = run; #if 0 fprintf(stderr,"wait load task id %d done. creator = 0x%x entry_offset = 0x%x\n",task_id, (unsigned int)run, task_list[task_id].entry_offset); #endif } static void null_waiter(Scheduler *m, int task_id) { } extern void register_task(int cmd, TaskObjectRun run) { task_list[cmd].run = run; task_list[cmd].load = null_loader; task_list[cmd].wait = null_waiter; } extern void register_dynamic_task(int cmd, memaddr start, int size, TaskObjectRun run, int entry_offset) { task_list[cmd].run = run; task_list[cmd].location = start; size &= 0xfffffffe; task_list[cmd].end = start+size; task_list[cmd].entry_offset = entry_offset; task_list[cmd].load = load_task; task_list[cmd].wait = wait_load; #if 0 fprintf(stderr,"cmd = %d\n",cmd); fprintf(stderr,"locatation = 0x%x\n",start); fprintf(stderr,"end = 0x%x\n",start+size); fprintf(stderr,"size = 0x%x\n",size); fprintf(stderr,"entry = 0x%x\n",entry_offset); #endif } /*! size 単位のMemory Segment を count 個作る @param [size] リストの要素1つのサイズ @param [count] 要素数 @return allocate した領域のポインタ */ MemList* Scheduler::createMemList(int size, int count) { uint32 head_size = round_up16(sizeof(MemorySegment)); uint32 seg_size = round_up16(head_size+size); char* mseg = (char*)allocate(seg_size*count); MemList* mlist = new MemList((MemorySegment*)mseg); if (!hash) { hash = new MemHash(); } for(int i = 0; i < count; i++) { MemorySegment* next = (MemorySegment*)(mseg+seg_size*i); char* data = (char*)next+head_size; next->data = (void*)data; next->size = size; next->address = (memaddr)next; mlist->addLast(next); } return mlist; } /*! Main Memory のSegmentを取得する @param [addr] Main Memory のアドレス @param [m] Mem List @return allocate した領域のポインタ memory directory にあるべきだが... */ MemorySegment * Scheduler::get_segment(memaddr addr, MemList *m) { MemorySegment *s = m->getFirst(); return get_segment(addr, m, s->size); } MemorySegment * Scheduler::get_segment(memaddr addr, MemList *m, int size) { // memory segment のsizeをoverride する場合がある MemorySegment *s = hash->get(addr); if (s) { /* 既に load されている */ // fprintf(stderr,"get_segement loaded %llx 0x%x size 0x%d\n",addr,s->data,size); m->moveToFirst(s); return s; } /* LRU なので、もっとも使われてない segment を上書きする */ s = m->getLast(); m->moveToFirst(s); memaddr old_addr = s->address; s->tag = get_tag(); dma_load(s->data, addr, size, s->tag); /* 前のをhashから削除 */ hash->remove(old_addr); /* 新しいaddress を登録 */ s->address = addr; hash->put(s->address, s); // fprintf(stderr,"get_segement %llx 0x%x size 0x%d\n",addr, s->data,size); return s; } uint32 Scheduler::get_tag() { static int tag = 16; tag ++; tag &= 0x0f; return tag+16; } /*! Main Memory のSegmentを書き出す Segment は get_segement されていて、 追い出されていてはいけない。 それを保証するのは難しい? @param [addr] Main Memory のアドレス @param [m] Mem List @return allocate した領域のポインタ */ void Scheduler::put_segment(MemorySegment *s) { dma_store(s->data, s->address, s->size, s->tag); } /*! Main Memory のSegmentを読込、書き出しを待つ @param [id] MemorySegment のid */ void Scheduler::wait_segment(MemorySegment *s) { // えーと、dma してない時には、skip しないとだめなんじゃないの? if (s->tag) dma_wait(s->tag); s->tag = 0; } HTask * Scheduler::create_task(int cmd) { return manager->create_task(cmd); } HTaskPtr Scheduler::create_task(int cmd, memaddr r, long rs, memaddr w, long ws) { return manager->create_task(cmd,r,rs,w,ws); } void Scheduler::set_task_depend(HTask * master, HTask * slave) { manager->set_task_depend(master, slave) ; } void Scheduler::spawn_task(HTask * t) { manager->spawn_task(t); } void Scheduler::set_task_cpu(HTask * t, CPU_TYPE cpu) { manager->set_task_cpu(t,cpu); } void* Scheduler::allocate(int size,int align) { return manager->allocate(size,align); } void* Scheduler::allocate(int size) { return manager->allocate(size,DEFAULT_ALIGNMENT); } long Scheduler::get_random() { #if defined(__SPU__) return 0; #else return random(); #endif } /* end */