diff TaskManager/kernel/schedule/SchedTask.cc @ 109:028ffc9c0375 draft

Cerium cvs version
author gongo@gendarme.local
date Wed, 12 Nov 2008 17:39:33 +0900
parents 3e331f7576a1
children e3b7776b1420
line wrap: on
line diff
--- a/TaskManager/kernel/schedule/SchedTask.cc	Wed Nov 12 17:29:35 2008 +0900
+++ b/TaskManager/kernel/schedule/SchedTask.cc	Wed Nov 12 17:39:33 2008 +0900
@@ -1,29 +1,113 @@
+#include <stdlib.h>
+#include <string.h>
 #include "SchedTask.h"
 #include "SchedTaskList.h"
 #include "SchedNop2Ready.h"
 #include "DmaManager.h"
 #include "error.h"
 #include "TaskManager.h"
-#include "SymTable.h"
+
+extern Scheduler::TaskObject task_list[MAX_TASK_OBJECT];
 
-SymTable *TaskManager::symtb;
+SchedTask*
+CreateSchedTask(TaskListPtr taskList, Scheduler *sched)
+{
+    TaskPtr task = &taskList->tasks[sched->curIndex_taskList++];
+    
+    return task_list[task->command](taskList, task, sched->get_curReadBuf(),
+				    sched->get_curWriteBuf(), sched);
+}
 
-SchedTask::SchedTask(TaskListPtr _list, TaskPtr _task, void *rbuf, void *wbuf,
-		     DmaManager* cn)
+SchedTask::SchedTask(TaskListPtr _list, TaskPtr _task, ListDataPtr rbuf,
+		     ListDataPtr wbuf, Scheduler* sc)
 {
-    list = _list;
-    task = _task;
-    readbuf = rbuf;
-    writebuf = wbuf;
-    connector = cn;
+    __list        = _list;
+    __task        = _task;
+    __inListData  = rbuf;
+    __outListData = wbuf;
+    __readbuf     = NULL;
+    __writebuf    = NULL;
+    __scheduler   = sc;
+    __taskGroup   = NULL;
+    __renew_flag  = 0;
+
+    smanager = new STaskManager(this);
 }
 
+SchedTask::~SchedTask(void)
+{
+    if (__flag_renewTask) {
+	/**
+	 * __inListData と __outListData はタスク自身のものなので
+	 * 終わったら即 free する。
+	 */
+	free(__inListData);
+        free(__outListData);
+ 
+	/**
+	 * __list != NULL の場合、
+	 * この Task が __list の最後の Task になるので (SchedTask::next 参照)
+	 * このタイミングで __list を解放する
+	 *   (free に渡されるアドレスが正しいものとなる)。
+	 * それ以外の Task では当然解放しない。
+	 *  __list == NULL なので、free に渡しても無問題
+	 */
+	free(__list);
+    }
+
+    delete smanager;
+}
+
+void
+SchedTask::__init__(void)
+{
+    /**
+     * task->inData や task->outData が
+     * PPE のものか、SPE のものかって
+     * アドレスで判定できれば楽になると思うんだが。。。
+     */
+    /**
+     * 関数ポインタでやるか・・?
+     */
+    if (__flag_renewTask == 0) {
+	__scheduler->dma_load(__inListData, (uint32)__task->inData,
+			      sizeof(ListData), DMA_READ_IN_LIST);
+	__scheduler->dma_load(__outListData, (uint32)__task->outData,
+			      sizeof(ListData), DMA_READ_OUT_LIST);
+	
+	__taskGroup = new TaskGroup;
+	__taskGroup->command = __task->self;
+    } else {
+	__inListData = __task->inData;
+	__outListData = __task->outData;
+	__taskGroup = (TaskGroupPtr)__task->self;
+    }
+}
+
+
+/**
+ * [Todo]
+ *   データの読み込み場所を readbuf ではなく、
+ *   ユーザ自身で決めれるようになるといいかもしれない。
+ *
+ *   # TaskManager が勝手に消すことなく、
+ *   # ユーザが SPE 上に持ち続けることができるため。
+ *   # もちろん管理はユーザに任せるわけだ。
+ */
 void
 SchedTask::read(void)
 {    
     __debug("[SchedTask:%s]\n", __FUNCTION__);
 
-    connector->dma_load(readbuf, task->in_addr, task->in_size, DMA_READ);
+    // wait for load inListData 
+    __scheduler->dma_wait(DMA_READ_IN_LIST);
+
+    // 読むデータが一つもなければ無視
+    if (__inListData->length < 1 || __inListData->size == 0) return;
+
+    // load Input Data
+    __readbuf = __scheduler->allocate(__inListData->size);
+    __scheduler->dma_loadList(__inListData, __readbuf, DMA_READ);
 }
 
 void
@@ -31,26 +115,33 @@
 {
     __debug("[SchedTask:%s]\n", __FUNCTION__);
 
-    connector->dma_wait(DMA_READ);
+    // wait for load outListData 
+    __scheduler->dma_wait(DMA_READ_OUT_LIST);
+    __scheduler->dma_wait(DMA_READ);
+
+    __writebuf = __scheduler->allocate(__outListData->size);
 
-    __debug("  task->command  = %d\n", task->command);
-    __debug("  task->in_size  = %d\n", task->in_size);
-    __debug("  task->in_addr  = 0x%x\n", task->in_addr);
-    __debug("  task->out_addr = 0x%x\n", task->out_addr);
-    __debug("  list->next     = 0x%x\n", (unsigned int)list->next);
-    __debug("  list->length   = 0x%x\n", (unsigned int)list->length);
+    __debug("  task->command  = %d\n", __task->command);
+    __debug("  task->in_size  = %d\n", __task->in_size);
+    __debug("  task->in_addr  = 0x%x\n", __task->in_addr);
+    __debug("  task->out_addr = 0x%x\n", __task->out_addr);
+    __debug("  list->next     = 0x%x\n", (unsigned int)__list->next);
+    __debug("  list->length   = 0x%x\n", (unsigned int)__list->length);
 
-    // obsolute
-    //   task->in_size = func_list[task->command](writebuf, readbuf);
+    run(__readbuf, __writebuf);
+
+    // 書き込む領域が要らなければ無視
+    if (__outListData->size > 0) {
+	__scheduler->dma_storeList(__outListData, __writebuf, DMA_WRITE);
+    }
 
-    // ごちゃごちゃしてるな
-    // 最初から void* じゃなくて 関数ポインタ としていれるべきか?
-    //int (*func)(void*, void*)
-    //= (int (*)(void*,void*))TaskManager::get_address(task->command);
-    SymTable::FuncObject func = TaskManager::get_address(task->command);
-    task->in_size = func(readbuf, writebuf);
-    //task->in_size = func((void*)task->in_addr, (void*)task->out_addr);
-    connector->dma_store(writebuf, task->out_addr, task->in_size, DMA_WRITE);
+    if (__taskGroup->status() != 0) {
+	__task->self = __taskGroup->command;
+	delete __taskGroup;
+	__taskGroup = NULL;
+    }
+
+    free(__readbuf);
 }
 
 void
@@ -58,45 +149,174 @@
 {
     __debug("[SchedTask:%s]\n", __FUNCTION__);
 
-    connector->dma_wait(DMA_WRITE);
-    connector->mail_write((unsigned int)task->self);
+    __scheduler->dma_wait(DMA_WRITE);
+
+    free(__writebuf);
+
+    /**
+     * タスクが生成されている場合、
+     * そのタスクが終わってからこのタスク終了コマンドを送る。
+     * # コマンドは生成されたタスクに引き継がれる
+     */
+    if (__task->self == MY_SPE_NOP) return;
+
+    if (__flag_renewTask) {
+	uint32 cmd;
+	
+	__taskGroup->remove(__task);
+	cmd = __taskGroup->status();
+
+	if (cmd != 0) {
+	    delete __taskGroup;
+	    __scheduler->mail_write(cmd);
+	}
+    } else {
+	if (__renew_flag == 0) {
+	    __scheduler->mail_write(__task->self);
+	}
+    }
 }
-
+    
 SchedTaskBase*
 SchedTask::next(Scheduler *m, SchedTaskBase *p)
 {
     __debug("[SchedTask:%s]\n", __FUNCTION__);
 
     delete p;
- 
-    // ここ直さねば。どうやって if 文消そう?
-    // オブジェクト増やせばいいのかな
-    if (list->length == 0) {
-	if (list->next == 0) {
-	    return new SchedNop2Ready(connector);
+
+    if (__scheduler->curIndex_taskList < __list->length) {
+	SchedTask* schedTask = CreateSchedTask(__list, __scheduler);
+	schedTask->__flag_renewTask = this->__flag_renewTask;
+	schedTask->__init__();
+
+	/**
+	 * この理由は SchedTask:~SchedTask() で
+	 */
+	__list = NULL;
+
+	return schedTask;
+    } else {
+	uint32 nextList = (uint32)__list->next;
+
+	if (nextList == 0) {
+	    return new SchedNop2Ready(__scheduler);
 	} else {
-	    return new SchedTaskList((unsigned int)list->next,
-				     m->get_curListBuf(), connector);
+	    return new SchedTaskList(nextList, __scheduler);
 	}
-    } else {
-	//return new SchedTask(list, m->get_curReadBuf(),
-	//m->get_curWriteBuf(), connector);
+    }
+}
 
-	// 本当は、ここで task->command に対応する、
-	// SchedTask を継承する class を作ればいい。。。はず
-	return new SchedTask(list, &list->tasks[--list->length],
-			     m->get_curReadBuf(), m->get_curWriteBuf(),
-			     connector);
+/**
+ * task->add_input で与えられた順番に対応する index (0〜n-1) で、
+ * buffer から対応するデータを返す。
+ */
+void*
+SchedTask::get_input(void *buff, int index)
+{
+    if (buff != NULL) {
+	return (void*)((int)buff + __inListData->bound[index]);
+    } else {
+	return NULL;
+    }
+}
+
+/**
+ * write buffer の領域を返す。
+ */
+void*
+SchedTask::get_output(void *buff, int index)
+{
+    if (buff != NULL) {
+	return (void*)((int)buff + __outListData->bound[index]);
+    } else {
+	return NULL;
     }
 }
 
-#if 0
-SchedTask
-createSchedTask(TaskListPtr list, void *rbuf, void *wbuf, DmaManager *cn)
+int
+SchedTask::get_param(int index)
+{
+    return __task->param[index];
+}
+
+TaskPtr
+SchedTask::create_task(int cmd)
+{
+    TaskListPtr taskList = __scheduler->get_renewListBuf();
+    TaskPtr p = &taskList->tasks[taskList->length++];
+    p->command = cmd;
+
+    p->inData = (ListData*)__scheduler->allocate(sizeof(ListData));
+    p->outData = (ListData*)__scheduler->allocate(sizeof(ListData));
+
+    p->inData->clear();
+    p->outData->clear();
+
+    p->self = MY_SPE_NOP;
+    p->param_size = 0;
+
+    return p;
+}
+
+/**
+ * 名前が。。。
+ */
+void
+SchedTask::wait_task(TaskPtr waitTask)
 {
-    TaskPtr task;
+    waitTask->self = (uint32)__taskGroup;
+
+    __scheduler->add_groupTask(__taskGroup, waitTask);
+
+    __renew_flag++;
+}
+
+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_free(int id) {
+    __scheduler->global_free(id);
+}
+
+void
+SchedTask::mainMem_alloc(int id, int size) {
+    __scheduler->mainMem_alloc(id, size);
+}
 
-    task = &list->tasks[--list->length];
-    
+void
+SchedTask::mainMem_wait(void) {
+    __scheduler->mainMem_wait();
+}
+
+void*
+SchedTask::mainMem_get(int id) {
+    return __scheduler->mainMem_get(id);
+}
+
+void*
+SchedTask::allocate(int size) {
+    return __scheduler->allocate(size);
 }
-#endif
+
+void
+SchedTask::dma_load(void *buf, uint32 addr, uint32 size, uint32 mask) {
+    __scheduler->dma_load(buf, addr, size, mask);
+}
+
+void
+SchedTask::dma_store(void *buf,uint32 addr, uint32 size, uint32 mask) {
+    __scheduler->dma_store(buf, addr, size, mask);
+}
+
+void
+SchedTask::dma_wait(uint32 mask) {
+    __scheduler->dma_wait(mask);
+}