source: asp3_wo_tecs/trunk/extension/pri_level/kernel/task.c@ 302

Last change on this file since 302 was 302, checked in by ertl-honda, 7 years ago

TECSレスのASP3の開発のため以下のtrunkからコピー
http://dev.toppers.jp/svn/asp3/branches/WO_TECS-3.C.0

File size: 12.0 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2005-2014 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 *
11 * 上記著作権者
12は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
13 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
14 * 変・再é…
15å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
16 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
17 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
18 * スコード中に含まれていること.
19 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
20 * 用できる形で再é…
21å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
22å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
23 * 者
24マニュアルなど)に,上記の著作権表示,この利用条件および下記
25 * の無保証規定を掲載すること.
26 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
27 * 用できない形で再é…
28å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
29 * と.
30 * (a) 再é…
31å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
32マニュアルなど)に,上記の著
33 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
34 * (b) 再é…
35å¸ƒã®å½¢æ…
36‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
37 * 報告すること.
38 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
39 * 害からも,上記著作権者
40およびTOPPERSプロジェクトをå…
41è²¬ã™ã‚‹ã“と.
42 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
43 * 由に基づく請求からも,上記著作権者
44およびTOPPERSプロジェクトを
45 * å…
46è²¬ã™ã‚‹ã“と.
47 *
48 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
49お
50 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
51 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
52 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
53 * の責任を負わない.
54 *
55 * $Id: task.c 244 2014-09-30 18:08:03Z ertl-hiro $
56 */
57
58/*
59 * タスク管理モジュール
60 */
61
62#include "kernel_impl.h"
63#include "task.h"
64#include "taskhook.h"
65#include "wait.h"
66
67#ifdef TOPPERS_tskini
68
69/*
70 * 実行状æ…
71‹ã®ã‚¿ã‚¹ã‚¯
72 */
73TCB *p_runtsk;
74
75/*
76 * 実行すべきタスク
77 */
78TCB *p_schedtsk;
79
80/*
81 * ディスパッチ許可状æ…
82‹
83 */
84bool_t enadsp;
85
86/*
87 * タスクディスパッチ可能状æ…
88‹
89 */
90bool_t dspflg;
91
92/*
93 * レディキュー
94 */
95QUEUE ready_queue[TNUM_TPRI];
96
97/*
98 * レディキューサーチのためのビットマップ
99 */
100#ifdef PRIMAP_LEVEL_1
101uint16_t ready_primap;
102#else /* PRIMAP_LEVEL_1 */
103uint16_t ready_primap1;
104uint16_t ready_primap2[TNUM_PRIMAP2];
105#endif /* PRIMAP_LEVEL_1 */
106
107/*
108 * タスク管理モジュールの初期化
109 */
110void
111initialize_task(void)
112{
113 uint_t i, j;
114 TCB *p_tcb;
115
116 p_runtsk = NULL;
117 p_schedtsk = NULL;
118 enadsp = true;
119 dspflg = true;
120
121 for (i = 0; i < TNUM_TPRI; i++) {
122 queue_initialize(&(ready_queue[i]));
123 }
124#ifdef PRIMAP_LEVEL_1
125 ready_primap = 0U;
126#else /* PRIMAP_LEVEL_1 */
127 ready_primap1 = 0U;
128 for (i = 0; i < TNUM_PRIMAP2; i++) {
129 ready_primap2[i] = 0U;
130 }
131#endif /* PRIMAP_LEVEL_1 */
132
133 for (i = 0; i < tnum_tsk; i++) {
134 j = INDEX_TSK(torder_table[i]);
135 p_tcb = &(tcb_table[j]);
136 p_tcb->p_tinib = &(tinib_table[j]);
137 p_tcb->actque = false;
138 make_dormant(p_tcb);
139 p_tcb->p_lastmtx = NULL;
140 if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) {
141 make_active(p_tcb);
142 }
143 }
144}
145
146#endif /* TOPPERS_tskini */
147
148/*
149 * ビットマップサーチ関数
150 *
151 * bitmap内
152の1のビットの内
153,最も下位(右)のものをサーチし,そのビッ
154 * ト番号を返す.ビット番号は,最下位ビットを0とする.bitmapに0を指定
155 * してはならない.この関数では,bitmapが16ビットであることを仮定し,
156 * uint16_t型としている.
157 *
158 * ビットサーチ命令を持つプロセッサでは,ビットサーチ命令を使うように
159 * 書き直した方が効率が良い場合がある.このような場合には,ターゲット
160 * 依存部でビットサーチ命令を使ったbitmap_searchを定義し,
161 * OMIT_BITMAP_SEARCHをマクロ定義すればよい.また,ビットサーチ命令の
162 * サーチ方向が逆などの理由で優å…
163ˆåº¦ã¨ãƒ“ットとの対応を変更したい場合に
164 * は,PRIMAP_BITをマクロ定義すればよい.
165 *
166 * また,ライブラリにffsがあるなら,次のように定義してライブラリ関数を
167 * 使った方が効率が良い可能性もある.
168 * #define bitmap_search(bitmap) (ffs(bitmap) - 1)
169 */
170#ifndef PRIMAP_BIT
171#define PRIMAP_BIT(pri) (1U << (pri))
172#endif /* PRIMAP_BIT */
173
174#ifndef OMIT_BITMAP_SEARCH
175
176static const unsigned char bitmap_search_table[] = { 0, 1, 0, 2, 0, 1, 0,
177 3, 0, 1, 0, 2, 0, 1, 0 };
178
179Inline uint_t
180bitmap_search(uint16_t bitmap)
181{
182 uint_t n = 0U;
183
184 assert(bitmap != 0U);
185 if ((bitmap & 0x00ffU) == 0U) {
186 bitmap >>= 8;
187 n += 8;
188 }
189 if ((bitmap & 0x0fU) == 0U) {
190 bitmap >>= 4;
191 n += 4;
192 }
193 return(n + bitmap_search_table[(bitmap & 0x0fU) - 1]);
194}
195
196#endif /* OMIT_BITMAP_SEARCH */
197
198/*
199 * 優å…
200ˆåº¦ãƒ“ットマップが空かのチェック
201 */
202Inline bool_t
203primap_empty(void)
204{
205#ifdef PRIMAP_LEVEL_1
206 return(ready_primap == 0U);
207#else /* PRIMAP_LEVEL_1 */
208 return(ready_primap1 == 0U);
209#endif /* PRIMAP_LEVEL_1 */
210}
211
212/*
213 * 優å…
214ˆåº¦ãƒ“ットマップのサーチ
215 */
216Inline uint_t
217primap_search(void)
218{
219#ifdef PRIMAP_LEVEL_1
220 return(bitmap_search(ready_primap));
221#else /* PRIMAP_LEVEL_1 */
222 uint_t i;
223
224 i = bitmap_search(ready_primap1);
225 return(i * TBIT_PRIMAP + bitmap_search(ready_primap2[i]));
226#endif /* PRIMAP_LEVEL_1 */
227}
228
229/*
230 * 優å…
231ˆåº¦ãƒ“ットマップのセット
232 */
233Inline void
234primap_set(uint_t pri)
235{
236#ifdef PRIMAP_LEVEL_1
237 ready_primap |= PRIMAP_BIT(pri);
238#else /* PRIMAP_LEVEL_1 */
239 ready_primap2[pri / TBIT_PRIMAP] |= PRIMAP_BIT(pri % TBIT_PRIMAP);
240 ready_primap1 |= PRIMAP_BIT(pri / TBIT_PRIMAP);
241#endif /* PRIMAP_LEVEL_1 */
242}
243
244/*
245 * 優å…
246ˆåº¦ãƒ“ットマップのクリア
247 */
248Inline void
249primap_clear(uint_t pri)
250{
251#ifdef PRIMAP_LEVEL_1
252 ready_primap &= ~PRIMAP_BIT(pri);
253#else /* PRIMAP_LEVEL_1 */
254 if ((ready_primap2[pri / TBIT_PRIMAP] &= ~PRIMAP_BIT(pri % TBIT_PRIMAP))
255 == 0U) {
256 ready_primap1 &= ~PRIMAP_BIT(pri / TBIT_PRIMAP);
257 }
258#endif /* PRIMAP_LEVEL_1 */
259}
260
261/*
262 * 最高優å…
263ˆé †ä½ã‚¿ã‚¹ã‚¯ã®ã‚µãƒ¼ãƒ
264 */
265#ifdef TOPPERS_tsksched
266
267TCB *
268search_schedtsk(void)
269{
270 uint_t schedpri;
271
272 schedpri = primap_search();
273 return((TCB *)(ready_queue[schedpri].p_next));
274}
275
276#endif /* TOPPERS_tsksched */
277
278/*
279 * 実行できる状æ…
280‹ã¸ã®é·ç§»
281 *
282 * 実行すべきタスクを更新するのは,実行できるタスクがなかった場合と,
283 * p_tcbの優å…
284ˆåº¦ãŒå®Ÿè¡Œã™ã¹ãã‚¿ã‚¹ã‚¯ã®å„ªå…
285ˆåº¦ã‚ˆã‚Šã‚‚高い場合である.
286 */
287#ifdef TOPPERS_tskrun
288
289void
290make_runnable(TCB *p_tcb)
291{
292 uint_t pri = p_tcb->priority;
293
294 queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue));
295 primap_set(pri);
296
297 if (dspflg) {
298 if (p_schedtsk == (TCB *) NULL || pri < p_schedtsk->priority) {
299 p_schedtsk = p_tcb;
300 }
301 }
302}
303
304#endif /* TOPPERS_tskrun */
305
306/*
307 * 実行できる状æ…
308‹ã‹ã‚‰ä»–の状æ…
309‹ã¸ã®é·ç§»
310 *
311 * 実行すべきタスクを更新するのは,p_tcbが実行すべきタスクであった場合
312 * である.p_tcbと同じ優å…
313ˆåº¦ã®ã‚¿ã‚¹ã‚¯ãŒä»–にある場合は,p_tcbの次のタス
314 * クが実行すべきタスクになる.そうでない場合は,レディキューをサーチ
315 * する必
316要がある.
317 */
318#ifdef TOPPERS_tsknrun
319
320void
321make_non_runnable(TCB *p_tcb)
322{
323 uint_t pri = p_tcb->priority;
324 QUEUE *p_queue = &(ready_queue[pri]);
325
326 queue_delete(&(p_tcb->task_queue));
327 if (queue_empty(p_queue)) {
328 primap_clear(pri);
329 if (p_schedtsk == p_tcb) {
330 assert(dspflg);
331 p_schedtsk = primap_empty() ? (TCB *) NULL : search_schedtsk();
332 }
333 }
334 else {
335 if (p_schedtsk == p_tcb) {
336 assert(dspflg);
337 p_schedtsk = (TCB *)(p_queue->p_next);
338 }
339 }
340}
341
342#endif /* TOPPERS_tsknrun */
343
344/*
345 * 休止状æ…
346‹ã¸ã®é·ç§»
347 */
348#ifdef TOPPERS_tskdmt
349
350void
351make_dormant(TCB *p_tcb)
352{
353 p_tcb->tstat = TS_DORMANT;
354 p_tcb->bpriority = p_tcb->p_tinib->ipriority;
355 p_tcb->priority = p_tcb->p_tinib->ipriority;
356 p_tcb->wupque = false;
357 p_tcb->raster = false;
358 p_tcb->enater = true;
359 LOG_TSKSTAT(p_tcb);
360}
361
362#endif /* TOPPERS_tskdmt */
363
364/*
365 * 休止状æ…
366‹ã‹ã‚‰å®Ÿè¡Œã§ãã‚‹çŠ¶æ…
367‹ã¸ã®é·ç§»
368 */
369#ifdef TOPPERS_tskact
370
371void
372make_active(TCB *p_tcb)
373{
374 activate_context(p_tcb);
375 p_tcb->tstat = TS_RUNNABLE;
376 LOG_TSKSTAT(p_tcb);
377 make_runnable(p_tcb);
378}
379
380#endif /* TOPPERS_tskact */
381
382/*
383 * タスクの優å…
384ˆåº¦ã®å¤‰æ›´
385 *
386 * タスクが実行できる状æ…
387‹ã®å ´åˆã«ã¯ï¼Œãƒ¬ãƒ‡ã‚£ã‚­ãƒ¥ãƒ¼ã®ä¸­ã§ã®ä½ç½®ã‚’変更す
388 * る.オブジェクトの待
389ちキューの中で待
390ち状æ…
391‹ã«ãªã£ã¦ã„る場合には,待
392
393 * ちキューの中での位置を変更する.
394 *
395 * 実行すべきタスクを更新するのは,(1) p_tcbが実行すべきタスクであって,
396 * その優å…
397ˆåº¦ã‚’下げた場合,(2) p_tcbが実行すべきタスクではなく,変更後
398 * の優å…
399ˆåº¦ãŒå®Ÿè¡Œã™ã¹ãã‚¿ã‚¹ã‚¯ã®å„ªå…
400ˆåº¦ã‚ˆã‚Šã‚‚高い場合である.(1)の場合に
401 * は,レディキューをサーチする必
402要がある.
403 */
404#ifdef TOPPERS_tskpri
405
406void
407change_priority(TCB *p_tcb, uint_t newpri, bool_t mtxmode)
408{
409 uint_t oldpri;
410
411 oldpri = p_tcb->priority;
412 p_tcb->priority = newpri;
413
414 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
415 /*
416 * タスクが実行できる状æ…
417‹ã®å ´åˆ
418 */
419 queue_delete(&(p_tcb->task_queue));
420 if (queue_empty(&(ready_queue[oldpri]))) {
421 primap_clear(oldpri);
422 }
423 if (mtxmode) {
424 queue_insert_next(&(ready_queue[newpri]), &(p_tcb->task_queue));
425 }
426 else {
427 queue_insert_prev(&(ready_queue[newpri]), &(p_tcb->task_queue));
428 }
429 primap_set(newpri);
430
431 if (dspflg) {
432 if (p_schedtsk == p_tcb) {
433 if (newpri >= oldpri) {
434 p_schedtsk = search_schedtsk();
435 }
436 }
437 else {
438 if (mtxmode ? newpri <= p_schedtsk->priority
439 : newpri < p_schedtsk->priority) {
440 p_schedtsk = p_tcb;
441 }
442 }
443 }
444 }
445 else {
446 if (TSTAT_WAIT_WOBJCB(p_tcb->tstat)) {
447 /*
448 * タスクが,同期・通信オブジェクトの管理ブロックのå…
449±é€šéƒ¨
450 * 分(WOBJCB)の待
451ちキューにつながれている場合
452 */
453 wobj_change_priority(((WINFO_WOBJ *)(p_tcb->p_winfo))->p_wobjcb,
454 p_tcb);
455 }
456 }
457}
458
459#endif /* TOPPERS_tskpri */
460
461/*
462 * レディキューの回転
463 *
464 * 実行すべきタスクを更新するのは,実行すべきタスクがタスクキューの末
465 * 尾に移動した場合である.
466 */
467#ifdef TOPPERS_tskrot
468
469void
470rotate_ready_queue(QUEUE *p_queue)
471{
472 QUEUE *p_entry;
473
474 if (!queue_empty(p_queue) && p_queue->p_next->p_next != p_queue) {
475 p_entry = queue_delete_next(p_queue);
476 queue_insert_prev(p_queue, p_entry);
477 if (dspflg) {
478 if (p_schedtsk == (TCB *) p_entry) {
479 p_schedtsk = (TCB *)(p_queue->p_next);
480 }
481 }
482 }
483}
484
485#endif /* TOPPERS_tskrot */
486
487/*
488 * タスクの終了処理
489 */
490#ifdef TOPPERS_tskterm
491
492void
493task_terminate(TCB *p_tcb)
494{
495 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
496 make_non_runnable(p_tcb);
497 }
498 else if (TSTAT_WAITING(p_tcb->tstat)) {
499 wait_dequeue_wobj(p_tcb);
500 wait_dequeue_tmevtb(p_tcb);
501 }
502 if (p_tcb->p_lastmtx != NULL) {
503 (*mtxhook_release_all)(p_tcb);
504 }
505 make_dormant(p_tcb);
506 if (p_tcb->actque) {
507 p_tcb->actque = false;
508 make_active(p_tcb);
509 }
510}
511
512#endif /* TOPPERS_tskterm */
Note: See TracBrowser for help on using the repository browser.