Mercurial > hg > Members > kono > Cerium
view TaskManager/Fifo/FifoTaskManagerImpl.cc @ 776:5088d70e66c5
heap corruption in TaskArray1
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 05 Mar 2010 10:12:49 +0900 (2010-03-05) |
parents | 31d0a5baafdf |
children | 974cd68383b3 |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "FifoTaskManagerImpl.h" #include "Scheduler.h" #include "SchedTask.h" #include "types.h" #include "error.h" #include "SchedNop.h" #include "SysFunc.h" // static void send_alloc_reply(FifoTaskManagerImpl *tm, int id, MainScheduler *s); FifoTaskManagerImpl::~FifoTaskManagerImpl() { delete mainScheduler; delete taskListImpl ; delete taskQueueImpl ; delete htaskImpl ; } /** * MailManager は PPE スケジューラとのメール交換、 * FifoScheduler は PPE 側のスケジューラ * BufferManager は Task、TaskList などのメモリ管理(大層なことしてないが */ void FifoTaskManagerImpl::init() { // TaskManager から呼ばれるので、かなりの部分は初期化されている。 mainScheduler = new MainScheduler(); mainScheduler->init(this); mainScheduler->id = 0; set_scheduler(mainScheduler); taskListImpl = new TaskListInfo; // taskQueueImpl = new TaskQueueInfo; // htaskImpl = new HTaskInfo(); mainTaskList = taskListImpl->create(); schedTaskManager = new SchedTask(); schedTaskManager->init(0,0,0,mainScheduler); } /** * これは CellTaskManagerImpl から呼ばれる。 * TaskList等 は共用で使うので引数に。 * CellTaskManagerImpl と FifoTaskManagerImpl が同時に * 上のデータにアクセスする事は(今は)ないのでこれでおk */ void FifoTaskManagerImpl::init(MainScheduler *_sched, TaskManagerImpl *tm) { mainScheduler = _sched; mainScheduler->init(this); set_scheduler(mainScheduler); taskListImpl = tm-> taskListImpl ; taskQueueImpl = tm-> taskQueueImpl ; htaskImpl = tm-> htaskImpl ; waitTaskQueue = tm->waitTaskQueue; mainTaskList = taskListImpl->create(); schedTaskManager = new SchedTask(); schedTaskManager->init(0,0,0,mainScheduler); } // void FifoTaskManagerImpl::show_profile() {} // void FifoTaskManagerImpl::start_profile() {} /** * スケジューラに渡す TaskList を取得する。 * * @return 実行タスクリスト * * ActiveTaskQueue (依存条件は満たし済み) のタスクを * 実行タスクリストに入れる */ TaskListPtr FifoTaskManagerImpl::get_runTaskList() { TaskListPtr list, list_top; SimpleTaskPtr task; // Task (SPE に送る Task) if (activeTaskQueue->empty()) { return NULL; } // PPE 側で実行される TaskList list_top = mainTaskList; // list_top->clear() とかの方がいいかもしれん。 list_top = taskListImpl->clear_taskList(list_top); list = list_top; // printf("active task queue length = %d\n",activeTaskQueue->length()); while (HTaskPtr htask = activeTaskQueue->poll()) { task = &list->tasks[list->length++]; if (htask->command==TaskArray1) { // compatibility int next = ((htask->r_size)/sizeof(SimpleTask))+1; if (list->length+next>=TASK_MAX_SIZE) { list->length--; TaskListPtr newList = taskListImpl->create(); list_top = TaskListInfo::append(list_top, newList); list = newList; task = &list->tasks[list->length++]; } Task *array = (Task*)&list->tasks[list->length]; list->length += next; if (list->length>=TASK_MAX_SIZE) { perror("task array1 overflow\n"); } memcpy(array, htask->rbuf, htask->r_size); free(htask->rbuf); htask->rbuf = 0; htask->r_size = 0; *task = *(SimpleTask*)htask; } else { *task = *(SimpleTask*)htask; } if (list->length >= TASK_MAX_SIZE) { TaskListPtr newList = taskListImpl->create(); list_top = TaskListInfo::append(list_top, newList); list = newList; } // activeTaskQueue->free_(htask); ここで free しないで、 // mail を待つ } mainTaskList = list_top; return list_top; } void FifoTaskManagerImpl::run() { TaskListPtr list; while((list = get_runTaskList())) { // list を実行する sendTaskList(list); // ppe scheduler からの mail を調べる mail_check(); } if (!waitTaskQueue->empty()) { get_scheduler()->printf("Dead lock detected\n"); } } /** * @param [list] 実行タスクリスト * @return FifoScheduler からのメール * * [Tasklist] -> [番兵] -> scheduler->run を抜ける */ void FifoTaskManagerImpl::sendTaskList(TaskListPtr list) { // TaskList のアドレスを送る mainScheduler->mail_write_from_host((memaddr)list); // EXIT_COMMAND (番兵的な意味で) // これを読むと、mainScheduler->run() から抜けて来る。 mainScheduler->mail_write_from_host((memaddr)MY_SPE_COMMAND_EXIT); // scheduler は受け取ったメールを元に実行する mainScheduler->run(new SchedNop()); // すべてのlistを実行するまで戻らない } /** * PPE Scheduler からのメールをチェックする * * @param [mail_list] * PPE 側で動く Scheduler からのメールリスト * 終了した Task や、その他(今はまだ実装してないけど)の情報が入ってる * * @return Scheduler が次に実行する Task List * NULL なら全てのタスクが実行終了したということ */ void FifoTaskManagerImpl::mail_check() { while (mainScheduler->has_mail_from_host()) { memaddr data = mainScheduler->mail_read_from_host(); if (data == (memaddr)MY_SPE_STATUS_READY) { __debug_ppe("mail_check(): Task List finish\n"); } else if (data == (memaddr)MY_SPE_COMMAND_EXIT) { __debug_ppe("mail_check(): Task List finish COMMAND\n"); } else if (data == (memaddr)MY_SPE_COMMAND_MALLOC) { // MY_SPE_COMMAND_MALLOC PPE からのmain memory request // 本来は呼ばれないはず... get_scheduler()->printf("error: MY_SPE_COMMAND_MALLOC from PPE\n"); // send_alloc_reply(this, 0, mainScheduler); } else if (data != (memaddr)MY_SPE_NOP) { __debug_ppe("mail_check(): recv from 0x%x\n", data); // post_func を先に実行しないと、systask_finish が active_queue // 移されてから、wait_for されるという事態が起きることがある。 HTaskPtr task = (HTaskPtr)data; task->post_func(schedTaskManager, task->post_arg1, task->post_arg2); check_task_finish(task, waitTaskQueue); } } } #if 0 static void send_alloc_reply(FifoTaskManagerImpl *tm, int id, MainScheduler *s) { /** * info[0] = alloc_id; (CellScheduler::mainMem_alloc 参照) * info[1] = alloc_addr; */ memaddr alloc_info[2]; long alloc_size; long command; alloc_info[0] = s->mail_read_from_host(); alloc_info[1] = s->mail_read_from_host(); command = (long)alloc_info[0]; alloc_size = (long)alloc_info[1]; alloc_info[1] = (memaddr)tm->allocate(alloc_size); s->mail_write_from_host(alloc_info[0]); s->mail_write_from_host(alloc_info[1]); } #endif /** * # # # # # # # # * Abstract Factory Pattern * # # # # # # # */ #ifdef __CERIUM_FIFO__ TaskManagerImpl* create_impl(int num) { return new FifoTaskManagerImpl(); } #endif // __CERIUM_FIFO__