diff TaskManager/kernel/ppe/TaskManagerImpl.cc @ 109:5c194c71eca8

Cerium cvs version
author gongo@gendarme.local
date Wed, 12 Nov 2008 17:39:33 +0900
parents 588ab5f0e659
children 44e3bf914155
line wrap: on
line diff
--- a/TaskManager/kernel/ppe/TaskManagerImpl.cc	Wed Nov 12 17:29:35 2008 +0900
+++ b/TaskManager/kernel/ppe/TaskManagerImpl.cc	Wed Nov 12 17:39:33 2008 +0900
@@ -2,48 +2,35 @@
 #include "TaskManagerImpl.h"
 #include "types.h"
 #include "error.h"
+#include "../sys_task/SysTask.h"
+
+static HTaskPtr systask_start;
+static HTaskPtr systask_finish;
 
 void
-noaction(void)
+noaction(void *p)
 {
 }
 
-TaskManagerImpl::TaskManagerImpl(int num) : machineNum(num) {}
-
-TaskManagerImpl::~TaskManagerImpl(void)
-{
-    delete mailManager;
-    delete scheduler;
-    delete bufferManager;
-}
+TaskManagerImpl::TaskManagerImpl(int num)
+    : machineNum(num), activeTaskQueue(NULL), waitTaskQueue(NULL) {}
 
 void
-TaskManagerImpl::init(void)
+TaskManagerImpl::systask_init(void)
 {
-    mailManager = new MailManager();
-    mailManager->init(20);
+    systask_register();
 
-    scheduler = new MainScheduler();
-    scheduler->init();
-    scheduler->set_mailManager(mailManager);
+    systask_finish = create_task(SYSTASK_FINISH);
+    append_waitTask(systask_finish);
 }
 
 HTaskPtr
-//TaskManagerImpl::create_task(int cmd, int size, DmaBuffer *in_addr, 
-//			     DmaBuffer *out_addr, void (*func)(void))
-TaskManagerImpl::create_task(int cmd, int size, unsigned int in_addr, 
-			     unsigned int out_addr, void (*func)(void))
+TaskManagerImpl::create_task(int cmd)
 {
     HTaskPtr new_task;
 
-    new_task = bufferManager->create_task(cmd, size, in_addr, out_addr);
-
-    if (func == NULL) {
-	new_task->post_func = noaction;
-    } else {
-	new_task->post_func = func;
-    }
-
+    new_task = bufferManager->create_task(cmd);
+    new_task->post_func = noaction;
     new_task->mimpl = this;
 
     return new_task;
@@ -52,6 +39,7 @@
 /**
  * task の依存関係を設定
  * master task が終わってから、slave task を実行するように
+ * master->wait_for(slave);
  */
 void
 TaskManagerImpl::set_task_depend(HTaskPtr master, HTaskPtr slave)
@@ -61,158 +49,186 @@
     m = bufferManager->create_taskQueue(master);
     s = bufferManager->create_taskQueue(slave);
 
-    master->wait_me = TaskQueueInfo::append(master->wait_me, s);
-    slave->wait_i   = TaskQueueInfo::append(slave->wait_i, m);
+    master->wait_me = TaskQueue::append(master->wait_me, s);
+    slave->wait_i   = TaskQueue::append(slave->wait_i, m);
 }
 
+/**
+ * タスクを実行可能キューまたは待機キューへ追加する。
+ * 依存関係が満たされていれば active, まだだったら wait へ。
+ * task->spawn();
+ */
 void
 TaskManagerImpl::spawn_task(HTaskPtr task)
 {
+    // waiter // master
+    // waitee // slave
     if (task->wait_i == NULL) {
-	bufferManager->append_activeTask(task);
+	append_activeTask(task);
     } else {
-	bufferManager->append_waitTask(task);	
+	append_waitTask(task);	
     }
+
+    systask_finish->wait_for(task);
 }
 
+/**
+ * Task を実行可能キューに追加する
+ */
+void
+TaskManagerImpl::append_activeTask(HTaskPtr task)
+{
+    TaskQueuePtr q;
+
+    q = bufferManager->create_taskQueue(task);
+    activeTaskQueue = TaskQueue::append(activeTaskQueue, q);
+}
+
+/**
+ * タスクが実行する CPU を選択する
+ *
+ * 現在は CPU_PPE, CPU_SPE, SPE_ANY, SPE_0, SPE_1, ..., SPE_5
+ * types.h に書いてます。
+ */
 void
 TaskManagerImpl::set_task_cpu(HTaskPtr task, CPU_TYPE type)
 {
     task->cpu_type = type;
 }
 
-TaskListPtr
-TaskManagerImpl::set_task(void)
+/**
+ * 終了したタスクから依存の処理とか
+ * post_func() はこのタスクが終了したら実行する関数。
+ * 今のところ使ってないっす
+ *
+ * @param [task] 終了したタスク
+ */
+void
+TaskManagerImpl::check_task_finish(HTaskPtr task)
 {
-    // ここ...直すかな
-    TaskListPtr list;
-    TaskQueuePtr queue;
-    TaskQueuePtr d;
-    HTaskPtr htask;
-    TaskPtr task;
+    notify_wait_taskQueue(task, task->wait_me);
+    task->post_func(task->post_arg);
+    bufferManager->free_task(task);
+}
 
-    queue = bufferManager->activeTaskQueue;
-    if (queue == NULL) {
-	return NULL;
+/**
+ * 終了したタスク [depend] を待っている TaskList に
+ * 終わった事を知らせる(削除する
+ */
+void
+TaskManagerImpl::notify_wait_taskQueue(HTaskPtr depend, TaskQueuePtr list)
+{
+    TaskQueuePtr p;
+    HTaskPtr task;    
+
+    p = list; // wait task list
+
+    while (p) {
+	task = (HTaskPtr)p->task;
+	task->wait_i = remove_taskQueue_eq_task(task->wait_i, depend);
+	p = p->next;
     }
 
-    bufferManager->clear_taskList();
- 
-    while (queue) {
-	list = bufferManager->get_available_taskList();
-	htask = queue->task;
-	d = queue;
-	queue = queue->next;
+    remove_taskQueue_all(list);
+}
+
+void
+TaskManagerImpl::append_waitTask(HTaskPtr task)
+{
+    TaskQueuePtr q;
+
+    q = bufferManager->create_taskQueue(task);
+    waitTaskQueue = TaskQueue::append(waitTaskQueue, q);
+}
+
+/**
+ * waitQueue の中で依存関係を満たしたタスクは
+ * activeQueue へ移す
+ */
+void
+TaskManagerImpl::wakeup_waitTask(void)
+{
+    TaskQueuePtr p, tmp;
 
-	task = &list->tasks[list->length++];
-	task->command  = htask->command;
+    p = waitTaskQueue;
+    while (p) {
+	HTaskPtr task = (HTaskPtr)p->task;
+	tmp = p;
+	p = p->next;
+	if (task->wait_i == NULL) {
+	    append_activeTask(task);
+	    waitTaskQueue = remove_taskQueue(waitTaskQueue, tmp);
+	}
+    }
+}
+
+void
+TaskManagerImpl::remove_taskQueue_all(TaskQueuePtr list)
+{
+    TaskQueuePtr p = list;
+    TaskQueuePtr p1;
+
+    while (p != NULL) {
+	p1 = p->next;
+	bufferManager->free_taskQueue(p);
+	p = p1;
+    }
+}
 
-#if 0
-	// Fix me !!!!!
-	// ださい
-	// かっこいい class 判定がないものか。typeinfoだっけ?
-	// in,out にあるのが DmaBuffer 以外だったら通信させない決まりにしたい
-	if (htask->in_addr != 0) {
-	    htask->in_addr->get_buffer(&task->in_addr);
-	} else {
-	    task->in_addr = 0;
+/**
+ * [list] が持つ queue->task の中に [task] と同じ奴があれば
+ * 削除する。まあ remove_taskQueue() の HTask で比較するverです。
+ * こういうのはオーバーロードでやるもんなのかな?
+ */
+TaskQueuePtr
+TaskManagerImpl::remove_taskQueue_eq_task(TaskQueuePtr list, HTaskPtr task)
+{
+    TaskQueuePtr p = list;
+    TaskQueuePtr p1;
+    
+    if (p == NULL) return p;
+
+    if (p->task == task) {
+	list = list->next;
+	bufferManager->free_taskQueue(p);
+    } else {
+	p1 = p->next;
+	while (p1 && p1->task && p1->task != task) {
+	    p1 = p1->next;
+	    p = p->next;
+	}
+	if (p1) {
+	    p->next = p1->next;
+	    bufferManager->free_taskQueue(p1);
 	}
-	if (htask->out_addr != 0) {
-	    htask->out_addr->get_buffer(&task->out_addr);
-	} else {
-	    task->out_addr = 0;
+    }
+
+    return list;    
+}
+
+TaskQueuePtr
+TaskManagerImpl::remove_taskQueue(TaskQueuePtr list, TaskQueuePtr q)
+{
+    TaskQueuePtr p = list;
+    TaskQueuePtr p1;
+
+    if (!p) return p;
+
+    if (p == q) {
+	list = list->next;
+	bufferManager->free_taskQueue(p);
+    } else {
+	p1 = p->next;
+	while (p1 && p1 != q) {
+	    p1 = p1->next;
+	    p = p->next;
 	}
-#else
-	task->in_addr  = htask->in_addr;
-	task->out_addr = htask->out_addr;
-#endif
-	task->in_size  = htask->in_size;
-	task->self = htask;
-
-	bufferManager->free_taskQueue(d);
+	if (p1) {
+	    p->next = p1->next;
+	    bufferManager->free_taskQueue(p1);
+	}
     }
-    bufferManager->activeTaskQueue = NULL;
 
     return list;
 }
 
-void
-TaskManagerImpl::run(void)
-{
-    TaskListPtr list;
-    MailQueuePtr list_mail; // task list
-    MailQueuePtr sentinel;  // 番兵
-    MailQueuePtr in_mail_list = NULL;
-    MailQueuePtr out_mail_list = NULL;
-
-    // 暫定
-    list = set_task();
-
-    list_mail =	mailManager->create((unsigned int)list);
-    in_mail_list = MailManager::append_mailQueue(in_mail_list, list_mail);
-
-    
-    // Fix me
-    // spe で仕事中のタスクがあったとしても
-    // ppe 側で active なリストが無くなれば、
-    // たとえ spe の task を待つ wait なリストがあったとしても
-    // loop を抜けて終わってしまう。
-    // ppe側のタスクだけじゃなく、spe 側も全て終わったっていう判定が必要だな。
-    // この do-while の一つ外でいいかなー
-    do {
-	sentinel  = mailManager->create(MY_SPE_COMMAND_EXIT);
-	in_mail_list = MailManager::append_mailQueue(in_mail_list, sentinel);
-
-	scheduler->send_mailList(in_mail_list);
-	scheduler->run();
-	out_mail_list = scheduler->recv_mailList();
-
-	// out_mail_list には、ppe scheduler からの mail がある
-	in_mail_list = mail_check(out_mail_list);
-    } while (in_mail_list);
-}
-
-/**
- * PPE Scheduler からのメールをチェックする
- */
-MailQueuePtr
-TaskManagerImpl::mail_check(MailQueuePtr mail_list)
-{
-    MailQueuePtr q = mail_list;
-    MailQueuePtr d;
-    MailQueuePtr ret = NULL;
-    unsigned int data;
-    TaskListPtr next_list;
-
-    while (q) {
-	data = q->data;
-
-	if (data == MY_SPE_STATUS_READY) {
-	    __debug_ppe("[FIFO] finish\n");
-	    next_list = set_task();
-	    if (next_list != NULL) {
-		d = mailManager->create((unsigned int)next_list);
-		ret = MailManager::append_mailQueue(ret, d);
-	    }
-	} else {
-	    __debug_ppe("[PPE] recv from : 0x%x\n", data);
-	    bufferManager->check_task_finish((HTaskPtr)data);
-	}
-
-	d = q;
-	q = q->next;
-
-	mailManager->free(d);
-    }
-
-    return ret;
-}
-
-/**
- * 型名指定するには template だけど...
- */
-DmaBuffer*
-TaskManagerImpl::allocate(int size)
-{
-    return new DmaBuffer(size);
-}