Mercurial > hg > Members > e085722 > Cerium
comparison TaskManager/kernel/ppe/TaskManagerImpl.cc @ 0:04e28d8d3c6f
first commit
author | Daiki KINJYO <e085722@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 08 Nov 2010 01:23:25 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:04e28d8d3c6f |
---|---|
1 #include <stdio.h> | |
2 #include "TaskManagerImpl.h" | |
3 #include "types.h" | |
4 #include "error.h" | |
5 #include "SchedTask.h" | |
6 #include "Scheduler.h" | |
7 #include "SysTask.h" | |
8 #include "SysFunc.h" | |
9 #include <string.h> | |
10 | |
11 // singleton | |
12 QueueInfo<TaskQueue> *taskQueuePool = new QueueInfo<TaskQueue>() ; | |
13 QueueInfo<HTask> *htaskPool = new QueueInfo<HTask>() ; | |
14 QueueInfo<TaskList> *taskListPool = new QueueInfo<TaskList>() ; | |
15 | |
16 | |
17 static HTaskPtr systask_start; | |
18 static HTaskPtr systask_finish; | |
19 | |
20 static void | |
21 noaction(SchedTask *s, void *read, void *write) | |
22 { | |
23 } | |
24 | |
25 TaskManagerImpl::TaskManagerImpl(int num) | |
26 : machineNum(num){ | |
27 // 実行可能なHTaskのリスト | |
28 activeTaskQueue = new QueueInfo<HTask>(htaskPool); | |
29 // wait_forで止まっているHTaskのリスト。必要ないが、Dead lock detection に使う | |
30 waitTaskQueue = new QueueInfo<HTask>(htaskPool); | |
31 // HTask の factory. QueueInfo<HTask> ならなんでもいい。 | |
32 htaskImpl = waitTaskQueue ; // any QueueInfo<HTask> | |
33 // Task の dependency を表現する double linked list. QueueInfo<HTask> とは別に必要。 | |
34 taskQueueImpl = new QueueInfo<TaskQueue>(taskQueuePool); | |
35 } | |
36 | |
37 /** | |
38 * 一番最初に PPE で実行される systask_start | |
39 */ | |
40 void | |
41 TaskManagerImpl::systask_init() | |
42 { | |
43 systask_register(); | |
44 systask_start = create_task(StartTask,0,0,0,0,__builtin_return_address(0)); | |
45 systask_finish = create_task(FinishTask,0,0,0,0,__builtin_return_address(0)); | |
46 | |
47 systask_start->spawn(); | |
48 | |
49 // すべての Task が FinishTask を wait_for すると、 | |
50 // あらゆる Task が FinishTask の waiting task queue を操作する | |
51 // ことになる。それは、重すぎる。PPE/SPE Task が終了した時点で、 | |
52 // TaskManager が実行する方が安い。 | |
53 // append_waitTask(systask_finish); | |
54 } | |
55 | |
56 /** | |
57 * Create Simple Task | |
58 */ | |
59 HTaskPtr | |
60 TaskManagerImpl::create_task(int cmd,memaddr rbuf, long r_size, memaddr wbuf, long w_size, void *from) { | |
61 HTaskPtr new_task; | |
62 | |
63 new_task = htaskImpl->create(); | |
64 new_task->init(cmd, rbuf, r_size, wbuf, w_size); | |
65 new_task->post_func = noaction; | |
66 new_task->mimpl = this; | |
67 new_task->from = (memaddr)from; | |
68 #ifdef EARLY_TOUCH | |
69 if (rbuf) { | |
70 if ((unsigned long)rbuf&0xf) { | |
71 printf("Data is not aligned. command = %d, addr = 0x%lx, size = %ld\n", | |
72 cmd, (unsigned long)rbuf, r_size); | |
73 } | |
74 char *p = (char *)rbuf; char b = *p; | |
75 p = (char *)(rbuf+r_size-1); b += *p; | |
76 } | |
77 if (wbuf) { | |
78 if ((unsigned long)wbuf&0xf) { | |
79 printf("Data is not aligned. command = %d, addr = 0x%lx, size = %ld\n", | |
80 cmd, (unsigned long)wbuf, w_size); | |
81 } | |
82 char *p = (char *)wbuf; char b = *p; | |
83 p = (char *)(wbuf+w_size-1); b += *p; | |
84 } | |
85 #endif | |
86 | |
87 return new_task; | |
88 } | |
89 | |
90 /** | |
91 * Create Compatible Task (TaskArray1) | |
92 */ | |
93 HTaskPtr | |
94 TaskManagerImpl::create_task(int cmd,void *from) | |
95 { | |
96 HTaskPtr new_task; | |
97 | |
98 // for compatibility | |
99 new_task = htaskImpl->create(); new_task->init(TaskArray1); | |
100 new_task->post_func = noaction; | |
101 new_task->mimpl = this; | |
102 new_task->create_task_array(cmd,1,8,8,8); | |
103 // rbuf, r_size were set | |
104 new_task->command = TaskArray1; | |
105 new_task->from = (memaddr)from; | |
106 | |
107 return new_task; | |
108 } | |
109 | |
110 /** | |
111 * Create Task Array | |
112 */ | |
113 HTaskPtr | |
114 TaskManagerImpl::create_task_array(int id, int num_task, int num_param, int num_inData, int num_outData, void *from) | |
115 { | |
116 HTaskPtr ta = create_task(TaskArray,0,0,0,0, from); | |
117 ta->create_task_array(id, num_task, num_param, num_inData, num_outData) ; | |
118 return ta; | |
119 } | |
120 | |
121 /** | |
122 * task の依存関係を設定 | |
123 * master task が終わってから、slave task を実行するように | |
124 * master->wait_for(slave); | |
125 */ | |
126 void | |
127 TaskManagerImpl::set_task_depend(HTaskPtr master, HTaskPtr slave) | |
128 { | |
129 TaskQueuePtr m, s; | |
130 if (!master->self) return; | |
131 | |
132 m = taskQueueImpl->create(); m->init(master); | |
133 s = taskQueueImpl->create(); s->init(slave); | |
134 | |
135 master->wait_me->addLast(s); | |
136 slave->wait_i->addLast(m); | |
137 s->waiter = m; | |
138 } | |
139 | |
140 /** | |
141 * タスクを実行可能キューまたは待機キューへ追加する。 | |
142 * 依存関係が満たされていれば active, まだだったら wait へ。 | |
143 * task->spawn(); | |
144 */ | |
145 void | |
146 TaskManagerImpl::spawn_task(HTaskPtr task) | |
147 { | |
148 // waiter // master | |
149 // waitee // slave | |
150 if (task->wait_i->empty()) { | |
151 append_activeTask(task); | |
152 } else { | |
153 append_waitTask(task); | |
154 } | |
155 } | |
156 | |
157 | |
158 /** | |
159 * Task を実行可能キューに追加する | |
160 */ | |
161 void | |
162 TaskManagerImpl::append_activeTask(HTaskPtr q) | |
163 { | |
164 activeTaskQueue->addLast(q); | |
165 } | |
166 | |
167 /** | |
168 * タスクが実行する CPU を選択する | |
169 * | |
170 * 現在は CPU_PPE, CPU_SPE, SPE_ANY, SPE_0, SPE_1, ..., SPE_5 | |
171 * types.h に書いてます。 | |
172 */ | |
173 void | |
174 TaskManagerImpl::set_task_cpu(HTaskPtr task, CPU_TYPE type) | |
175 { | |
176 if (machineNum==0) | |
177 task->cpu_type = CPU_PPE ; | |
178 else | |
179 task->cpu_type = type; | |
180 } | |
181 | |
182 #if 0 | |
183 static void | |
184 check_wait(TaskManagerImpl *tm, QueueInfo<TaskQueue> *wait_i) { | |
185 for(TaskQueue *t = wait_i->getFirst(); t; t = wait_i->getNext(t)) { | |
186 if (!tm->waitTaskQueue->find(t->task)) { | |
187 printf("stray waiting task%d %lx\n",t->task->command, (long)t->task); | |
188 } else if (tm->activeTaskQueue->find(t->task)) { | |
189 printf(" active task%d in waiting queue %lx\n",t->task->command, (long)t->task); | |
190 } else | |
191 printf("."); | |
192 } | |
193 } | |
194 #endif | |
195 | |
196 /** | |
197 * @brief 終了したタスクから依存の処理とか | |
198 * post_func() はこのタスクが終了したら実行する関数。 | |
199 * | |
200 * @param [task] 終了したタスク | |
201 */ | |
202 void | |
203 TaskManagerImpl::check_task_finish(HTaskPtr me, QueueInfo<HTask> *wait_queue) | |
204 { | |
205 while(TaskQueue *p = me->wait_me->poll()) { | |
206 HTaskPtr you = p->task; | |
207 QueueInfo<TaskQueue> *wait_i = you->wait_i; | |
208 // 相手の wait queue から自分(を指しているTaskQueue)を削除 | |
209 wait_i->remove(p->waiter); | |
210 // queue を free する | |
211 wait_i->free_(p->waiter); | |
212 | |
213 if (wait_i->empty()) { | |
214 wait_queue->remove(you); | |
215 append_activeTask(you); | |
216 } | |
217 | |
218 wait_i->free_(p); // p->wait_i, p->wait_me は再利用される | |
219 } | |
220 | |
221 // me を誰かが持っていて、me が finish した後に、 | |
222 // me->wait_for(i) とか、やられると気まずい。 | |
223 // 特に、me が他人に再利用されていると。そういう時には、 | |
224 // このfreeをコメントアウトしてみる。 | |
225 | |
226 // id かななんかでチェックした方が良いが... | |
227 | |
228 me->self = 0; | |
229 if (!me->flag.no_auto_free) | |
230 htaskImpl->free_(me); | |
231 } | |
232 | |
233 /** | |
234 * @brief 終了したタスクリストの依存の処理 | |
235 * @param [task] 終了したタスク | |
236 */ | |
237 void | |
238 TaskManagerImpl::check_task_list_finish(SchedTask *s, TaskListPtr list, QueueInfo<HTask> *wait_queue) | |
239 { | |
240 for(int i = 0;i<list->length;i++) { | |
241 SimpleTaskPtr task = &list->tasks[i]; | |
242 HTask *me = (HTask*)task->self; | |
243 me->post_func(s, me->post_arg1, me->post_arg2); | |
244 if (task->command==TaskArray1) { | |
245 int next = ((task->r_size)/sizeof(SimpleTask))+1; | |
246 // assert(next<list->length); | |
247 i+=next; | |
248 } | |
249 s->polling(); | |
250 check_task_finish(me, wait_queue); | |
251 } | |
252 } | |
253 | |
254 /** | |
255 * @brief waitTaskqueue への挿入 。必須ではない。 | |
256 * 現状では、dead lock 検出にしか使ってない | |
257 * | |
258 * @param [task] 終了したタスク | |
259 */ | |
260 void | |
261 TaskManagerImpl::append_waitTask(HTaskPtr q) | |
262 { | |
263 waitTaskQueue ->addLast(q); | |
264 } | |
265 | |
266 /** | |
267 @brief htask を DMA でCPUに渡すための TaskList に入れる (copy) | |
268 @param htask | |
269 @param taskList | |
270 TaskList は自動的に延長される | |
271 */ | |
272 void | |
273 TaskManagerImpl::set_taskList(HTaskPtr htask, QueueInfo<TaskList> * taskList) { | |
274 TaskListPtr list ; | |
275 if ( taskList->empty() ) { | |
276 list = taskList->create(); | |
277 taskList->addLast(list); | |
278 } else | |
279 list = taskList->getLast(); | |
280 SimpleTaskPtr task = &list->tasks[list->length++]; | |
281 if (htask->command==TaskArray1) { | |
282 // compatibility | |
283 int next = ((htask->r_size)/sizeof(SimpleTask))+1; | |
284 if (list->length+next>=TASK_MAX_SIZE) { | |
285 list->length--; | |
286 TaskListPtr newList = taskList->create(); | |
287 taskList->addLast(newList); | |
288 list = newList; | |
289 task = &list->tasks[list->length++]; | |
290 } | |
291 Task *array = (Task*)&list->tasks[list->length]; | |
292 list->length += next; | |
293 if (list->length>=TASK_MAX_SIZE) { | |
294 perror("task array1 overflow\n"); | |
295 } | |
296 memcpy(array, htask->rbuf, htask->r_size); | |
297 free(htask->rbuf); | |
298 // htask->rbuf = 0; htask->r_size = 0; we need this... | |
299 *task = *(SimpleTask*)htask; | |
300 } else { | |
301 *task = *(SimpleTask*)htask; | |
302 } | |
303 if (list->length >= TASK_MAX_SIZE) { | |
304 TaskListPtr newList = taskList->create(); | |
305 taskList->addLast(newList); | |
306 list = newList; | |
307 } | |
308 } | |
309 | |
310 | |
311 | |
312 /* end */ |