source: rubycfg_asp/trunk/asp_dcre/kernel/task.c@ 313

Last change on this file since 313 was 313, checked in by coas-nagasima, 7 years ago

ソースを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 12.7 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-2011 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 313 2017-07-23 04:50:32Z coas-nagasima $
56 */
57
58/*
59 * タスク管理モジュール
60 */
61
62#include "kernel_impl.h"
63#include "wait.h"
64#include "task.h"
65
66/*
67 * トレースログマクロのデフォルト定義
68 */
69#ifndef LOG_TEX_ENTER
70#define LOG_TEX_ENTER(p_tcb, texptn)
71#endif /* LOG_TEX_ENTER */
72
73#ifndef LOG_TEX_LEAVE
74#define LOG_TEX_LEAVE(p_tcb)
75#endif /* LOG_TEX_LEAVE */
76
77#ifdef TOPPERS_tskini
78
79/*
80 * 実行状æ…
81‹ã®ã‚¿ã‚¹ã‚¯
82 */
83TCB *p_runtsk;
84
85/*
86 * 最高優å…
87ˆé †ä½ã®ã‚¿ã‚¹ã‚¯
88 */
89TCB *p_schedtsk;
90
91/*
92 * タスクディスパッチ/タスク例外処理ルーチン起動要求フラグ
93 */
94bool_t reqflg;
95
96/*
97 * 割込み優å…
98ˆåº¦ãƒžã‚¹ã‚¯å…
99¨è§£é™¤çŠ¶æ…
100‹
101 */
102bool_t ipmflg;
103
104/*
105 * ディスパッチ禁止状æ…
106‹
107 */
108bool_t disdsp;
109
110/*
111 * タスクディスパッチ可能状æ…
112‹
113 */
114bool_t dspflg;
115
116/*
117 * レディキュー
118 */
119QUEUE ready_queue[TNUM_TPRI];
120
121/*
122 * レディキューサーチのためのビットマップ
123 */
124uint16_t ready_primap;
125
126/*
127 * 使用していないTCBのリスト
128 */
129QUEUE free_tcb;
130
131/*
132 * タスク管理モジュールの初期化
133 */
134void
135initialize_task(void)
136{
137 uint_t i, j;
138 TCB *p_tcb;
139 TINIB *p_tinib;
140
141 p_runtsk = NULL;
142 p_schedtsk = NULL;
143 reqflg = false;
144 ipmflg = true;
145 disdsp = false;
146 dspflg = true;
147
148 for (i = 0; i < TNUM_TPRI; i++) {
149 queue_initialize(&(ready_queue[i]));
150 }
151 ready_primap = 0U;
152
153 for (i = 0; i < tnum_stsk; i++) {
154 j = INDEX_TSK(torder_table[i]);
155 p_tcb = &(tcb_table[j]);
156 p_tcb->p_tinib = &(tinib_table[j]);
157 p_tcb->actque = false;
158 make_dormant(p_tcb);
159 if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) {
160 (void) make_active(p_tcb);
161 }
162 }
163 queue_initialize(&free_tcb);
164 for (j = 0; i < tnum_tsk; i++, j++) {
165 p_tcb = &(tcb_table[i]);
166 p_tinib = &(atinib_table[j]);
167 p_tinib->tskatr = TA_NOEXS;
168 p_tcb->p_tinib = ((const TINIB *) p_tinib);
169 queue_insert_prev(&free_tcb, &(p_tcb->task_queue));
170 }
171}
172
173#endif /* TOPPERS_tskini */
174
175/*
176 * ビットマップサーチ関数
177 *
178 * bitmap内
179の1のビットの内
180,最も下位(右)のものをサーチし,そのビッ
181 * ト番号を返す.ビット番号は,最下位ビットを0とする.bitmapに0を指定
182 * してはならない.この関数では,bitmapが16ビットであることを仮定し,
183 * uint16_t型としている.
184 *
185 * ビットサーチ命令を持つプロセッサでは,ビットサーチ命令を使うように
186 * 書き直した方が効率が良い場合がある.このような場合には,ターゲット
187 * 依存部でビットサーチ命令を使ったbitmap_searchを定義し,
188 * OMIT_BITMAP_SEARCHをマクロ定義すればよい.また,ビットサーチ命令の
189 * サーチ方向が逆などの理由で優å…
190ˆåº¦ã¨ãƒ“ットとの対応を変更したい場合に
191 * は,PRIMAP_BITをマクロ定義すればよい.
192 *
193 * また,ライブラリにffsがあるなら,次のように定義してライブラリ関数を
194 * 使った方が効率が良い可能性もある.
195 * #define bitmap_search(bitmap) (ffs(bitmap) - 1)
196 */
197#ifndef PRIMAP_BIT
198#define PRIMAP_BIT(pri) (1U << (pri))
199#endif /* PRIMAP_BIT */
200
201#ifndef OMIT_BITMAP_SEARCH
202
203static const unsigned char bitmap_search_table[] = { 0, 1, 0, 2, 0, 1, 0,
204 3, 0, 1, 0, 2, 0, 1, 0 };
205
206Inline uint_t
207bitmap_search(uint16_t bitmap)
208{
209 uint_t n = 0U;
210
211 assert(bitmap != 0U);
212 if ((bitmap & 0x00ffU) == 0U) {
213 bitmap >>= 8;
214 n += 8;
215 }
216 if ((bitmap & 0x0fU) == 0U) {
217 bitmap >>= 4;
218 n += 4;
219 }
220 return(n + bitmap_search_table[(bitmap & 0x0fU) - 1]);
221}
222
223#endif /* OMIT_BITMAP_SEARCH */
224
225/*
226 * 優å…
227ˆåº¦ãƒ“ットマップが空かのチェック
228 */
229Inline bool_t
230primap_empty(void)
231{
232 return(ready_primap == 0U);
233}
234
235/*
236 * 優å…
237ˆåº¦ãƒ“ットマップのサーチ
238 */
239Inline uint_t
240primap_search(void)
241{
242 return(bitmap_search(ready_primap));
243}
244
245/*
246 * 優å…
247ˆåº¦ãƒ“ットマップのセット
248 */
249Inline void
250primap_set(uint_t pri)
251{
252 ready_primap |= PRIMAP_BIT(pri);
253}
254
255/*
256 * 優å…
257ˆåº¦ãƒ“ットマップのクリア
258 */
259Inline void
260primap_clear(uint_t pri)
261{
262 ready_primap &= ~PRIMAP_BIT(pri);
263}
264
265/*
266 * 最高優å…
267ˆé †ä½ã‚¿ã‚¹ã‚¯ã®ã‚µãƒ¼ãƒ
268 */
269#ifdef TOPPERS_tsksched
270
271TCB *
272search_schedtsk(void)
273{
274 uint_t schedpri;
275
276 schedpri = primap_search();
277 return((TCB *)(ready_queue[schedpri].p_next));
278}
279
280#endif /* TOPPERS_tsksched */
281
282/*
283 * 実行できる状æ…
284‹ã¸ã®é·ç§»
285 *
286 * 最高優å…
287ˆé †ä½ã®ã‚¿ã‚¹ã‚¯ã‚’更新するのは,実行できるタスクがなかった場合
288 * と,p_tcbの優å…
289ˆåº¦ãŒæœ€é«˜å„ªå…
290ˆé †ä½ã®ã‚¿ã‚¹ã‚¯ã®å„ªå…
291ˆåº¦ã‚ˆã‚Šã‚‚高い場合であ
292 * る.
293 */
294#ifdef TOPPERS_tskrun
295
296bool_t
297make_runnable(TCB *p_tcb)
298{
299 uint_t pri = p_tcb->priority;
300
301 queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue));
302 primap_set(pri);
303
304 if (p_schedtsk == (TCB *) NULL || pri < p_schedtsk->priority) {
305 p_schedtsk = p_tcb;
306 return(dspflg);
307 }
308 return(false);
309}
310
311#endif /* TOPPERS_tskrun */
312
313/*
314 * 実行できる状æ…
315‹ã‹ã‚‰ä»–の状æ…
316‹ã¸ã®é·ç§»
317 *
318 * 最高優å…
319ˆé †ä½ã®ã‚¿ã‚¹ã‚¯ã‚’更新するのは,p_tcbが最高優å…
320ˆé †ä½ã®ã‚¿ã‚¹ã‚¯ã§
321 * あった場合である.p_tcbと同じ優å…
322ˆåº¦ã®ã‚¿ã‚¹ã‚¯ãŒä»–にある場合は,p_tcb
323 * の次のタスクが最高優å…
324ˆé †ä½ã«ãªã‚‹ï¼Žãã†ã§ãªã„場合は,レディキューを
325 * サーチする必
326要がある.
327 */
328#ifdef TOPPERS_tsknrun
329
330bool_t
331make_non_runnable(TCB *p_tcb)
332{
333 uint_t pri = p_tcb->priority;
334 QUEUE *p_queue = &(ready_queue[pri]);
335
336 queue_delete(&(p_tcb->task_queue));
337 if (queue_empty(p_queue)) {
338 primap_clear(pri);
339 if (p_schedtsk == p_tcb) {
340 p_schedtsk = primap_empty() ? (TCB *) NULL : search_schedtsk();
341 return(dspflg);
342 }
343 }
344 else {
345 if (p_schedtsk == p_tcb) {
346 p_schedtsk = (TCB *)(p_queue->p_next);
347 return(dspflg);
348 }
349 }
350 return(false);
351}
352
353#endif /* TOPPERS_tsknrun */
354
355/*
356 * 休止状æ…
357‹ã¸ã®é·ç§»
358 */
359#ifdef TOPPERS_tskdmt
360
361void
362make_dormant(TCB *p_tcb)
363{
364 p_tcb->tstat = TS_DORMANT;
365 p_tcb->priority = p_tcb->p_tinib->ipriority;
366 p_tcb->wupque = false;
367 p_tcb->enatex = false;
368 p_tcb->texptn = 0U;
369 LOG_TSKSTAT(p_tcb);
370}
371
372#endif /* TOPPERS_tskdmt */
373
374/*
375 * 休止状æ…
376‹ã‹ã‚‰å®Ÿè¡Œã§ãã‚‹çŠ¶æ…
377‹ã¸ã®é·ç§»
378 */
379#ifdef TOPPERS_tskact
380
381bool_t
382make_active(TCB *p_tcb)
383{
384 activate_context(p_tcb);
385 p_tcb->tstat = TS_RUNNABLE;
386 LOG_TSKSTAT(p_tcb);
387 return(make_runnable(p_tcb));
388}
389
390#endif /* TOPPERS_tskact */
391
392/*
393 * タスクの優å…
394ˆåº¦ã®å¤‰æ›´
395 *
396 * タスクが実行できる状æ…
397‹ã®å ´åˆã«ã¯ï¼Œãƒ¬ãƒ‡ã‚£ã‚­ãƒ¥ãƒ¼ã®ä¸­ã§ã®ä½ç½®ã‚’変更す
398 * る.オブジェクトの待
399ちキューの中で待
400ち状æ…
401‹ã«ãªã£ã¦ã„る場合には,待
402
403 * ちキューの中での位置を変更する.
404 *
405 * 最高優å…
406ˆé †ä½ã®ã‚¿ã‚¹ã‚¯ã‚’更新するのは,(1) p_tcbが最高優å…
407ˆé †ä½ã®ã‚¿ã‚¹
408 * クであって,その優å…
409ˆåº¦ã‚’下げた場合,(2) p_tcbが最高優å…
410ˆé †ä½ã®ã‚¿ã‚¹
411 * クではなく,変更後の優å…
412ˆåº¦ãŒæœ€é«˜å„ªå…
413ˆé †ä½ã®ã‚¿ã‚¹ã‚¯ã®å„ªå…
414ˆåº¦ã‚ˆã‚Šã‚‚高い
415 * 場合である.(1)の場合には,レディキューをサーチする必
416要がある.
417 */
418#ifdef TOPPERS_tskpri
419
420bool_t
421change_priority(TCB *p_tcb, uint_t newpri)
422{
423 uint_t oldpri;
424
425 oldpri = p_tcb->priority;
426 p_tcb->priority = newpri;
427
428 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
429 /*
430 * タスクが実行できる状æ…
431‹ã®å ´åˆ
432 */
433 queue_delete(&(p_tcb->task_queue));
434 if (queue_empty(&(ready_queue[oldpri]))) {
435 primap_clear(oldpri);
436 }
437 queue_insert_prev(&(ready_queue[newpri]), &(p_tcb->task_queue));
438 primap_set(newpri);
439
440 if (p_schedtsk == p_tcb) {
441 if (newpri >= oldpri) {
442 p_schedtsk = search_schedtsk();
443 return(p_schedtsk != p_tcb && dspflg);
444 }
445 }
446 else {
447 if (newpri < p_schedtsk->priority) {
448 p_schedtsk = p_tcb;
449 return(dspflg);
450 }
451 }
452 }
453 else {
454 if (TSTAT_WAIT_WOBJCB(p_tcb->tstat)) {
455 /*
456 * タスクが,同期・通信オブジェクトの管理ブロックのå…
457±é€šéƒ¨
458 * 分(WOBJCB)の待
459ちキューにつながれている場合
460 */
461 wobj_change_priority(((WINFO_WOBJ *)(p_tcb->p_winfo))->p_wobjcb,
462 p_tcb);
463 }
464 }
465 return(false);
466}
467
468#endif /* TOPPERS_tskpri */
469
470/*
471 * レディキューの回転
472 *
473 * 最高優å…
474ˆé †ä½ã®ã‚¿ã‚¹ã‚¯ã‚’更新するのは,最高優å…
475ˆé †ä½ã®ã‚¿ã‚¹ã‚¯ãŒã‚¿ã‚¹ã‚¯ã‚­
476 * ューの末尾に移動した場合である.
477 */
478#ifdef TOPPERS_tskrot
479
480bool_t
481rotate_ready_queue(uint_t pri)
482{
483 QUEUE *p_queue = &(ready_queue[pri]);
484 QUEUE *p_entry;
485
486 if (!queue_empty(p_queue) && p_queue->p_next->p_next != p_queue) {
487 p_entry = queue_delete_next(p_queue);
488 queue_insert_prev(p_queue, p_entry);
489 if (p_schedtsk == (TCB *) p_entry) {
490 p_schedtsk = (TCB *)(p_queue->p_next);
491 return(dspflg);
492 }
493 }
494 return(false);
495}
496
497#endif /* TOPPERS_tskrot */
498
499/*
500 * タスク例外処理ルーチンの呼出し
501 *
502 * ASPカーネルでは,タスク例外処理ルーチン内
503でCPUロック状æ…
504‹ã«é·ç§»ã—,
505 * å…
506ƒã®çŠ¶æ…
507‹ã«æˆ»ã•ãšã«ãƒªã‚¿ãƒ¼ãƒ³ã—た場合,カーネルがå…
508ƒã®çŠ¶æ…
509‹ã«æˆ»ã™ï¼Ž
510 */
511#ifdef TOPPERS_tsktex
512
513void
514call_texrtn(void)
515{
516 TEXPTN texptn;
517 bool_t saved_disdsp;
518
519 saved_disdsp = disdsp;
520 p_runtsk->enatex = false;
521 do {
522 texptn = p_runtsk->texptn;
523 p_runtsk->texptn = 0U;
524
525 t_unlock_cpu();
526 LOG_TEX_ENTER(p_runtsk, texptn);
527 (*((TEXRTN)(p_runtsk->p_tinib->texrtn)))(texptn,
528 p_runtsk->p_tinib->exinf);
529 LOG_TEX_LEAVE(p_runtsk);
530 if (!t_sense_lock()) {
531 t_lock_cpu();
532 }
533 if (!ipmflg) {
534 t_set_ipm(TIPM_ENAALL);
535 ipmflg = true;
536 }
537 disdsp = saved_disdsp;
538 dspflg = !disdsp;
539 p_runtsk->enatex = false;
540 if (p_runtsk != p_schedtsk && dspflg) {
541 /*
542 * ここでdispatchを呼び出す処理は,相互再帰呼出しになって
543 * いるが,dispatchを呼ぶ前にp_runtsk->enatexをfalseにして
544 * おけば支障がない.その理由については,「TOPPERS/ASP カー
545 * ネル 設計メモ」を参ç…
546§ã®ã“と.
547 */
548 dispatch();
549 }
550 } while (p_runtsk->texptn != 0U);
551 p_runtsk->enatex = true;
552}
553
554/*
555 * タスク例外処理ルーチンの起動
556 */
557#ifndef OMIT_CALLTEX
558
559void
560calltex(void)
561{
562 if (p_runtsk->enatex && p_runtsk->texptn != 0U && ipmflg) {
563 call_texrtn();
564 }
565}
566
567#endif /* OMIT_CALLTEX */
568#endif /* TOPPERS_tsktex */
Note: See TracBrowser for help on using the repository browser.