3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * High Reliable system Profile Kernel
6 * Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
9 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
10 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
22 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
23 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
24 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
26 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
27 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
28 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
29 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
33 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
34 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
35 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38 * @(#) $Id: bit_mutex.c 762 2008-03-07 23:51:41Z hiro $
45 #include "kernel/kernel_impl.h"
46 #include "kernel/task.h"
47 #include "kernel/mutex.h"
50 * ミューテックスIDからミューテックス管理ブロックを取り出すためのマク
53 #define INDEX_MTX(mtxid) ((uint_t)((mtxid) - TMIN_MTXID))
54 #define get_mtxcb(mtxid) (&(mtxcb_table[INDEX_MTX(mtxid)]))
57 * ミューテックス管理ブロック中のmutex_queueへのポインタから,ミューテッ
58 * クス管理ブロックへのポインタを取り出すためのマクロ(mutex.cより)
60 #define MTXCB_QUEUE(p_queue) \
61 ((MTXCB *)(((char *) p_queue) - offsetof(MTXCB, mutex_queue)))
64 * ミューテックスのプロトコルを判断するマクロ(mutex.cより)
66 #define MTXPROTO_MASK 0x03U
67 #define MTXPROTO(p_mtxcb) ((p_mtxcb)->p_mtxinib->mtxatr & MTXPROTO_MASK)
68 #define MTX_CEILING(p_mtxcb) (MTXPROTO(p_mtxcb) == TA_CEILING)
73 #define E_SYS_LINENO ERCD(E_SYS, -(__LINE__))
76 * 管理ブロックのアドレスの正当性のチェック
78 #define VALID_TCB(p_tcb) \
79 ((((char *) p_tcb) - ((char *) tcb_table)) % sizeof(TCB) == 0 \
80 && TMIN_TSKID <= TSKID(p_tcb) && TSKID(p_tcb) <= tmax_tskid)
82 #define VALID_MTXCB(p_mtxcb) \
83 ((((char *) p_mtxcb) - ((char *) mtxcb_table)) % sizeof(MTXCB) == 0 \
84 && TMIN_MTXID <= MTXID(p_mtxcb) && MTXID(p_mtxcb) <= tmax_mtxid)
89 * p_queueにp_entryが含まれているかを調べる.含まれていればtrue,含ま
90 * れていない場合にはfalseを返す.ダブルリンクの不整合の場合にも,
94 in_queue(QUEUE *p_queue, QUEUE *p_entry)
96 QUEUE *p_current, *p_next;
98 p_current = p_queue->p_next;
99 if (p_current->p_prev != p_queue) {
100 return(false); /* ダブルリンクの不整合 */
102 while (p_current != p_queue) {
103 if (p_current == p_entry) {
104 return(true); /* p_entryが含まれていた */
110 p_next = p_current->p_next;
111 if (p_next->p_prev != p_current) {
112 return(false); /* ダブルリンクの不整合 */
123 bit_mutex_task(ID tskid)
127 QUEUE *p_queue, *p_next;
130 if (!(TMIN_TSKID <= (tskid) && (tskid) <= tmax_tskid)) {
133 p_tcb = get_tcb(tskid);
134 priority = p_tcb->bpriority;
137 * タスクがロックしているミューテックスのキューの検査
139 p_queue = p_tcb->mutex_queue.p_next;
140 if (p_queue->p_prev != &(p_tcb->mutex_queue)) {
141 return(E_SYS_LINENO);
143 while (p_queue != &(p_tcb->mutex_queue)) {
144 p_mtxcb = MTXCB_QUEUE(p_queue);
145 if (!VALID_MTXCB(p_mtxcb)) {
146 return(E_SYS_LINENO);
150 * ミューテックスをロックしているタスクのチェック
152 if (p_mtxcb->p_loctsk != p_tcb) {
153 return(E_SYS_LINENO);
159 if (MTXPROTO(p_mtxcb)) {
160 if (p_mtxcb->p_mtxinib->ceilpri < priority) {
161 priority = p_mtxcb->p_mtxinib->ceilpri;
168 p_next = p_queue->p_next;
169 if (p_next->p_prev != p_queue) {
170 return(E_SYS_LINENO);
178 if (p_tcb->priority != p_tcb->priority) {
179 return(E_SYS_LINENO);
183 * タスクが待っているミューテックスに関する検査
185 if (TSTAT_WAIT_MTX(p_tcb->tstat)) {
186 p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb;
187 if (!VALID_MTXCB(p_mtxcb)) {
188 return(E_SYS_LINENO);
190 if (!in_queue(&(p_mtxcb->wait_queue), &(p_tcb->task_queue))) {
191 return(E_SYS_LINENO);
201 bit_mutex_mutex(ID mtxid)
205 QUEUE *p_queue, *p_next;
208 if (!(TMIN_MTXID <= (mtxid) && (mtxid) <= tmax_mtxid)) {
211 p_mtxcb = get_mtxcb(mtxid);
216 if (p_mtxcb->p_mtxinib != &(mtxinib_table[INDEX_MTX(mtxid)])) {
217 return(E_SYS_LINENO);
223 p_queue = p_mtxcb->wait_queue.p_next;
224 if (p_queue->p_prev != &(p_mtxcb->wait_queue)) {
225 return(E_SYS_LINENO);
227 priority = TMIN_TPRI;
228 while (p_queue != &(p_mtxcb->wait_queue)) {
229 p_tcb = (TCB *) p_queue;
230 if (!VALID_TCB(p_tcb)) {
231 return(E_SYS_LINENO);
235 * キューがタスク優先度順になっているかの検査
237 if (MTXPROTO(p_mtxcb) != TA_NULL) {
238 if (p_tcb->priority < priority) {
239 return(E_SYS_LINENO);
242 priority = p_tcb->priority;
247 * ミューテックス待ち状態のタスクの検査は,タスク毎の検査で行っ
250 if (!TSTAT_WAIT_MTX(p_tcb->tstat)) {
251 return(E_SYS_LINENO);
257 if (MTXPROTO(p_mtxcb) == TA_CEILING) {
258 if (p_tcb->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
259 return(E_SYS_LINENO);
266 p_next = p_queue->p_next;
267 if (p_next->p_prev != p_queue) {
268 return(E_SYS_LINENO);
274 * ミューテックスをロックしているタスクの検査
276 p_tcb = p_mtxcb->p_loctsk;
281 if (!queue_empty(&(p_mtxcb->wait_queue))) {
282 return(E_SYS_LINENO);
289 * ミューテックスをロックしているタスクの検査は,タスク毎の検
290 * 査で行っているため,ここでは行わない.
292 if (!VALID_TCB(p_tcb)) {
293 return(E_SYS_LINENO);
295 if (!in_queue(&(p_tcb->mutex_queue), &(p_mtxcb->mutex_queue))) {
296 return(E_SYS_LINENO);
302 if (MTXPROTO(p_mtxcb) == TA_CEILING) {
303 if (p_tcb->bpriority < p_mtxcb->p_mtxinib->ceilpri) {
304 return(E_SYS_LINENO);
323 for (tskid = TMIN_TSKID; tskid <= tmax_tskid; tskid++) {
324 ercd = bit_mutex_task(tskid);
333 for (mtxid = TMIN_MTXID; mtxid <= tmax_mtxid; mtxid++) {
334 ercd = bit_mutex_mutex(mtxid);