OSDN Git Service

カーネルのターゲット非依存部1.7.0およびCFGをマージ
[toppersasp4lpc/asp.git] / asp / extension / dcre / 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-2010 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 1966 2010-11-20 07:23:56Z ertl-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_ACRE_SEM_ENTER
57 #define LOG_ACRE_SEM_ENTER(pk_csem)
58 #endif /* LOG_ACRE_SEM_ENTER */
59
60 #ifndef LOG_ACRE_SEM_LEAVE
61 #define LOG_ACRE_SEM_LEAVE(ercd)
62 #endif /* LOG_ACRE_SEM_LEAVE */
63
64 #ifndef LOG_DEL_SEM_ENTER
65 #define LOG_DEL_SEM_ENTER(semid)
66 #endif /* LOG_DEL_SEM_ENTER */
67
68 #ifndef LOG_DEL_SEM_LEAVE
69 #define LOG_DEL_SEM_LEAVE(ercd)
70 #endif /* LOG_DEL_SEM_LEAVE */
71
72 #ifndef LOG_SIG_SEM_ENTER
73 #define LOG_SIG_SEM_ENTER(semid)
74 #endif /* LOG_SIG_SEM_ENTER */
75
76 #ifndef LOG_SIG_SEM_LEAVE
77 #define LOG_SIG_SEM_LEAVE(ercd)
78 #endif /* LOG_SIG_SEM_LEAVE */
79
80 #ifndef LOG_ISIG_SEM_ENTER
81 #define LOG_ISIG_SEM_ENTER(semid)
82 #endif /* LOG_ISIG_SEM_ENTER */
83
84 #ifndef LOG_ISIG_SEM_LEAVE
85 #define LOG_ISIG_SEM_LEAVE(ercd)
86 #endif /* LOG_ISIG_SEM_LEAVE */
87
88 #ifndef LOG_WAI_SEM_ENTER
89 #define LOG_WAI_SEM_ENTER(semid)
90 #endif /* LOG_WAI_SEM_ENTER */
91
92 #ifndef LOG_WAI_SEM_LEAVE
93 #define LOG_WAI_SEM_LEAVE(ercd)
94 #endif /* LOG_WAI_SEM_LEAVE */
95
96 #ifndef LOG_POL_SEM_ENTER
97 #define LOG_POL_SEM_ENTER(semid)
98 #endif /* LOG_POL_SEM_ENTER */
99
100 #ifndef LOG_POL_SEM_LEAVE
101 #define LOG_POL_SEM_LEAVE(ercd)
102 #endif /* LOG_POL_SEM_LEAVE */
103
104 #ifndef LOG_TWAI_SEM_ENTER
105 #define LOG_TWAI_SEM_ENTER(semid, tmout)
106 #endif /* LOG_TWAI_SEM_ENTER */
107
108 #ifndef LOG_TWAI_SEM_LEAVE
109 #define LOG_TWAI_SEM_LEAVE(ercd)
110 #endif /* LOG_TWAI_SEM_LEAVE */
111
112 #ifndef LOG_INI_SEM_ENTER
113 #define LOG_INI_SEM_ENTER(semid)
114 #endif /* LOG_INI_SEM_ENTER */
115
116 #ifndef LOG_INI_SEM_LEAVE
117 #define LOG_INI_SEM_LEAVE(ercd)
118 #endif /* LOG_INI_SEM_LEAVE */
119
120 #ifndef LOG_REF_SEM_ENTER
121 #define LOG_REF_SEM_ENTER(semid, pk_rsem)
122 #endif /* LOG_REF_SEM_ENTER */
123
124 #ifndef LOG_REF_SEM_LEAVE
125 #define LOG_REF_SEM_LEAVE(ercd, pk_rsem)
126 #endif /* LOG_REF_SEM_LEAVE */
127
128 /*
129  *  セマフォの数
130  */
131 #define tnum_sem        ((uint_t)(tmax_semid - TMIN_SEMID + 1))
132 #define tnum_ssem       ((uint_t)(tmax_ssemid - TMIN_SEMID + 1))
133
134 /*
135  *  セマフォIDからセマフォ管理ブロックを取り出すためのマクロ
136  */
137 #define INDEX_SEM(semid)        ((uint_t)((semid) - TMIN_SEMID))
138 #define get_semcb(semid)        (&(semcb_table[INDEX_SEM(semid)]))
139
140 #ifdef TOPPERS_semini
141
142 /*
143  *  使用していないセマフォ管理ブロックのリスト
144  */
145 QUEUE   free_semcb;
146
147 /* 
148  *  セマフォ機能の初期化
149  */
150 void
151 initialize_semaphore(void)
152 {
153         uint_t  i, j;
154         SEMCB   *p_semcb;
155         SEMINIB *p_seminib;
156
157         for (p_semcb = semcb_table, i = 0; i < tnum_ssem; p_semcb++, i++) {
158                 queue_initialize(&(p_semcb->wait_queue));
159                 p_semcb->p_seminib = &(seminib_table[i]);
160                 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
161         }
162         queue_initialize(&free_semcb);
163         for (j = 0; i < tnum_sem; p_semcb++, i++, j++) {
164                 p_seminib = &(aseminib_table[j]);
165                 p_seminib->sematr = TA_NOEXS;
166                 p_semcb->p_seminib = ((const SEMINIB *) p_seminib);
167                 queue_insert_prev(&free_semcb, &(p_semcb->wait_queue));
168         }
169 }
170
171 #endif /* TOPPERS_semini */
172
173 /*
174  *  セマフォの生成
175  */
176 #ifdef TOPPERS_acre_sem
177
178 ER_UINT
179 acre_sem(const T_CSEM *pk_csem)
180 {
181         SEMCB   *p_semcb;
182         SEMINIB *p_seminib;
183         ER              ercd;
184
185         LOG_ACRE_SEM_ENTER(pk_csem);
186         CHECK_TSKCTX_UNL();
187         CHECK_RSATR(pk_csem->sematr, TA_TPRI);
188         CHECK_PAR(0 <= pk_csem->isemcnt && pk_csem->isemcnt <= pk_csem->maxsem);
189         CHECK_PAR(1 <= pk_csem->maxsem && pk_csem->maxsem <= TMAX_MAXSEM);
190
191         t_lock_cpu();
192         if (queue_empty(&free_semcb)) {
193                 ercd = E_NOID;
194         }
195         else {
196                 p_semcb = ((SEMCB *) queue_delete_next(&free_semcb));
197                 p_seminib = (SEMINIB *)(p_semcb->p_seminib);
198                 p_seminib->sematr = pk_csem->sematr;
199                 p_seminib->isemcnt = pk_csem->isemcnt;
200                 p_seminib->maxsem = pk_csem->maxsem;
201
202                 queue_initialize(&(p_semcb->wait_queue));
203                 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
204                 ercd = SEMID(p_semcb);
205         }
206         t_unlock_cpu();
207
208   error_exit:
209         LOG_ACRE_SEM_LEAVE(ercd);
210         return(ercd);
211 }
212
213 #endif /* TOPPERS_acre_sem */
214
215 /*
216  *  セマフォの削除
217  */
218 #ifdef TOPPERS_del_sem
219
220 ER
221 del_sem(ID semid)
222 {
223         SEMCB   *p_semcb;
224         SEMINIB *p_seminib;
225         bool_t  dspreq;
226         ER              ercd;
227
228         LOG_DEL_SEM_ENTER(semid);
229         CHECK_TSKCTX_UNL();
230         CHECK_SEMID(semid);
231         p_semcb = get_semcb(semid);
232
233         t_lock_cpu();
234         if (p_semcb->p_seminib->sematr == TA_NOEXS) {
235                 ercd = E_NOEXS;
236         }
237         else if (SEMID(p_semcb) > tmax_ssemid) {
238                 dspreq = init_wait_queue(&(p_semcb->wait_queue));
239                 p_seminib = (SEMINIB *)(p_semcb->p_seminib);
240                 p_seminib->sematr = TA_NOEXS;
241                 queue_insert_prev(&free_semcb, &(p_semcb->wait_queue));
242                 if (dspreq) {
243                         dispatch();
244                 }
245                 ercd = E_OK;
246         }
247         else {
248                 ercd = E_OBJ;
249         }
250         t_unlock_cpu();
251
252   error_exit:
253         LOG_DEL_SEM_LEAVE(ercd);
254         return(ercd);
255 }
256
257 #endif /* TOPPERS_del_sem */
258
259 /*
260  *  セマフォ資源の返却
261  */
262 #ifdef TOPPERS_sig_sem
263
264 ER
265 sig_sem(ID semid)
266 {
267         SEMCB   *p_semcb;
268         TCB             *p_tcb;
269         ER              ercd;
270     
271         LOG_SIG_SEM_ENTER(semid);
272         CHECK_TSKCTX_UNL();
273         CHECK_SEMID(semid);
274         p_semcb = get_semcb(semid);
275
276         t_lock_cpu();
277         if (p_semcb->p_seminib->sematr == TA_NOEXS) {
278                 ercd = E_NOEXS;
279         }
280         else if (!queue_empty(&(p_semcb->wait_queue))) {
281                 p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
282                 if (wait_complete(p_tcb)) {
283                         dispatch();
284                 }
285                 ercd = E_OK;
286         }
287         else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
288                 p_semcb->semcnt += 1;
289                 ercd = E_OK;
290         }
291         else {
292                 ercd = E_QOVR;
293         }
294         t_unlock_cpu();
295
296   error_exit:
297         LOG_SIG_SEM_LEAVE(ercd);
298         return(ercd);
299 }
300
301 #endif /* TOPPERS_sig_sem */
302
303 /*
304  *  セマフォ資源の返却(非タスクコンテキスト用)
305  */
306 #ifdef TOPPERS_isig_sem
307
308 ER
309 isig_sem(ID semid)
310 {
311         SEMCB   *p_semcb;
312         TCB             *p_tcb;
313         ER              ercd;
314     
315         LOG_ISIG_SEM_ENTER(semid);
316         CHECK_INTCTX_UNL();
317         CHECK_SEMID(semid);
318         p_semcb = get_semcb(semid);
319
320         i_lock_cpu();
321         if (p_semcb->p_seminib->sematr == TA_NOEXS) {
322                 ercd = E_NOEXS;
323         }
324         else if (!queue_empty(&(p_semcb->wait_queue))) {
325                 p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
326                 if (wait_complete(p_tcb)) {
327                         reqflg = true;
328                 }
329                 ercd = E_OK;
330         }
331         else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
332                 p_semcb->semcnt += 1;
333                 ercd = E_OK;
334         }
335         else {
336                 ercd = E_QOVR;
337         }
338         i_unlock_cpu();
339
340   error_exit:
341         LOG_ISIG_SEM_LEAVE(ercd);
342         return(ercd);
343 }
344
345 #endif /* TOPPERS_isig_sem */
346
347 /*
348  *  セマフォ資源の獲得
349  */
350 #ifdef TOPPERS_wai_sem
351
352 ER
353 wai_sem(ID semid)
354 {
355         SEMCB   *p_semcb;
356         WINFO_SEM winfo_sem;
357         ER              ercd;
358
359         LOG_WAI_SEM_ENTER(semid);
360         CHECK_DISPATCH();
361         CHECK_SEMID(semid);
362         p_semcb = get_semcb(semid);
363
364         t_lock_cpu();
365         if (p_semcb->p_seminib->sematr == TA_NOEXS) {
366                 ercd = E_NOEXS;
367         }
368         else if (p_semcb->semcnt >= 1) {
369                 p_semcb->semcnt -= 1;
370                 ercd = E_OK;
371         }
372         else {
373                 p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
374                 wobj_make_wait((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem);
375                 dispatch();
376                 ercd = winfo_sem.winfo.wercd;
377         }
378         t_unlock_cpu();
379
380   error_exit:
381         LOG_WAI_SEM_LEAVE(ercd);
382         return(ercd);
383 }
384
385 #endif /* TOPPERS_wai_sem */
386
387 /*
388  *  セマフォ資源の獲得(ポーリング)
389  */
390 #ifdef TOPPERS_pol_sem
391
392 ER
393 pol_sem(ID semid)
394 {
395         SEMCB   *p_semcb;
396         ER              ercd;
397
398         LOG_POL_SEM_ENTER(semid);
399         CHECK_TSKCTX_UNL();
400         CHECK_SEMID(semid);
401         p_semcb = get_semcb(semid);
402
403         t_lock_cpu();
404         if (p_semcb->p_seminib->sematr == TA_NOEXS) {
405                 ercd = E_NOEXS;
406         }
407         else if (p_semcb->semcnt >= 1) {
408                 p_semcb->semcnt -= 1;
409                 ercd = E_OK;
410         }
411         else {
412                 ercd = E_TMOUT;
413         }
414         t_unlock_cpu();
415
416   error_exit:
417         LOG_POL_SEM_LEAVE(ercd);
418         return(ercd);
419 }
420
421 #endif /* TOPPERS_pol_sem */
422
423 /*
424  *  セマフォ資源の獲得(タイムアウトあり)
425  */
426 #ifdef TOPPERS_twai_sem
427
428 ER
429 twai_sem(ID semid, TMO tmout)
430 {
431         SEMCB   *p_semcb;
432         WINFO_SEM winfo_sem;
433         TMEVTB  tmevtb;
434         ER              ercd;
435
436         LOG_TWAI_SEM_ENTER(semid, tmout);
437         CHECK_DISPATCH();
438         CHECK_SEMID(semid);
439         CHECK_TMOUT(tmout);
440         p_semcb = get_semcb(semid);
441
442         t_lock_cpu();
443         if (p_semcb->p_seminib->sematr == TA_NOEXS) {
444                 ercd = E_NOEXS;
445         }
446         else if (p_semcb->semcnt >= 1) {
447                 p_semcb->semcnt -= 1;
448                 ercd = E_OK;
449         }
450         else if (tmout == TMO_POL) {
451                 ercd = E_TMOUT;
452         }
453         else {
454                 p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
455                 wobj_make_wait_tmout((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem,
456                                                                                                                 &tmevtb, tmout);
457                 dispatch();
458                 ercd = winfo_sem.winfo.wercd;
459         }
460         t_unlock_cpu();
461
462   error_exit:
463         LOG_TWAI_SEM_LEAVE(ercd);
464         return(ercd);
465 }
466
467 #endif /* TOPPERS_twai_sem */
468
469 /*
470  *  セマフォの再初期化
471  */
472 #ifdef TOPPERS_ini_sem
473
474 ER
475 ini_sem(ID semid)
476 {
477         SEMCB   *p_semcb;
478         bool_t  dspreq;
479         ER              ercd;
480     
481         LOG_INI_SEM_ENTER(semid);
482         CHECK_TSKCTX_UNL();
483         CHECK_SEMID(semid);
484         p_semcb = get_semcb(semid);
485
486         t_lock_cpu();
487         if (p_semcb->p_seminib->sematr == TA_NOEXS) {
488                 ercd = E_NOEXS;
489         }
490         else {
491                 dspreq = init_wait_queue(&(p_semcb->wait_queue));
492                 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
493                 if (dspreq) {
494                         dispatch();
495                 }
496                 ercd = E_OK;
497         }
498         t_unlock_cpu();
499
500   error_exit:
501         LOG_INI_SEM_LEAVE(ercd);
502         return(ercd);
503 }
504
505 #endif /* TOPPERS_ini_sem */
506
507 /*
508  *  セマフォの状態参照
509  */
510 #ifdef TOPPERS_ref_sem
511
512 ER
513 ref_sem(ID semid, T_RSEM *pk_rsem)
514 {
515         SEMCB   *p_semcb;
516         ER              ercd;
517     
518         LOG_REF_SEM_ENTER(semid, pk_rsem);
519         CHECK_TSKCTX_UNL();
520         CHECK_SEMID(semid);
521         p_semcb = get_semcb(semid);
522
523         t_lock_cpu();
524         if (p_semcb->p_seminib->sematr == TA_NOEXS) {
525                 ercd = E_NOEXS;
526         }
527         else {
528                 pk_rsem->wtskid = wait_tskid(&(p_semcb->wait_queue));
529                 pk_rsem->semcnt = p_semcb->semcnt;
530                 ercd = E_OK;
531         }
532         t_unlock_cpu();
533
534   error_exit:
535         LOG_REF_SEM_LEAVE(ercd, pk_rsem);
536         return(ercd);
537 }
538
539 #endif /* TOPPERS_ref_sem */