diff TaskManager/Fifo/FifoTaskManagerImpl.cc @ 109:5c194c71eca8

Cerium cvs version
author gongo@gendarme.local
date Wed, 12 Nov 2008 17:39:33 +0900
parents 7492eb28b577
children 72dcf908ec52
line wrap: on
line diff
--- a/TaskManager/Fifo/FifoTaskManagerImpl.cc	Wed Nov 12 17:29:35 2008 +0900
+++ b/TaskManager/Fifo/FifoTaskManagerImpl.cc	Wed Nov 12 17:39:33 2008 +0900
@@ -3,25 +3,235 @@
 #include <string.h>
 #include "FifoTaskManagerImpl.h"
 #include "types.h"
+#include "error.h"
 
+FifoTaskManagerImpl::~FifoTaskManagerImpl(void)
+{
+    delete mailManager;
+    delete scheduler;
+    delete bufferManager;
+}
+
+/**
+ * MailManager は PPE スケジューラとのメール交換、
+ * FifoScheduler は PPE 側のスケジューラ
+ * BufferManager は Task、TaskList などのメモリ管理(大層なことしてないが
+ */
 void
 FifoTaskManagerImpl::init(void)
 {
-    TaskManagerImpl::init();
+    mailManager = new MailManager();
+    mailManager->init(20);
+
+    scheduler = new MainScheduler();
+    scheduler->init();
+    scheduler->set_mailManager(mailManager);
 
     bufferManager = new BufferManager;
     bufferManager->init();
+
+    mainTaskList = bufferManager->create_taskList();
+}
+
+/**
+ * これは CellTaskManagerImpl から呼ばれる。
+ * BufferManager は共用で使うので引数に。
+ * CellTaskManagerImpl と FifoTaskManagerImpl が同時に
+ * 上のデータにアクセスする事は(今は)ないのでこれでおk 
+ */
+void
+FifoTaskManagerImpl::init(MainScheduler *_sched, BufferManager *buff)
+{
+    mailManager = new MailManager();
+    mailManager->init(20);
+
+    //scheduler = new MainScheduler();
+    scheduler = _sched;
+    scheduler->init();
+    scheduler->set_mailManager(mailManager);
+
+    bufferManager = buff;
+
+    mainTaskList = bufferManager->create_taskList();
+}
+
+/**
+ * スケジューラに渡す TaskList を取得する。
+ *
+ * @return 実行タスクリスト
+ *
+ * ActiveTaskQueue (依存条件は満たし済み) のタスクを
+ * 実行タスクリストに入れる
+ */
+TaskListPtr
+FifoTaskManagerImpl::get_runTaskList(void)
+{
+    TaskListPtr list, list_top;
+    TaskQueuePtr queue;
+    TaskQueuePtr d;
+    HTaskPtr htask; // HTask (PPE にある)
+    TaskPtr task; // Task (SPE に送る Task)
+
+    queue = activeTaskQueue;
+    if (queue == NULL) {
+	return NULL;
+    }
+
+    // PPE 側で実行される TaskList
+    list_top = mainTaskList;
+
+    // list_top->clear() とかの方がいいかもしれん。
+    list_top = bufferManager->clear_taskList(list_top);
+    list = list_top;
+
+    while (queue) {
+	htask = (HTaskPtr)queue->task;
+	d = queue;
+	queue = queue->next;
+
+	task = &list->tasks[list->length++];
+
+#if 0
+	task->command  = htask->command;
+	task->inData   = htask->inData;
+	task->outData  = htask->outData;
+	task->self     = (unsigned int)htask;
+#else
+	memcpy(task, htask, sizeof(Task));
+#endif
+
+	if (list->length >= TASK_MAX_SIZE) {
+	    TaskListPtr newList = bufferManager->create_taskList();
+	    list_top = TaskListInfo::append(list_top, newList);
+	    list = newList;
+	}
+
+	bufferManager->free_taskQueue(d);
+    }
+
+    activeTaskQueue = NULL;
+    mainTaskList = list_top;
+
+    return list_top;
+}
+
+
+void
+FifoTaskManagerImpl::run(void)
+{
+    TaskListPtr list;
+    MailQueuePtr mail;
+
+    list = get_runTaskList();
+
+    do {
+	// list を実行する
+	mail = schedule(list);
+
+	// mail には、ppe scheduler からの mail がある
+	mail_check(mail);
+
+	// 依存関係を満たしたものは実行可能キューへ
+	wakeup_waitTask();
+	list = get_runTaskList();
+    } while (list);
+}
+
+/**
+ * @param [list] 実行タスクリスト
+ * @return FifoScheduler からのメール
+ *
+ * [Tasklist] -> [番兵] -> scheduler->run を抜ける
+ */
+MailQueuePtr
+FifoTaskManagerImpl::schedule(TaskListPtr list)
+{
+    MailQueuePtr list_mail; // task list
+    MailQueuePtr sentinel;  // 番兵
+    MailQueuePtr in_mail_list = NULL;
+    MailQueuePtr out_mail_list = NULL;
+
+    // TaskList のアドレス
+    list_mail =	mailManager->create((unsigned int)list);
+    in_mail_list = MailManager::append_mailQueue(in_mail_list, list_mail);
+
+    // EXIT_COMMAND (番兵的な意味で)
+    sentinel  = mailManager->create(MY_SPE_COMMAND_EXIT);
+    in_mail_list = MailManager::append_mailQueue(in_mail_list, sentinel);
+    
+    // scheduler は受け取ったメールを元に実行する
+    scheduler->send_mailList(in_mail_list);
+    scheduler->run();
+    out_mail_list = scheduler->recv_mailList(); 
+
+    return out_mail_list;
+}
+
+/**
+ * PPE Scheduler からのメールをチェックする
+ *
+ * @param [mail_list]
+ *        PPE 側で動く Scheduler からのメールリスト
+ *        終了した Task や、その他(今はまだ実装してないけど)の情報が入ってる
+ *
+ * @return Scheduler が次に実行する Task List                       
+ *         NULL なら全てのタスクが実行終了したということ
+ */
+void
+FifoTaskManagerImpl::mail_check(MailQueuePtr mail_list)
+{
+    MailQueuePtr q = mail_list;
+    MailQueuePtr d;
+    unsigned int data;
+
+    while (q) {
+	data = q->data;
+
+	/**
+	 * MY_SPE_STATUS_READY: SPE が持ってた Task 全て終了
+	 * MY_SPE_NOP: 特に意味のないコマンド
+	 * それ以外:終了したタスク(PPEにあるのでアドレス
+	 *
+	 * MY_SPE_NOP が 0 なので、
+	 * 下のように data > MY_SPE_NOP とかしています。
+	 * 一目でよくわからない書き方なんで、直したいところですが。。。
+	 */
+	if (data == MY_SPE_STATUS_READY) {
+	    __debug_ppe("mail_check(): Task List finish\n");
+	} else if (data > MY_SPE_NOP) {
+	    __debug_ppe("mail_check(): recv from 0x%x\n", data);
+	    check_task_finish((HTaskPtr)data);
+	}
+
+	d = q;
+	q = q->next;
+
+	mailManager->free(d);
+    }
 }
 
 void
-FifoTaskManagerImpl::spawn_task(HTaskPtr task)
+FifoTaskManagerImpl::mail_check(MailQueuePtr mail_list, TaskQueuePtr *wait)
 {
-    TaskManagerImpl::spawn_task(task);
-    //run();
+    waitTaskQueue = *wait;
+    mail_check(mail_list);
 }
 
-TaskManagerImpl*
+void*
+FifoTaskManagerImpl::allocate(int size)
+{
+    return malloc(size);
+}
+
+/**
+ * こういう使い方を
+ *   Abstract Factory Pattern
+ * というらしい。
+ */
+#ifdef __CERIUM_FIFO__
+TaskManagerImpl* 
 create_impl(int num)
 {
     return new FifoTaskManagerImpl();
 }
+#endif // __CERIUM_FIFO__