source: EcnlProtoTool/trunk/asp3_dcre/kernel/task.c@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 11.3 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 270 2017-02-09 04:03:47Z coas-nagasima $
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 * 使用していないTCBのリスト
104 */
105QUEUE free_tcb;
106
107/*
108 * タスク管理モジュールの初期化
109 */
110void
111initialize_task(void)
112{
113 uint_t i, j;
114 TCB *p_tcb;
115 TINIB *p_tinib;
116
117 p_runtsk = NULL;
118 p_schedtsk = NULL;
119 enadsp = true;
120 dspflg = true;
121
122 for (i = 0; i < TNUM_TPRI; i++) {
123 queue_initialize(&(ready_queue[i]));
124 }
125 ready_primap = 0U;
126
127 for (i = 0; i < tnum_stsk; i++) {
128 j = INDEX_TSK(torder_table[i]);
129 p_tcb = &(tcb_table[j]);
130 p_tcb->p_tinib = &(tinib_table[j]);
131 p_tcb->actque = false;
132 make_dormant(p_tcb);
133 if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) {
134 make_active(p_tcb);
135 }
136 }
137 queue_initialize(&free_tcb);
138 for (j = 0; i < tnum_tsk; i++, j++) {
139 p_tcb = &(tcb_table[i]);
140 p_tinib = &(atinib_table[j]);
141 p_tinib->tskatr = TA_NOEXS;
142 p_tcb->p_tinib = ((const TINIB *) p_tinib);
143 queue_insert_prev(&free_tcb, &(p_tcb->task_queue));
144 }
145}
146
147#endif /* TOPPERS_tskini */
148
149/*
150 * ビットマップサーチ関数
151 *
152 * bitmap内
153の1のビットの内
154,最も下位(右)のものをサーチし,そのビッ
155 * ト番号を返す.ビット番号は,最下位ビットを0とする.bitmapに0を指定
156 * してはならない.この関数では,bitmapが16ビットであることを仮定し,
157 * uint16_t型としている.
158 *
159 * ビットサーチ命令を持つプロセッサでは,ビットサーチ命令を使うように
160 * 書き直した方が効率が良い場合がある.このような場合には,ターゲット
161 * 依存部でビットサーチ命令を使ったbitmap_searchを定義し,
162 * OMIT_BITMAP_SEARCHをマクロ定義すればよい.また,ビットサーチ命令の
163 * サーチ方向が逆などの理由で優å…
164ˆåº¦ã¨ãƒ“ットとの対応を変更したい場合に
165 * は,PRIMAP_BITをマクロ定義すればよい.
166 *
167 * また,ライブラリにffsがあるなら,次のように定義してライブラリ関数を
168 * 使った方が効率が良い可能性もある.
169 * #define bitmap_search(bitmap) (ffs(bitmap) - 1)
170 */
171#ifndef PRIMAP_BIT
172#define PRIMAP_BIT(pri) (1U << (pri))
173#endif /* PRIMAP_BIT */
174
175#ifndef OMIT_BITMAP_SEARCH
176
177static const unsigned char bitmap_search_table[] = { 0, 1, 0, 2, 0, 1, 0,
178 3, 0, 1, 0, 2, 0, 1, 0 };
179
180Inline uint_t
181bitmap_search(uint16_t bitmap)
182{
183 uint_t n = 0U;
184
185 assert(bitmap != 0U);
186 if ((bitmap & 0x00ffU) == 0U) {
187 bitmap >>= 8;
188 n += 8;
189 }
190 if ((bitmap & 0x0fU) == 0U) {
191 bitmap >>= 4;
192 n += 4;
193 }
194 return(n + bitmap_search_table[(bitmap & 0x0fU) - 1]);
195}
196
197#endif /* OMIT_BITMAP_SEARCH */
198
199/*
200 * 優å…
201ˆåº¦ãƒ“ットマップが空かのチェック
202 */
203Inline bool_t
204primap_empty(void)
205{
206 return(ready_primap == 0U);
207}
208
209/*
210 * 優å…
211ˆåº¦ãƒ“ットマップのサーチ
212 */
213Inline uint_t
214primap_search(void)
215{
216 return(bitmap_search(ready_primap));
217}
218
219/*
220 * 優å…
221ˆåº¦ãƒ“ットマップのセット
222 */
223Inline void
224primap_set(uint_t pri)
225{
226 ready_primap |= PRIMAP_BIT(pri);
227}
228
229/*
230 * 優å…
231ˆåº¦ãƒ“ットマップのクリア
232 */
233Inline void
234primap_clear(uint_t pri)
235{
236 ready_primap &= ~PRIMAP_BIT(pri);
237}
238
239/*
240 * 最高優å…
241ˆé †ä½ã‚¿ã‚¹ã‚¯ã®ã‚µãƒ¼ãƒ
242 */
243#ifdef TOPPERS_tsksched
244
245TCB *
246search_schedtsk(void)
247{
248 uint_t schedpri;
249
250 schedpri = primap_search();
251 return((TCB *)(ready_queue[schedpri].p_next));
252}
253
254#endif /* TOPPERS_tsksched */
255
256/*
257 * 実行できる状æ…
258‹ã¸ã®é·ç§»
259 *
260 * 実行すべきタスクを更新するのは,実行できるタスクがなかった場合と,
261 * p_tcbの優å…
262ˆåº¦ãŒå®Ÿè¡Œã™ã¹ãã‚¿ã‚¹ã‚¯ã®å„ªå…
263ˆåº¦ã‚ˆã‚Šã‚‚高い場合である.
264 */
265#ifdef TOPPERS_tskrun
266
267void
268make_runnable(TCB *p_tcb)
269{
270 uint_t pri = p_tcb->priority;
271
272 queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue));
273 primap_set(pri);
274
275 if (dspflg) {
276 if (p_schedtsk == (TCB *) NULL || pri < p_schedtsk->priority) {
277 p_schedtsk = p_tcb;
278 }
279 }
280}
281
282#endif /* TOPPERS_tskrun */
283
284/*
285 * 実行できる状æ…
286‹ã‹ã‚‰ä»–の状æ…
287‹ã¸ã®é·ç§»
288 *
289 * 実行すべきタスクを更新するのは,p_tcbが実行すべきタスクであった場合
290 * である.p_tcbと同じ優å…
291ˆåº¦ã®ã‚¿ã‚¹ã‚¯ãŒä»–にある場合は,p_tcbの次のタス
292 * クが実行すべきタスクになる.そうでない場合は,レディキューをサーチ
293 * する必
294要がある.
295 */
296#ifdef TOPPERS_tsknrun
297
298void
299make_non_runnable(TCB *p_tcb)
300{
301 uint_t pri = p_tcb->priority;
302 QUEUE *p_queue = &(ready_queue[pri]);
303
304 queue_delete(&(p_tcb->task_queue));
305 if (queue_empty(p_queue)) {
306 primap_clear(pri);
307 if (p_schedtsk == p_tcb) {
308 assert(dspflg);
309 p_schedtsk = primap_empty() ? (TCB *) NULL : search_schedtsk();
310 }
311 }
312 else {
313 if (p_schedtsk == p_tcb) {
314 assert(dspflg);
315 p_schedtsk = (TCB *)(p_queue->p_next);
316 }
317 }
318}
319
320#endif /* TOPPERS_tsknrun */
321
322/*
323 * 休止状æ…
324‹ã¸ã®é·ç§»
325 */
326#ifdef TOPPERS_tskdmt
327
328void
329make_dormant(TCB *p_tcb)
330{
331 p_tcb->tstat = TS_DORMANT;
332 p_tcb->bpriority = p_tcb->p_tinib->ipriority;
333 p_tcb->priority = p_tcb->p_tinib->ipriority;
334 p_tcb->wupque = false;
335 p_tcb->raster = false;
336 p_tcb->enater = true;
337 LOG_TSKSTAT(p_tcb);
338}
339
340#endif /* TOPPERS_tskdmt */
341
342/*
343 * 休止状æ…
344‹ã‹ã‚‰å®Ÿè¡Œã§ãã‚‹çŠ¶æ…
345‹ã¸ã®é·ç§»
346 */
347#ifdef TOPPERS_tskact
348
349void
350make_active(TCB *p_tcb)
351{
352 activate_context(p_tcb);
353 p_tcb->tstat = TS_RUNNABLE;
354 LOG_TSKSTAT(p_tcb);
355 make_runnable(p_tcb);
356}
357
358#endif /* TOPPERS_tskact */
359
360/*
361 * タスクの優å…
362ˆåº¦ã®å¤‰æ›´
363 *
364 * タスクが実行できる状æ…
365‹ã®å ´åˆã«ã¯ï¼Œãƒ¬ãƒ‡ã‚£ã‚­ãƒ¥ãƒ¼ã®ä¸­ã§ã®ä½ç½®ã‚’変更す
366 * る.オブジェクトの待
367ちキューの中で待
368ち状æ…
369‹ã«ãªã£ã¦ã„る場合には,待
370
371 * ちキューの中での位置を変更する.
372 *
373 * 実行すべきタスクを更新するのは,(1) p_tcbが実行すべきタスクであって,
374 * その優å…
375ˆåº¦ã‚’下げた場合,(2) p_tcbが実行すべきタスクではなく,変更後
376 * の優å…
377ˆåº¦ãŒå®Ÿè¡Œã™ã¹ãã‚¿ã‚¹ã‚¯ã®å„ªå…
378ˆåº¦ã‚ˆã‚Šã‚‚高い場合である.(1)の場合に
379 * は,レディキューをサーチする必
380要がある.
381 */
382#ifdef TOPPERS_tskpri
383
384void
385change_priority(TCB *p_tcb, uint_t newpri, bool_t mtxmode)
386{
387 uint_t oldpri;
388
389 oldpri = p_tcb->priority;
390 p_tcb->priority = newpri;
391
392 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
393 /*
394 * タスクが実行できる状æ…
395‹ã®å ´åˆ
396 */
397 queue_delete(&(p_tcb->task_queue));
398 if (queue_empty(&(ready_queue[oldpri]))) {
399 primap_clear(oldpri);
400 }
401 if (mtxmode) {
402 queue_insert_next(&(ready_queue[newpri]), &(p_tcb->task_queue));
403 }
404 else {
405 queue_insert_prev(&(ready_queue[newpri]), &(p_tcb->task_queue));
406 }
407 primap_set(newpri);
408
409 if (dspflg) {
410 if (p_schedtsk == p_tcb) {
411 if (newpri >= oldpri) {
412 p_schedtsk = search_schedtsk();
413 }
414 }
415 else {
416 if (mtxmode ? newpri <= p_schedtsk->priority
417 : newpri < p_schedtsk->priority) {
418 p_schedtsk = p_tcb;
419 }
420 }
421 }
422 }
423 else {
424 if (TSTAT_WAIT_WOBJCB(p_tcb->tstat)) {
425 /*
426 * タスクが,同期・通信オブジェクトの管理ブロックのå…
427±é€šéƒ¨
428 * 分(WOBJCB)の待
429ちキューにつながれている場合
430 */
431 wobj_change_priority(((WINFO_WOBJ *)(p_tcb->p_winfo))->p_wobjcb,
432 p_tcb);
433 }
434 }
435}
436
437#endif /* TOPPERS_tskpri */
438
439/*
440 * レディキューの回転
441 *
442 * 実行すべきタスクを更新するのは,実行すべきタスクがタスクキューの末
443 * 尾に移動した場合である.
444 */
445#ifdef TOPPERS_tskrot
446
447void
448rotate_ready_queue(QUEUE *p_queue)
449{
450 QUEUE *p_entry;
451
452 if (!queue_empty(p_queue) && p_queue->p_next->p_next != p_queue) {
453 p_entry = queue_delete_next(p_queue);
454 queue_insert_prev(p_queue, p_entry);
455 if (dspflg) {
456 if (p_schedtsk == (TCB *) p_entry) {
457 p_schedtsk = (TCB *)(p_queue->p_next);
458 }
459 }
460 }
461}
462
463#endif /* TOPPERS_tskrot */
464
465/*
466 * タスクの終了処理
467 */
468#ifdef TOPPERS_tskterm
469
470void
471task_terminate(TCB *p_tcb)
472{
473 if (TSTAT_RUNNABLE(p_tcb->tstat)) {
474 make_non_runnable(p_tcb);
475 }
476 else if (TSTAT_WAITING(p_tcb->tstat)) {
477 wait_dequeue_wobj(p_tcb);
478 wait_dequeue_tmevtb(p_tcb);
479 }
480 if (p_tcb->p_lastmtx != NULL) {
481 (*mtxhook_release_all)(p_tcb);
482 }
483 make_dormant(p_tcb);
484 if (p_tcb->actque) {
485 p_tcb->actque = false;
486 make_active(p_tcb);
487 }
488}
489
490#endif /* TOPPERS_tskterm */
Note: See TracBrowser for help on using the repository browser.