source: asp3_wo_tecs/trunk/extension/subprio/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.9 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 258 2014-10-04 19:37:38Z 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 */
100uint16_t ready_primap;
101
102/*
103 * タスク管理モジュールの初期化
104 */
105void
106initialize_task(void)
107{
108 uint_t i, j;
109 TCB *p_tcb;
110
111 p_runtsk = NULL;
112 p_schedtsk = NULL;
113 enadsp = true;
114 dspflg = true;
115
116 for (i = 0; i < TNUM_TPRI; i++) {
117 queue_initialize(&(ready_queue[i]));
118 }
119 ready_primap = 0U;
120
121 for (i = 0; i < tnum_tsk; i++) {
122 j = INDEX_TSK(torder_table[i]);
123 p_tcb = &(tcb_table[j]);
124 p_tcb->p_tinib = &(tinib_table[j]);
125 p_tcb->actque = false;
126 p_tcb->subpri = UINT_MAX;
127 make_dormant(p_tcb);
128 p_tcb->p_lastmtx = NULL;
129 if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) {
130 make_active(p_tcb);
131 }
132 }
133}
134
135#endif /* TOPPERS_tskini */
136
137/*
138 * ビットマップサーチ関数
139 *
140 * bitmap内
141の1のビットの内
142,最も下位(右)のものをサーチし,そのビッ
143 * ト番号を返す.ビット番号は,最下位ビットを0とする.bitmapに0を指定
144 * してはならない.この関数では,bitmapが16ビットであることを仮定し,
145 * uint16_t型としている.
146 *
147 * ビットサーチ命令を持つプロセッサでは,ビットサーチ命令を使うように
148 * 書き直した方が効率が良い場合がある.このような場合には,ターゲット
149 * 依存部でビットサーチ命令を使ったbitmap_searchを定義し,
150 * OMIT_BITMAP_SEARCHをマクロ定義すればよい.また,ビットサーチ命令の
151 * サーチ方向が逆などの理由で優å…
152ˆåº¦ã¨ãƒ“ットとの対応を変更したい場合に
153 * は,PRIMAP_BITをマクロ定義すればよい.
154 *
155 * また,ライブラリにffsがあるなら,次のように定義してライブラリ関数を
156 * 使った方が効率が良い可能性もある.
157 * #define bitmap_search(bitmap) (ffs(bitmap) - 1)
158 */
159#ifndef OMIT_BITMAP_SEARCH
160
161static const unsigned char bitmap_search_table[] = { 0, 1, 0, 2, 0, 1, 0,
162 3, 0, 1, 0, 2, 0, 1, 0 };
163
164Inline uint_t
165bitmap_search(uint16_t bitmap)
166{
167 uint_t n = 0U;
168
169 assert(bitmap != 0U);
170 if ((bitmap & 0x00ffU) == 0U) {
171 bitmap >>= 8;
172 n += 8;
173 }
174 if ((bitmap & 0x0fU) == 0U) {
175 bitmap >>= 4;
176 n += 4;
177 }
178 return(n + bitmap_search_table[(bitmap & 0x0fU) - 1]);
179}
180
181#endif /* OMIT_BITMAP_SEARCH */
182
183/*
184 * 優å…
185ˆåº¦ãƒ“ットマップが空かのチェック
186 */
187Inline bool_t
188primap_empty(void)
189{
190 return(ready_primap == 0U);
191}
192
193/*
194 * 優å…
195ˆåº¦ãƒ“ットマップのサーチ
196 */
197Inline uint_t
198primap_search(void)
199{
200 return(bitmap_search(ready_primap));
201}
202
203/*
204 * 優å…
205ˆåº¦ãƒ“ットマップのセット
206 */
207Inline void
208primap_set(uint_t pri)
209{
210 ready_primap |= PRIMAP_BIT(pri);
211}
212
213/*
214 * 優å…
215ˆåº¦ãƒ“ットマップのクリア
216 */
217Inline void
218primap_clear(uint_t pri)
219{
220 ready_primap &= ~PRIMAP_BIT(pri);
221}
222
223/*
224 * 最高優å…
225ˆé †ä½ã‚¿ã‚¹ã‚¯ã®ã‚µãƒ¼ãƒ
226 */
227#ifdef TOPPERS_tsksched
228
229TCB *
230search_schedtsk(void)
231{
232 uint_t schedpri;
233
234 schedpri = primap_search();
235 return((TCB *)(ready_queue[schedpri].p_next));
236}
237
238#endif /* TOPPERS_tsksched */
239
240/*
241 * タスクのサブ優å…
242ˆåº¦é †ã®ã‚­ãƒ¥ãƒ¼ã¸ã®æŒ¿å…
243¥
244 *
245 * p_tcbで指定されるタスクを,サブ優å…
246ˆåº¦é †ã§ï¼Œã‚­ãƒ¥ãƒ¼p_queueに挿å…
247¥ã™ã‚‹ï¼Ž
248 * キューの中に同じサブ優å…
249ˆåº¦ã®ã‚¿ã‚¹ã‚¯ãŒã‚る場合には,mtxmodeがtrueの時
250 * はそれらのå…
251ˆé ­ã«ï¼Œfalseの時はそれらの最後に挿å…
252¥ã™ã‚‹ï¼Ž
253 */
254Inline void
255queue_insert_subprio(QUEUE *p_queue, TCB *p_tcb, bool_t mtxmode)
256{
257 QUEUE *p_entry;
258 uint_t subpri = p_tcb->subpri;
259
260 for (p_entry = p_queue->p_next; p_entry != p_queue;
261 p_entry = p_entry->p_next) {
262 if (mtxmode ? subpri <= ((TCB *) p_entry)->subpri
263 : subpri < ((TCB *) p_entry)->subpri) {
264 break;
265 }
266 }
267 queue_insert_prev(p_entry, &(p_tcb->task_queue));
268}
269
270/*
271 * 実行できる状æ…
272‹ã¸ã®é·ç§»
273 *
274 * 実行すべきタスクを更新するのは,実行できるタスクがなかった場合と,
275 * p_tcbの優å…
276ˆåº¦ãŒå®Ÿè¡Œã™ã¹ãã‚¿ã‚¹ã‚¯ã®å„ªå…
277ˆåº¦ã‚ˆã‚Šã‚‚高い場合である.
278 */
279#ifdef TOPPERS_tskrun
280
281void
282make_runnable(TCB *p_tcb)
283{
284 uint_t pri = p_tcb->priority;
285
286 if ((subprio_primap & PRIMAP_BIT(pri)) != 0U) {
287 queue_insert_subprio(&(ready_queue[pri]), p_tcb, false);
288 }
289 else {
290 queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue));
291 }
292 primap_set(pri);
293
294 if (dspflg) {
295 if (p_schedtsk == (TCB *) NULL || pri < p_schedtsk->priority) {
296 p_schedtsk = p_tcb;
297 }
298 }
299}
300
301#endif /* TOPPERS_tskrun */
302
303/*
304 * 実行できる状æ…
305‹ã‹ã‚‰ä»–の状æ…
306‹ã¸ã®é·ç§»
307 *
308 * 実行すべきタスクを更新するのは,p_tcbが実行すべきタスクであった場合
309 * である.p_tcbと同じ優å…
310ˆåº¦ã®ã‚¿ã‚¹ã‚¯ãŒä»–にある場合は,p_tcbの次のタス
311 * クが実行すべきタスクになる.そうでない場合は,レディキューをサーチ
312 * する必
313要がある.
314 */
315#ifdef TOPPERS_tsknrun
316
317void
318make_non_runnable(TCB *p_tcb)
319{
320 uint_t pri = p_tcb->priority;
321 QUEUE *p_queue = &(ready_queue[pri]);
322
323 queue_delete(&(p_tcb->task_queue));
324 if (queue_empty(p_queue)) {
325 primap_clear(pri);
326 if (p_schedtsk == p_tcb) {
327 assert(dspflg);
328 p_schedtsk = primap_empty() ? (TCB *) NULL : search_schedtsk();
329 }
330 }
331 else {
332 if (p_schedtsk == p_tcb) {
333 assert(dspflg);
334 p_schedtsk = (TCB *)(p_queue->p_next);
335 }
336 }
337}
338
339#endif /* TOPPERS_tsknrun */
340
341/*
342 * 休止状æ…
343‹ã¸ã®é·ç§»
344 */
345#ifdef TOPPERS_tskdmt
346
347void
348make_dormant(TCB *p_tcb)
349{
350 p_tcb->tstat = TS_DORMANT;
351 p_tcb->bpriority = p_tcb->p_tinib->ipriority;
352 p_tcb->priority = p_tcb->p_tinib->ipriority;
353 p_tcb->wupque = false;
354 p_tcb->raster = false;
355 p_tcb->enater = true;
356 LOG_TSKSTAT(p_tcb);
357}
358
359#endif /* TOPPERS_tskdmt */
360
361/*
362 * 休止状æ…
363‹ã‹ã‚‰å®Ÿè¡Œã§ãã‚‹çŠ¶æ…
364‹ã¸ã®é·ç§»
365 */
366#ifdef TOPPERS_tskact
367
368void
369make_active(TCB *p_tcb)
370{
371 activate_context(p_tcb);
372 p_tcb->tstat = TS_RUNNABLE;
373 LOG_TSKSTAT(p_tcb);
374 make_runnable(p_tcb);
375}
376
377#endif /* TOPPERS_tskact */
378
379/*
380 * タスクの優å…
381ˆåº¦ã®å¤‰æ›´
382 *
383 * タスクが実行できる状æ…
384‹ã®å ´åˆã«ã¯ï¼Œãƒ¬ãƒ‡ã‚£ã‚­ãƒ¥ãƒ¼ã®ä¸­ã§ã®ä½ç½®ã‚’変更す
385 * る.オブジェクトの待
386ちキューの中で待
387ち状æ…
388‹ã«ãªã£ã¦ã„る場合には,待
389
390 * ちキューの中での位置を変更する.
391 *
392 * 実行すべきタスクを更新するのは,(1) p_tcbが実行すべきタスクであって,
393 * その優å…
394ˆåº¦ã‚’下げた場合,(2) p_tcbが実行すべきタスクではなく,変更後
395 * の優å…
396ˆåº¦ãŒå®Ÿè¡Œã™ã¹ãã‚¿ã‚¹ã‚¯ã®å„ªå…
397ˆåº¦ã‚ˆã‚Šã‚‚高い場合である.(1)の場合に
398 * は,レディキューをサーチする必
399要がある.
400 */
401#ifdef TOPPERS_tskpri
402
403void
404change_priority(TCB *p_tcb, uint_t newpri, bool_t mtxmode)
405{
406 uint_t oldpri;
407
408 oldpri = p_tcb->priority;
409 p_tcb->priority = newpri;
410
411 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
412 /*
413 * タスクが実行できる状æ…
414‹ã®å ´åˆ
415 */
416 queue_delete(&(p_tcb->task_queue));
417 if (queue_empty(&(ready_queue[oldpri]))) {
418 primap_clear(oldpri);
419 }
420 if ((subprio_primap & PRIMAP_BIT(newpri)) != 0U) {
421 queue_insert_subprio(&(ready_queue[newpri]), p_tcb, mtxmode);
422 }
423 else 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ˆåº¦ãŒã‚µãƒ–優å…
468ˆåº¦ã‚’使用する
469 * と設定されている場合には,レディキューの中での位置を変更する.
470 *
471 * サブ優å…
472ˆåº¦ã‚’変更したタスクと,実行すべきタスクの優å…
473ˆåº¦ãŒåŒã˜å ´åˆã«ï¼Œ
474 * その優å…
475ˆåº¦ã®ä¸­ã§å„ªå…
476ˆé †ä½ãŒæœ€ã‚‚高いタスクを,実行すべきタスクとする.
477 */
478#ifdef TOPPERS_tskspr
479
480void
481change_subprio(TCB *p_tcb, uint_t subpri)
482{
483 p_tcb->subpri = subpri; /*ï¼»NGKI3672ï¼½*/
484 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
485 if ((subprio_primap & PRIMAP_BIT(p_tcb->priority)) != 0U) {
486 queue_delete(&(p_tcb->task_queue)); /*ï¼»NGKI3673ï¼½*/
487 queue_insert_subprio(&(ready_queue[p_tcb->priority]), p_tcb, false);
488 }
489 if (dspflg) {
490 if (p_schedtsk->priority == p_tcb->priority) {
491 p_schedtsk = (TCB *)(ready_queue[p_tcb->priority].p_next);
492 }
493 }
494 }
495}
496
497#endif /* TOPPERS_tskspr */
498
499/*
500 * レディキューの回転
501 *
502 * 実行すべきタスクを更新するのは,実行すべきタスクがタスクキューの末
503 * 尾に移動した場合である.
504 */
505#ifdef TOPPERS_tskrot
506
507void
508rotate_ready_queue(QUEUE *p_queue)
509{
510 QUEUE *p_entry;
511
512 if (!queue_empty(p_queue) && p_queue->p_next->p_next != p_queue) {
513 p_entry = queue_delete_next(p_queue);
514 queue_insert_prev(p_queue, p_entry);
515 if (dspflg) {
516 if (p_schedtsk == (TCB *) p_entry) {
517 p_schedtsk = (TCB *)(p_queue->p_next);
518 }
519 }
520 }
521}
522
523#endif /* TOPPERS_tskrot */
524
525/*
526 * タスクの終了処理
527 */
528#ifdef TOPPERS_tskterm
529
530void
531task_terminate(TCB *p_tcb)
532{
533 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
534 make_non_runnable(p_tcb);
535 }
536 else if (TSTAT_WAITING(p_tcb->tstat)) {
537 wait_dequeue_wobj(p_tcb);
538 wait_dequeue_tmevtb(p_tcb);
539 }
540 if (p_tcb->p_lastmtx != NULL) {
541 (*mtxhook_release_all)(p_tcb);
542 }
543 make_dormant(p_tcb);
544 if (p_tcb->actque) {
545 p_tcb->actque = false;
546 make_active(p_tcb);
547 }
548}
549
550#endif /* TOPPERS_tskterm */
Note: See TracBrowser for help on using the repository browser.