OSDN Git Service

マルチプロジェクト型にレポジトリを変更するために移動した
[toppersasp4lpc/asp.git] / asp / kernel / semaphore.c
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-2008 by Embedded and Real-Time Systems Laboratory
9  *              Graduate School of Information Science, Nagoya Univ., JAPAN
10  * 
11  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
12  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
31  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32  *      免責すること.
33  * 
34  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
35  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
36  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
37  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38  *  の責任を負わない.
39  * 
40  *  @(#) $Id: semaphore.c 748 2008-03-07 17:18:06Z hiro $
41  */
42
43 /*
44  *              セマフォ機能
45  */
46
47 #include "kernel_impl.h"
48 #include "check.h"
49 #include "task.h"
50 #include "wait.h"
51 #include "semaphore.h"
52
53 /*
54  *  トレースログマクロのデフォルト定義
55  */
56 #ifndef LOG_SIG_SEM_ENTER
57 #define LOG_SIG_SEM_ENTER(semid)
58 #endif /* LOG_SIG_SEM_ENTER */
59
60 #ifndef LOG_SIG_SEM_LEAVE
61 #define LOG_SIG_SEM_LEAVE(ercd)
62 #endif /* LOG_SIG_SEM_LEAVE */
63
64 #ifndef LOG_ISIG_SEM_ENTER
65 #define LOG_ISIG_SEM_ENTER(semid)
66 #endif /* LOG_ISIG_SEM_ENTER */
67
68 #ifndef LOG_ISIG_SEM_LEAVE
69 #define LOG_ISIG_SEM_LEAVE(ercd)
70 #endif /* LOG_ISIG_SEM_LEAVE */
71
72 #ifndef LOG_WAI_SEM_ENTER
73 #define LOG_WAI_SEM_ENTER(semid)
74 #endif /* LOG_WAI_SEM_ENTER */
75
76 #ifndef LOG_WAI_SEM_LEAVE
77 #define LOG_WAI_SEM_LEAVE(ercd)
78 #endif /* LOG_WAI_SEM_LEAVE */
79
80 #ifndef LOG_POL_SEM_ENTER
81 #define LOG_POL_SEM_ENTER(semid)
82 #endif /* LOG_POL_SEM_ENTER */
83
84 #ifndef LOG_POL_SEM_LEAVE
85 #define LOG_POL_SEM_LEAVE(ercd)
86 #endif /* LOG_POL_SEM_LEAVE */
87
88 #ifndef LOG_TWAI_SEM_ENTER
89 #define LOG_TWAI_SEM_ENTER(semid, tmout)
90 #endif /* LOG_TWAI_SEM_ENTER */
91
92 #ifndef LOG_TWAI_SEM_LEAVE
93 #define LOG_TWAI_SEM_LEAVE(ercd)
94 #endif /* LOG_TWAI_SEM_LEAVE */
95
96 #ifndef LOG_INI_SEM_ENTER
97 #define LOG_INI_SEM_ENTER(semid)
98 #endif /* LOG_INI_SEM_ENTER */
99
100 #ifndef LOG_INI_SEM_LEAVE
101 #define LOG_INI_SEM_LEAVE(ercd)
102 #endif /* LOG_INI_SEM_LEAVE */
103
104 #ifndef LOG_REF_SEM_ENTER
105 #define LOG_REF_SEM_ENTER(semid, pk_rsem)
106 #endif /* LOG_REF_SEM_ENTER */
107
108 #ifndef LOG_REF_SEM_LEAVE
109 #define LOG_REF_SEM_LEAVE(ercd, pk_rsem)
110 #endif /* LOG_REF_SEM_LEAVE */
111
112 /*
113  *  セマフォの数
114  */
115 #define tnum_sem        ((uint_t)(tmax_semid - TMIN_SEMID + 1))
116
117 /*
118  *  セマフォIDからセマフォ管理ブロックを取り出すためのマクロ
119  */
120 #define INDEX_SEM(semid)        ((uint_t)((semid) - TMIN_SEMID))
121 #define get_semcb(semid)        (&(semcb_table[INDEX_SEM(semid)]))
122
123 /* 
124  *  セマフォ機能の初期化
125  */
126 #ifdef TOPPERS_semini
127
128 void
129 initialize_semaphore(void)
130 {
131         uint_t  i;
132         SEMCB   *p_semcb;
133
134         for (p_semcb = semcb_table, i = 0; i < tnum_sem; p_semcb++, i++) {
135                 queue_initialize(&(p_semcb->wait_queue));
136                 p_semcb->p_seminib = &(seminib_table[i]);
137                 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
138         }
139 }
140
141 #endif /* TOPPERS_semini */
142
143 /*
144  *  セマフォ資源の返却
145  */
146 #ifdef TOPPERS_sig_sem
147
148 ER
149 sig_sem(ID semid)
150 {
151         SEMCB   *p_semcb;
152         TCB             *p_tcb;
153         ER              ercd;
154     
155         LOG_SIG_SEM_ENTER(semid);
156         CHECK_TSKCTX_UNL();
157         CHECK_SEMID(semid);
158         p_semcb = get_semcb(semid);
159
160         t_lock_cpu();
161         if (!queue_empty(&(p_semcb->wait_queue))) {
162                 p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
163                 if (wait_complete(p_tcb)) {
164                         dispatch();
165                 }
166                 ercd = E_OK;
167         }
168         else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
169                 p_semcb->semcnt += 1;
170                 ercd = E_OK;
171         }
172         else {
173                 ercd = E_QOVR;
174         }
175         t_unlock_cpu();
176
177   error_exit:
178         LOG_SIG_SEM_LEAVE(ercd);
179         return(ercd);
180 }
181
182 #endif /* TOPPERS_sig_sem */
183
184 /*
185  *  セマフォ資源の返却(非タスクコンテキスト用)
186  */
187 #ifdef TOPPERS_isig_sem
188
189 ER
190 isig_sem(ID semid)
191 {
192         SEMCB   *p_semcb;
193         TCB             *p_tcb;
194         ER              ercd;
195     
196         LOG_ISIG_SEM_ENTER(semid);
197         CHECK_INTCTX_UNL();
198         CHECK_SEMID(semid);
199         p_semcb = get_semcb(semid);
200
201         i_lock_cpu();
202         if (!queue_empty(&(p_semcb->wait_queue))) {
203                 p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
204                 if (wait_complete(p_tcb)) {
205                         reqflg = true;
206                 }
207                 ercd = E_OK;
208         }
209         else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
210                 p_semcb->semcnt += 1;
211                 ercd = E_OK;
212         }
213         else {
214                 ercd = E_QOVR;
215         }
216         i_unlock_cpu();
217
218   error_exit:
219         LOG_ISIG_SEM_LEAVE(ercd);
220         return(ercd);
221 }
222
223 #endif /* TOPPERS_isig_sem */
224
225 /*
226  *  セマフォ資源の獲得
227  */
228 #ifdef TOPPERS_wai_sem
229
230 ER
231 wai_sem(ID semid)
232 {
233         SEMCB   *p_semcb;
234         WINFO_SEM winfo_sem;
235         ER              ercd;
236
237         LOG_WAI_SEM_ENTER(semid);
238         CHECK_DISPATCH();
239         CHECK_SEMID(semid);
240         p_semcb = get_semcb(semid);
241
242         t_lock_cpu();
243         if (p_semcb->semcnt >= 1) {
244                 p_semcb->semcnt -= 1;
245                 ercd = E_OK;
246         }
247         else {
248                 p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
249                 wobj_make_wait((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem);
250                 dispatch();
251                 ercd = winfo_sem.winfo.wercd;
252         }
253         t_unlock_cpu();
254
255   error_exit:
256         LOG_WAI_SEM_LEAVE(ercd);
257         return(ercd);
258 }
259
260 #endif /* TOPPERS_wai_sem */
261
262 /*
263  *  セマフォ資源の獲得(ポーリング)
264  */
265 #ifdef TOPPERS_pol_sem
266
267 ER
268 pol_sem(ID semid)
269 {
270         SEMCB   *p_semcb;
271         ER              ercd;
272
273         LOG_POL_SEM_ENTER(semid);
274         CHECK_TSKCTX_UNL();
275         CHECK_SEMID(semid);
276         p_semcb = get_semcb(semid);
277
278         t_lock_cpu();
279         if (p_semcb->semcnt >= 1) {
280                 p_semcb->semcnt -= 1;
281                 ercd = E_OK;
282         }
283         else {
284                 ercd = E_TMOUT;
285         }
286         t_unlock_cpu();
287
288   error_exit:
289         LOG_POL_SEM_LEAVE(ercd);
290         return(ercd);
291 }
292
293 #endif /* TOPPERS_pol_sem */
294
295 /*
296  *  セマフォ資源の獲得(タイムアウトあり)
297  */
298 #ifdef TOPPERS_twai_sem
299
300 ER
301 twai_sem(ID semid, TMO tmout)
302 {
303         SEMCB   *p_semcb;
304         WINFO_SEM winfo_sem;
305         TMEVTB  tmevtb;
306         ER              ercd;
307
308         LOG_TWAI_SEM_ENTER(semid, tmout);
309         CHECK_DISPATCH();
310         CHECK_SEMID(semid);
311         CHECK_TMOUT(tmout);
312         p_semcb = get_semcb(semid);
313
314         t_lock_cpu();
315         if (p_semcb->semcnt >= 1) {
316                 p_semcb->semcnt -= 1;
317                 ercd = E_OK;
318         }
319         else if (tmout == TMO_POL) {
320                 ercd = E_TMOUT;
321         }
322         else {
323                 p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
324                 wobj_make_wait_tmout((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem,
325                                                                                                                 &tmevtb, tmout);
326                 dispatch();
327                 ercd = winfo_sem.winfo.wercd;
328         }
329         t_unlock_cpu();
330
331   error_exit:
332         LOG_TWAI_SEM_LEAVE(ercd);
333         return(ercd);
334 }
335
336 #endif /* TOPPERS_twai_sem */
337
338 /*
339  *  セマフォの再初期化
340  */
341 #ifdef TOPPERS_ini_sem
342
343 ER
344 ini_sem(ID semid)
345 {
346         SEMCB   *p_semcb;
347         bool_t  dspreq;
348         ER              ercd;
349     
350         LOG_INI_SEM_ENTER(semid);
351         CHECK_TSKCTX_UNL();
352         CHECK_SEMID(semid);
353         p_semcb = get_semcb(semid);
354
355         t_lock_cpu();
356         dspreq = init_wait_queue(&(p_semcb->wait_queue));
357         p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
358         if (dspreq) {
359                 dispatch();
360         }
361         ercd = E_OK;
362         t_unlock_cpu();
363
364   error_exit:
365         LOG_INI_SEM_LEAVE(ercd);
366         return(ercd);
367 }
368
369 #endif /* TOPPERS_ini_sem */
370
371 /*
372  *  セマフォの状態参照
373  */
374 #ifdef TOPPERS_ref_sem
375
376 ER
377 ref_sem(ID semid, T_RSEM *pk_rsem)
378 {
379         SEMCB   *p_semcb;
380         ER              ercd;
381     
382         LOG_REF_SEM_ENTER(semid, pk_rsem);
383         CHECK_TSKCTX_UNL();
384         CHECK_SEMID(semid);
385         p_semcb = get_semcb(semid);
386
387         t_lock_cpu();
388         pk_rsem->wtskid = wait_tskid(&(p_semcb->wait_queue));
389         pk_rsem->semcnt = p_semcb->semcnt;
390         ercd = E_OK;
391         t_unlock_cpu();
392
393   error_exit:
394         LOG_REF_SEM_LEAVE(ercd, pk_rsem);
395         return(ercd);
396 }
397
398 #endif /* TOPPERS_ref_sem */