source: UsbWattMeter/trunk/asp_dcre/kernel/semaphore.c

Last change on this file was 167, checked in by coas-nagasima, 6 years ago

MIMEにSJISを設定

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc; charset=SHIFT_JIS
File size: 11.0 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-2012 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 167 2016-03-08 11:37:45Z coas-nagasima $
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 */
145QUEUE free_semcb;
146
147/*
148 * セマフォ機能の初期化
149 */
150void
151initialize_semaphore(void)
152{
153 uint_t i, j;
154 SEMCB *p_semcb;
155 SEMINIB *p_seminib;
156
157 for (i = 0; i < tnum_ssem; i++) {
158 p_semcb = &(semcb_table[i]);
159 queue_initialize(&(p_semcb->wait_queue));
160 p_semcb->p_seminib = &(seminib_table[i]);
161 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
162 }
163 queue_initialize(&free_semcb);
164 for (j = 0; i < tnum_sem; i++, j++) {
165 p_semcb = &(semcb_table[i]);
166 p_seminib = &(aseminib_table[j]);
167 p_seminib->sematr = TA_NOEXS;
168 p_semcb->p_seminib = ((const SEMINIB *) p_seminib);
169 queue_insert_prev(&free_semcb, &(p_semcb->wait_queue));
170 }
171}
172
173#endif /* TOPPERS_semini */
174
175/*
176 * セマフォの生成
177 */
178#ifdef TOPPERS_acre_sem
179
180ER_UINT
181acre_sem(const T_CSEM *pk_csem)
182{
183 SEMCB *p_semcb;
184 SEMINIB *p_seminib;
185 ER ercd;
186
187 LOG_ACRE_SEM_ENTER(pk_csem);
188 CHECK_TSKCTX_UNL();
189 CHECK_RSATR(pk_csem->sematr, TA_TPRI);
190 CHECK_PAR(0 <= pk_csem->isemcnt && pk_csem->isemcnt <= pk_csem->maxsem);
191 CHECK_PAR(1 <= pk_csem->maxsem && pk_csem->maxsem <= TMAX_MAXSEM);
192
193 t_lock_cpu();
194 if (tnum_sem == 0 || queue_empty(&free_semcb)) {
195 ercd = E_NOID;
196 }
197 else {
198 p_semcb = ((SEMCB *) queue_delete_next(&free_semcb));
199 p_seminib = (SEMINIB *)(p_semcb->p_seminib);
200 p_seminib->sematr = pk_csem->sematr;
201 p_seminib->isemcnt = pk_csem->isemcnt;
202 p_seminib->maxsem = pk_csem->maxsem;
203
204 queue_initialize(&(p_semcb->wait_queue));
205 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
206 ercd = SEMID(p_semcb);
207 }
208 t_unlock_cpu();
209
210 error_exit:
211 LOG_ACRE_SEM_LEAVE(ercd);
212 return(ercd);
213}
214
215#endif /* TOPPERS_acre_sem */
216
217/*
218 * セマフォの削除
219 */
220#ifdef TOPPERS_del_sem
221
222ER
223del_sem(ID semid)
224{
225 SEMCB *p_semcb;
226 SEMINIB *p_seminib;
227 bool_t dspreq;
228 ER ercd;
229
230 LOG_DEL_SEM_ENTER(semid);
231 CHECK_TSKCTX_UNL();
232 CHECK_SEMID(semid);
233 p_semcb = get_semcb(semid);
234
235 t_lock_cpu();
236 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
237 ercd = E_NOEXS;
238 }
239 else if (SEMID(p_semcb) > tmax_ssemid) {
240 dspreq = init_wait_queue(&(p_semcb->wait_queue));
241 p_seminib = (SEMINIB *)(p_semcb->p_seminib);
242 p_seminib->sematr = TA_NOEXS;
243 queue_insert_prev(&free_semcb, &(p_semcb->wait_queue));
244 if (dspreq) {
245 dispatch();
246 }
247 ercd = E_OK;
248 }
249 else {
250 ercd = E_OBJ;
251 }
252 t_unlock_cpu();
253
254 error_exit:
255 LOG_DEL_SEM_LEAVE(ercd);
256 return(ercd);
257}
258
259#endif /* TOPPERS_del_sem */
260
261/*
262 * セマフォ資源の返却
263 */
264#ifdef TOPPERS_sig_sem
265
266ER
267sig_sem(ID semid)
268{
269 SEMCB *p_semcb;
270 TCB *p_tcb;
271 ER ercd;
272
273 LOG_SIG_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->p_seminib->sematr == TA_NOEXS) {
280 ercd = E_NOEXS;
281 }
282 else if (!queue_empty(&(p_semcb->wait_queue))) {
283 p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
284 if (wait_complete(p_tcb)) {
285 dispatch();
286 }
287 ercd = E_OK;
288 }
289 else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
290 p_semcb->semcnt += 1;
291 ercd = E_OK;
292 }
293 else {
294 ercd = E_QOVR;
295 }
296 t_unlock_cpu();
297
298 error_exit:
299 LOG_SIG_SEM_LEAVE(ercd);
300 return(ercd);
301}
302
303#endif /* TOPPERS_sig_sem */
304
305/*
306 * セマフォ資源の返却(非タスクコンテキスト用)
307 */
308#ifdef TOPPERS_isig_sem
309
310ER
311isig_sem(ID semid)
312{
313 SEMCB *p_semcb;
314 TCB *p_tcb;
315 ER ercd;
316
317 LOG_ISIG_SEM_ENTER(semid);
318 CHECK_INTCTX_UNL();
319 CHECK_SEMID(semid);
320 p_semcb = get_semcb(semid);
321
322 i_lock_cpu();
323 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
324 ercd = E_NOEXS;
325 }
326 else if (!queue_empty(&(p_semcb->wait_queue))) {
327 p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
328 if (wait_complete(p_tcb)) {
329 reqflg = true;
330 }
331 ercd = E_OK;
332 }
333 else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
334 p_semcb->semcnt += 1;
335 ercd = E_OK;
336 }
337 else {
338 ercd = E_QOVR;
339 }
340 i_unlock_cpu();
341
342 error_exit:
343 LOG_ISIG_SEM_LEAVE(ercd);
344 return(ercd);
345}
346
347#endif /* TOPPERS_isig_sem */
348
349/*
350 * セマフォ資源の獲得
351 */
352#ifdef TOPPERS_wai_sem
353
354ER
355wai_sem(ID semid)
356{
357 SEMCB *p_semcb;
358 WINFO_SEM winfo_sem;
359 ER ercd;
360
361 LOG_WAI_SEM_ENTER(semid);
362 CHECK_DISPATCH();
363 CHECK_SEMID(semid);
364 p_semcb = get_semcb(semid);
365
366 t_lock_cpu();
367 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
368 ercd = E_NOEXS;
369 }
370 else if (p_semcb->semcnt >= 1) {
371 p_semcb->semcnt -= 1;
372 ercd = E_OK;
373 }
374 else {
375 p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
376 wobj_make_wait((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem);
377 dispatch();
378 ercd = winfo_sem.winfo.wercd;
379 }
380 t_unlock_cpu();
381
382 error_exit:
383 LOG_WAI_SEM_LEAVE(ercd);
384 return(ercd);
385}
386
387#endif /* TOPPERS_wai_sem */
388
389/*
390 * セマフォ資源の獲得(ポーリング)
391 */
392#ifdef TOPPERS_pol_sem
393
394ER
395pol_sem(ID semid)
396{
397 SEMCB *p_semcb;
398 ER ercd;
399
400 LOG_POL_SEM_ENTER(semid);
401 CHECK_TSKCTX_UNL();
402 CHECK_SEMID(semid);
403 p_semcb = get_semcb(semid);
404
405 t_lock_cpu();
406 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
407 ercd = E_NOEXS;
408 }
409 else if (p_semcb->semcnt >= 1) {
410 p_semcb->semcnt -= 1;
411 ercd = E_OK;
412 }
413 else {
414 ercd = E_TMOUT;
415 }
416 t_unlock_cpu();
417
418 error_exit:
419 LOG_POL_SEM_LEAVE(ercd);
420 return(ercd);
421}
422
423#endif /* TOPPERS_pol_sem */
424
425/*
426 * セマフォ資源の獲得(タイムアウトあり)
427 */
428#ifdef TOPPERS_twai_sem
429
430ER
431twai_sem(ID semid, TMO tmout)
432{
433 SEMCB *p_semcb;
434 WINFO_SEM winfo_sem;
435 TMEVTB tmevtb;
436 ER ercd;
437
438 LOG_TWAI_SEM_ENTER(semid, tmout);
439 CHECK_DISPATCH();
440 CHECK_SEMID(semid);
441 CHECK_TMOUT(tmout);
442 p_semcb = get_semcb(semid);
443
444 t_lock_cpu();
445 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
446 ercd = E_NOEXS;
447 }
448 else if (p_semcb->semcnt >= 1) {
449 p_semcb->semcnt -= 1;
450 ercd = E_OK;
451 }
452 else if (tmout == TMO_POL) {
453 ercd = E_TMOUT;
454 }
455 else {
456 p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
457 wobj_make_wait_tmout((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem,
458 &tmevtb, tmout);
459 dispatch();
460 ercd = winfo_sem.winfo.wercd;
461 }
462 t_unlock_cpu();
463
464 error_exit:
465 LOG_TWAI_SEM_LEAVE(ercd);
466 return(ercd);
467}
468
469#endif /* TOPPERS_twai_sem */
470
471/*
472 * セマフォの再初期化
473 */
474#ifdef TOPPERS_ini_sem
475
476ER
477ini_sem(ID semid)
478{
479 SEMCB *p_semcb;
480 bool_t dspreq;
481 ER ercd;
482
483 LOG_INI_SEM_ENTER(semid);
484 CHECK_TSKCTX_UNL();
485 CHECK_SEMID(semid);
486 p_semcb = get_semcb(semid);
487
488 t_lock_cpu();
489 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
490 ercd = E_NOEXS;
491 }
492 else {
493 dspreq = init_wait_queue(&(p_semcb->wait_queue));
494 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
495 if (dspreq) {
496 dispatch();
497 }
498 ercd = E_OK;
499 }
500 t_unlock_cpu();
501
502 error_exit:
503 LOG_INI_SEM_LEAVE(ercd);
504 return(ercd);
505}
506
507#endif /* TOPPERS_ini_sem */
508
509/*
510 * セマフォの状態参照
511 */
512#ifdef TOPPERS_ref_sem
513
514ER
515ref_sem(ID semid, T_RSEM *pk_rsem)
516{
517 SEMCB *p_semcb;
518 ER ercd;
519
520 LOG_REF_SEM_ENTER(semid, pk_rsem);
521 CHECK_TSKCTX_UNL();
522 CHECK_SEMID(semid);
523 p_semcb = get_semcb(semid);
524
525 t_lock_cpu();
526 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
527 ercd = E_NOEXS;
528 }
529 else {
530 pk_rsem->wtskid = wait_tskid(&(p_semcb->wait_queue));
531 pk_rsem->semcnt = p_semcb->semcnt;
532 ercd = E_OK;
533 }
534 t_unlock_cpu();
535
536 error_exit:
537 LOG_REF_SEM_LEAVE(ercd, pk_rsem);
538 return(ercd);
539}
540
541#endif /* TOPPERS_ref_sem */
Note: See TracBrowser for help on using the repository browser.