source: asp3_wo_tecs/trunk/kernel/mutex.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: 13.8 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) 2005-2015 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
8 *
9 * 上記著作権者
10は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
11 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
12 * 変・再é…
13å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
14 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16 * スコード中に含まれていること.
17 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18 * 用できる形で再é…
19å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
20å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
21 * 者
22マニュアルなど)に,上記の著作権表示,この利用条件および下記
23 * の無保証規定を掲載すること.
24 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
25 * 用できない形で再é…
26å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
27 * と.
28 * (a) 再é…
29å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
30マニュアルなど)に,上記の著
31 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
32 * (b) 再é…
33å¸ƒã®å½¢æ…
34‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
35 * 報告すること.
36 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
37 * 害からも,上記著作権者
38およびTOPPERSプロジェクトをå…
39è²¬ã™ã‚‹ã“と.
40 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
41 * 由に基づく請求からも,上記著作権者
42およびTOPPERSプロジェクトを
43 * å…
44è²¬ã™ã‚‹ã“と.
45 *
46 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
47お
48 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
49 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
50 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
51 * の責任を負わない.
52 *
53 * $Id: mutex.c 471 2015-12-30 10:03:16Z ertl-hiro $
54 */
55
56/*
57 * ミューテックス機能
58 */
59
60#include "kernel_impl.h"
61#include "check.h"
62#include "task.h"
63#include "taskhook.h"
64#include "wait.h"
65#include "mutex.h"
66
67/*
68 * トレースログマクロのデフォルト定義
69 */
70#ifndef LOG_LOC_MTX_ENTER
71#define LOG_LOC_MTX_ENTER(mtxid)
72#endif /* LOG_LOC_MTX_ENTER */
73
74#ifndef LOG_LOC_MTX_LEAVE
75#define LOG_LOC_MTX_LEAVE(ercd)
76#endif /* LOG_LOC_MTX_LEAVE */
77
78#ifndef LOG_PLOC_MTX_ENTER
79#define LOG_PLOC_MTX_ENTER(mtxid)
80#endif /* LOG_PLOC_MTX_ENTER */
81
82#ifndef LOG_PLOC_MTX_LEAVE
83#define LOG_PLOC_MTX_LEAVE(ercd)
84#endif /* LOG_PLOC_MTX_LEAVE */
85
86#ifndef LOG_TLOC_MTX_ENTER
87#define LOG_TLOC_MTX_ENTER(mtxid, tmout)
88#endif /* LOG_TLOC_MTX_ENTER */
89
90#ifndef LOG_TLOC_MTX_LEAVE
91#define LOG_TLOC_MTX_LEAVE(ercd)
92#endif /* LOG_TLOC_MTX_LEAVE */
93
94#ifndef LOG_UNL_MTX_ENTER
95#define LOG_UNL_MTX_ENTER(mtxid)
96#endif /* LOG_UNL_MTX_ENTER */
97
98#ifndef LOG_UNL_MTX_LEAVE
99#define LOG_UNL_MTX_LEAVE(ercd)
100#endif /* LOG_UNL_MTX_LEAVE */
101
102#ifndef LOG_INI_MTX_ENTER
103#define LOG_INI_MTX_ENTER(mtxid)
104#endif /* LOG_INI_MTX_ENTER */
105
106#ifndef LOG_INI_MTX_LEAVE
107#define LOG_INI_MTX_LEAVE(ercd)
108#endif /* LOG_INI_MTX_LEAVE */
109
110#ifndef LOG_REF_MTX_ENTER
111#define LOG_REF_MTX_ENTER(mtxid, pk_rmtx)
112#endif /* LOG_REF_MTX_ENTER */
113
114#ifndef LOG_REF_MTX_LEAVE
115#define LOG_REF_MTX_LEAVE(ercd, pk_rmtx)
116#endif /* LOG_REF_MTX_LEAVE */
117
118/*
119 * ミューテックスの数
120 */
121#define tnum_mtx ((uint_t)(tmax_mtxid - TMIN_MTXID + 1))
122
123/*
124 * ミューテックスIDからミューテックス管理ブロックを取り出すためのマクロ
125 */
126#define INDEX_MTX(mtxid) ((uint_t)((mtxid) - TMIN_MTXID))
127#define get_mtxcb(mtxid) (&(mtxcb_table[INDEX_MTX(mtxid)]))
128
129/*
130 * ミューテックスのプロトコルを判断するマクロ
131 */
132#define MTXPROTO_MASK 0x03U
133#define MTXPROTO(p_mtxcb) ((p_mtxcb)->p_mtxinib->mtxatr & MTXPROTO_MASK)
134#define MTX_CEILING(p_mtxcb) (MTXPROTO(p_mtxcb) == TA_CEILING)
135
136/*
137 * ミューテックス機能の初期化
138 */
139#ifdef TOPPERS_mtxini
140
141void
142initialize_mutex(void)
143{
144 uint_t i;
145 MTXCB *p_mtxcb;
146
147 mtxhook_check_ceilpri = mutex_check_ceilpri;
148 mtxhook_scan_ceilmtx = mutex_scan_ceilmtx;
149 mtxhook_release_all = mutex_release_all;
150
151 for (i = 0; i < tnum_mtx; i++) {
152 p_mtxcb = &(mtxcb_table[i]);
153 queue_initialize(&(p_mtxcb->wait_queue));
154 p_mtxcb->p_mtxinib = &(mtxinib_table[i]);
155 p_mtxcb->p_loctsk = NULL;
156 }
157}
158
159#endif /* TOPPERS_mtxini */
160
161/*
162 * 上限優å…
163ˆåº¦é•åã®ãƒã‚§ãƒƒã‚¯
164 */
165#ifdef TOPPERS_mtxchk
166
167bool_t
168mutex_check_ceilpri(TCB *p_tcb, uint_t bpriority)
169{
170 MTXCB *p_mtxcb;
171
172 /*
173 * タスクがロックしている優å…
174ˆåº¦ä¸Šé™ãƒŸãƒ¥ãƒ¼ãƒ†ãƒƒã‚¯ã‚¹ã®ä¸­ã§ï¼Œä¸Šé™å„ªå…
175ˆ
176 * 度がbpriorityよりも低いものがあれば,falseを返す.
177 */
178 p_mtxcb = p_tcb->p_lastmtx;
179 while (p_mtxcb != NULL) {
180 if (MTX_CEILING(p_mtxcb) && bpriority < p_mtxcb->p_mtxinib->ceilpri) {
181 return(false);
182 }
183 p_mtxcb = p_mtxcb->p_prevmtx;
184 }
185
186 /*
187 * タスクが優å…
188ˆåº¦ä¸Šé™ãƒŸãƒ¥ãƒ¼ãƒ†ãƒƒã‚¯ã‚¹ã®ãƒ­ãƒƒã‚¯ã‚’å¾…
189っている場合に,そ
190 * の上限優å…
191ˆåº¦ãŒbpriorityよりも低くければ,falseを返す.
192 */
193 if (TSTAT_WAIT_MTX(p_tcb->tstat)) {
194 p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb;
195 if (MTX_CEILING(p_mtxcb) && bpriority < p_mtxcb->p_mtxinib->ceilpri) {
196 return(false);
197 }
198 }
199
200 /*
201 * いずれの条件にも当てはまらなければtrueを返す.
202 */
203 return(true);
204}
205
206#endif /* TOPPERS_mtxchk */
207
208/*
209 * 優å…
210ˆåº¦ä¸Šé™ãƒŸãƒ¥ãƒ¼ãƒ†ãƒƒã‚¯ã‚¹ã‚’ロックしているかのチェック
211 */
212#ifdef TOPPERS_mtxscan
213
214bool_t
215mutex_scan_ceilmtx(TCB *p_tcb)
216{
217 MTXCB *p_mtxcb;
218
219 p_mtxcb = p_tcb->p_lastmtx;
220 while (p_mtxcb != NULL) {
221 if (MTX_CEILING(p_mtxcb)) {
222 return(true);
223 }
224 p_mtxcb = p_mtxcb->p_prevmtx;
225 }
226 return(false);
227}
228
229#endif /* TOPPERS_mtxscan */
230
231/*
232 * タスクの現在優å…
233ˆåº¦ã®è¨ˆç®—
234 *
235 * p_tcbで指定されるタスクの現在優å…
236ˆåº¦ï¼ˆã«è¨­å®šã™ã¹ãå€¤ï¼‰ã‚’計算する.
237 */
238Inline uint_t
239mutex_calc_priority(TCB *p_tcb)
240{
241 uint_t priority;
242 MTXCB *p_mtxcb;
243
244 priority = p_tcb->bpriority;
245 p_mtxcb = p_tcb->p_lastmtx;
246 while (p_mtxcb != NULL) {
247 if (MTX_CEILING(p_mtxcb) && p_mtxcb->p_mtxinib->ceilpri < priority) {
248 priority = p_mtxcb->p_mtxinib->ceilpri;
249 }
250 p_mtxcb = p_mtxcb->p_prevmtx;
251 }
252 return(priority);
253}
254
255/*
256 * ミューテックスを解放した場合の現在優å…
257ˆåº¦å¤‰æ›´å‡¦ç†
258 */
259#ifdef TOPPERS_mtxdrop
260
261void
262mutex_drop_priority(TCB *p_tcb, MTXCB *p_mtxcb)
263{
264 uint_t newpri;
265
266 if (MTX_CEILING(p_mtxcb)
267 && p_mtxcb->p_mtxinib->ceilpri == p_tcb->priority) {
268 newpri = mutex_calc_priority(p_tcb);
269 if (newpri != p_tcb->priority) {
270 change_priority(p_tcb, newpri, true);
271 }
272 }
273}
274
275#endif /* TOPPERS_mtxdrop */
276
277/*
278 * ミューテックスのロック
279 */
280#ifdef TOPPERS_mtxacq
281
282void
283mutex_acquire(TCB *p_tcb, MTXCB *p_mtxcb)
284{
285 p_mtxcb->p_loctsk = p_tcb;
286 p_mtxcb->p_prevmtx = p_tcb->p_lastmtx;
287 p_tcb->p_lastmtx = p_mtxcb;
288 if (MTX_CEILING(p_mtxcb)
289 && p_mtxcb->p_mtxinib->ceilpri < p_tcb->priority) {
290 change_priority(p_tcb, p_mtxcb->p_mtxinib->ceilpri, true);
291 }
292}
293
294#endif /* TOPPERS_mtxacq */
295
296/*
297 * ミューテックスのロック解除
298 */
299#ifdef TOPPERS_mtxrel
300
301void
302mutex_release(MTXCB *p_mtxcb)
303{
304 TCB *p_tcb;
305
306 if (queue_empty(&(p_mtxcb->wait_queue))) {
307 p_mtxcb->p_loctsk = NULL;
308 }
309 else {
310 /*
311 * ミューテックス待
312ちキューのå…
313ˆé ­ã‚¿ã‚¹ã‚¯ï¼ˆp_tcb)に,ミューテッ
314 * クスをロックさせる.
315 */
316 p_tcb = (TCB *) queue_delete_next(&(p_mtxcb->wait_queue));
317 wait_dequeue_tmevtb(p_tcb);
318 p_tcb->p_winfo->wercd = E_OK;
319
320 p_mtxcb->p_loctsk = p_tcb;
321 p_mtxcb->p_prevmtx = p_tcb->p_lastmtx;
322 p_tcb->p_lastmtx = p_mtxcb;
323 if (MTX_CEILING(p_mtxcb)) {
324 if (p_mtxcb->p_mtxinib->ceilpri < p_tcb->priority) {
325 p_tcb->priority = p_mtxcb->p_mtxinib->ceilpri;
326 }
327 }
328 make_non_wait(p_tcb);
329 }
330}
331
332#endif /* TOPPERS_mtxrel */
333
334/*
335 * タスクがロックしているすべてのミューテックスのロック解除
336 */
337#ifdef TOPPERS_mtxrela
338
339void
340mutex_release_all(TCB *p_tcb)
341{
342 MTXCB *p_mtxcb;
343
344 while ((p_mtxcb = p_tcb->p_lastmtx) != NULL) {
345 p_tcb->p_lastmtx = p_mtxcb->p_prevmtx;
346 mutex_release(p_mtxcb);
347 }
348}
349
350#endif /* TOPPERS_mtxrela */
351
352/*
353 * ミューテックスのロック
354 */
355#ifdef TOPPERS_loc_mtx
356
357ER
358loc_mtx(ID mtxid)
359{
360 MTXCB *p_mtxcb;
361 WINFO_MTX winfo_mtx;
362 ER ercd;
363
364 LOG_LOC_MTX_ENTER(mtxid);
365 CHECK_DISPATCH();
366 CHECK_ID(VALID_MTXID(mtxid));
367 p_mtxcb = get_mtxcb(mtxid);
368
369 lock_cpu_dsp();
370 if (p_runtsk->raster) {
371 ercd = E_RASTER;
372 }
373 else if (MTX_CEILING(p_mtxcb)
374 && p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
375 ercd = E_ILUSE;
376 }
377 else if (p_mtxcb->p_loctsk == NULL) {
378 mutex_acquire(p_runtsk, p_mtxcb);
379 /*
380 * 優å…
381ˆåº¦ä¸Šé™ãƒŸãƒ¥ãƒ¼ãƒ†ãƒƒã‚¯ã‚¹ã‚’ロックした場合,p_runtskの優å…
382ˆåº¦
383 * が上がる可能性があるが,ディスパッチが必
384要になることはない.
385 */
386 assert(p_runtsk == p_schedtsk);
387 ercd = E_OK;
388 }
389 else if (p_mtxcb->p_loctsk == p_runtsk) {
390 ercd = E_OBJ;
391 }
392 else {
393 p_runtsk->tstat = TS_WAITING_MTX;
394 wobj_make_wait((WOBJCB *) p_mtxcb, (WINFO_WOBJ *) &winfo_mtx);
395 dispatch();
396 ercd = winfo_mtx.winfo.wercd;
397 }
398 unlock_cpu_dsp();
399
400 error_exit:
401 LOG_LOC_MTX_LEAVE(ercd);
402 return(ercd);
403}
404
405#endif /* TOPPERS_loc_mtx */
406
407/*
408 * ミューテックスのロック(ポーリング)
409 */
410#ifdef TOPPERS_ploc_mtx
411
412ER
413ploc_mtx(ID mtxid)
414{
415 MTXCB *p_mtxcb;
416 ER ercd;
417
418 LOG_PLOC_MTX_ENTER(mtxid);
419 CHECK_TSKCTX_UNL();
420 CHECK_ID(VALID_MTXID(mtxid));
421 p_mtxcb = get_mtxcb(mtxid);
422
423 lock_cpu();
424 if (MTX_CEILING(p_mtxcb)
425 && p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
426 ercd = E_ILUSE;
427 }
428 else if (p_mtxcb->p_loctsk == NULL) {
429 mutex_acquire(p_runtsk, p_mtxcb);
430 /*
431 * 優å…
432ˆåº¦ä¸Šé™ãƒŸãƒ¥ãƒ¼ãƒ†ãƒƒã‚¯ã‚¹ã‚’ロックした場合,p_runtskの優å…
433ˆåº¦
434 * が上がる可能性があるが,ディスパッチが必
435要になることはない.
436 */
437 assert(p_runtsk == p_schedtsk);
438 ercd = E_OK;
439 }
440 else if (p_mtxcb->p_loctsk == p_runtsk) {
441 ercd = E_OBJ;
442 }
443 else {
444 ercd = E_TMOUT;
445 }
446 unlock_cpu();
447
448 error_exit:
449 LOG_PLOC_MTX_LEAVE(ercd);
450 return(ercd);
451}
452
453#endif /* TOPPERS_ploc_mtx */
454
455/*
456 * ミューテックスのロック(タイムアウトあり)
457 */
458#ifdef TOPPERS_tloc_mtx
459
460ER
461tloc_mtx(ID mtxid, TMO tmout)
462{
463 MTXCB *p_mtxcb;
464 WINFO_MTX winfo_mtx;
465 TMEVTB tmevtb;
466 ER ercd;
467
468 LOG_TLOC_MTX_ENTER(mtxid, tmout);
469 CHECK_DISPATCH();
470 CHECK_ID(VALID_MTXID(mtxid));
471 CHECK_PAR(VALID_TMOUT(tmout));
472 p_mtxcb = get_mtxcb(mtxid);
473
474 lock_cpu_dsp();
475 if (p_runtsk->raster) {
476 ercd = E_RASTER;
477 }
478 else if (MTX_CEILING(p_mtxcb)
479 && p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
480 ercd = E_ILUSE;
481 }
482 else if (p_mtxcb->p_loctsk == NULL) {
483 mutex_acquire(p_runtsk, p_mtxcb);
484 /*
485 * 優å…
486ˆåº¦ä¸Šé™ãƒŸãƒ¥ãƒ¼ãƒ†ãƒƒã‚¯ã‚¹ã‚’ロックした場合,p_runtskの優å…
487ˆåº¦
488 * が上がる可能性があるが,ディスパッチが必
489要になることはない.
490 */
491 assert(p_runtsk == p_schedtsk);
492 ercd = E_OK;
493 }
494 else if (p_mtxcb->p_loctsk == p_runtsk) {
495 ercd = E_OBJ;
496 }
497 else if (tmout == TMO_POL) {
498 ercd = E_TMOUT;
499 }
500 else {
501 p_runtsk->tstat = TS_WAITING_MTX;
502 wobj_make_wait_tmout((WOBJCB *) p_mtxcb, (WINFO_WOBJ *) &winfo_mtx,
503 &tmevtb, tmout);
504 dispatch();
505 ercd = winfo_mtx.winfo.wercd;
506 }
507 unlock_cpu_dsp();
508
509 error_exit:
510 LOG_TLOC_MTX_LEAVE(ercd);
511 return(ercd);
512}
513
514#endif /* TOPPERS_tloc_mtx */
515
516/*
517 * ミューテックスのロック解除
518 */
519#ifdef TOPPERS_unl_mtx
520
521ER
522unl_mtx(ID mtxid)
523{
524 MTXCB *p_mtxcb;
525 ER ercd;
526
527 LOG_UNL_MTX_ENTER(mtxid);
528 CHECK_TSKCTX_UNL();
529 CHECK_ID(VALID_MTXID(mtxid));
530 p_mtxcb = get_mtxcb(mtxid);
531
532 lock_cpu();
533 if (p_mtxcb != p_runtsk->p_lastmtx) {
534 ercd = E_OBJ;
535 }
536 else {
537 p_runtsk->p_lastmtx = p_mtxcb->p_prevmtx;
538 mutex_drop_priority(p_runtsk, p_mtxcb);
539 mutex_release(p_mtxcb);
540 if (p_runtsk != p_schedtsk) {
541 dispatch();
542 }
543 ercd = E_OK;
544 }
545 unlock_cpu();
546
547 error_exit:
548 LOG_UNL_MTX_LEAVE(ercd);
549 return(ercd);
550}
551
552#endif /* TOPPERS_unl_mtx */
553
554/*
555 * ミューテックスの再初期化
556 */
557#ifdef TOPPERS_ini_mtx
558
559ER
560ini_mtx(ID mtxid)
561{
562 MTXCB *p_mtxcb, **pp_prevmtx;
563 TCB *p_loctsk;
564 ER ercd;
565
566 LOG_INI_MTX_ENTER(mtxid);
567 CHECK_TSKCTX_UNL();
568 CHECK_ID(VALID_MTXID(mtxid));
569 p_mtxcb = get_mtxcb(mtxid);
570
571 lock_cpu();
572 init_wait_queue(&(p_mtxcb->wait_queue));
573 p_loctsk = p_mtxcb->p_loctsk;
574 if (p_loctsk != NULL) {
575 p_mtxcb->p_loctsk = NULL;
576 pp_prevmtx = &(p_loctsk->p_lastmtx);
577 while (*pp_prevmtx != NULL) {
578 if (*pp_prevmtx == p_mtxcb) {
579 *pp_prevmtx = p_mtxcb->p_prevmtx;
580 break;
581 }
582 pp_prevmtx = &((*pp_prevmtx)->p_prevmtx);
583 }
584 mutex_drop_priority(p_loctsk, p_mtxcb);
585 }
586 if (p_runtsk != p_schedtsk) {
587 dispatch();
588 }
589 ercd = E_OK;
590 unlock_cpu();
591
592 error_exit:
593 LOG_INI_MTX_LEAVE(ercd);
594 return(ercd);
595}
596
597#endif /* TOPPERS_ini_mtx */
598
599/*
600 * ミューテックスの状æ…
601‹å‚ç…
602§
603 */
604#ifdef TOPPERS_ref_mtx
605
606ER
607ref_mtx(ID mtxid, T_RMTX *pk_rmtx)
608{
609 MTXCB *p_mtxcb;
610 ER ercd;
611
612 LOG_REF_MTX_ENTER(mtxid, pk_rmtx);
613 CHECK_TSKCTX_UNL();
614 CHECK_ID(VALID_MTXID(mtxid));
615 p_mtxcb = get_mtxcb(mtxid);
616
617 lock_cpu();
618 pk_rmtx->htskid = (p_mtxcb->p_loctsk != NULL) ? TSKID(p_mtxcb->p_loctsk)
619 : TSK_NONE;
620 pk_rmtx->wtskid = wait_tskid(&(p_mtxcb->wait_queue));
621 ercd = E_OK;
622 unlock_cpu();
623
624 error_exit:
625 LOG_REF_MTX_LEAVE(ercd, pk_rmtx);
626 return(ercd);
627}
628
629#endif /* TOPPERS_ref_mtx */
Note: See TracBrowser for help on using the repository browser.