source: azure_iot_hub/trunk/asp3_dcre/kernel/semaphore.c@ 389

Last change on this file since 389 was 389, checked in by coas-nagasima, 5 years ago

ビルドが通るよう更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 11.2 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-2016 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$
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_WAI_SEM_ENTER
81#define LOG_WAI_SEM_ENTER(semid)
82#endif /* LOG_WAI_SEM_ENTER */
83
84#ifndef LOG_WAI_SEM_LEAVE
85#define LOG_WAI_SEM_LEAVE(ercd)
86#endif /* LOG_WAI_SEM_LEAVE */
87
88#ifndef LOG_POL_SEM_ENTER
89#define LOG_POL_SEM_ENTER(semid)
90#endif /* LOG_POL_SEM_ENTER */
91
92#ifndef LOG_POL_SEM_LEAVE
93#define LOG_POL_SEM_LEAVE(ercd)
94#endif /* LOG_POL_SEM_LEAVE */
95
96#ifndef LOG_TWAI_SEM_ENTER
97#define LOG_TWAI_SEM_ENTER(semid, tmout)
98#endif /* LOG_TWAI_SEM_ENTER */
99
100#ifndef LOG_TWAI_SEM_LEAVE
101#define LOG_TWAI_SEM_LEAVE(ercd)
102#endif /* LOG_TWAI_SEM_LEAVE */
103
104#ifndef LOG_INI_SEM_ENTER
105#define LOG_INI_SEM_ENTER(semid)
106#endif /* LOG_INI_SEM_ENTER */
107
108#ifndef LOG_INI_SEM_LEAVE
109#define LOG_INI_SEM_LEAVE(ercd)
110#endif /* LOG_INI_SEM_LEAVE */
111
112#ifndef LOG_REF_SEM_ENTER
113#define LOG_REF_SEM_ENTER(semid, pk_rsem)
114#endif /* LOG_REF_SEM_ENTER */
115
116#ifndef LOG_REF_SEM_LEAVE
117#define LOG_REF_SEM_LEAVE(ercd, pk_rsem)
118#endif /* LOG_REF_SEM_LEAVE */
119
120/*
121 * セマフォの数
122 */
123#define tnum_sem ((uint_t)(tmax_semid - TMIN_SEMID + 1))
124#define tnum_ssem ((uint_t)(tmax_ssemid - TMIN_SEMID + 1))
125
126/*
127 * セマフォIDからセマフォ管理ブロックを取り出すためのマクロ
128 */
129#define INDEX_SEM(semid) ((uint_t)((semid) - TMIN_SEMID))
130#define get_semcb(semid) (&(semcb_table[INDEX_SEM(semid)]))
131
132#ifdef TOPPERS_semini
133
134/*
135 * 使用していないセマフォ管理ブロックのリスト
136 */
137QUEUE free_semcb;
138
139/*
140 * セマフォ機能の初期化
141 */
142void
143initialize_semaphore(void)
144{
145 uint_t i, j;
146 SEMCB *p_semcb;
147 SEMINIB *p_seminib;
148
149 for (i = 0; i < tnum_ssem; i++) {
150 p_semcb = &(semcb_table[i]);
151 queue_initialize(&(p_semcb->wait_queue));
152 p_semcb->p_seminib = &(seminib_table[i]);
153 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
154 }
155 queue_initialize(&free_semcb);
156 for (j = 0; i < tnum_sem; i++, j++) {
157 p_semcb = &(semcb_table[i]);
158 p_seminib = &(aseminib_table[j]);
159 p_seminib->sematr = TA_NOEXS;
160 p_semcb->p_seminib = ((const SEMINIB *) p_seminib);
161 queue_insert_prev(&free_semcb, &(p_semcb->wait_queue));
162 }
163}
164
165#endif /* TOPPERS_semini */
166
167/*
168 * セマフォの生成
169 */
170#ifdef TOPPERS_acre_sem
171
172ER_UINT
173acre_sem(const T_CSEM *pk_csem)
174{
175 SEMCB *p_semcb;
176 SEMINIB *p_seminib;
177 ATR sematr;
178 uint_t isemcnt, maxsem;
179 ER ercd;
180
181 LOG_ACRE_SEM_ENTER(pk_csem);
182 CHECK_TSKCTX_UNL();
183
184 sematr = pk_csem->sematr;
185 isemcnt = pk_csem->isemcnt;
186 maxsem = pk_csem->maxsem;
187
188 CHECK_RSATR(sematr, TA_TPRI);
189 CHECK_PAR(0 <= isemcnt && isemcnt <= maxsem);
190 CHECK_PAR(1 <= maxsem && maxsem <= TMAX_MAXSEM);
191
192 lock_cpu();
193 if (tnum_sem == 0 || queue_empty(&free_semcb)) {
194 ercd = E_NOID;
195 }
196 else {
197 p_semcb = ((SEMCB *) queue_delete_next(&free_semcb));
198 p_seminib = (SEMINIB *)(p_semcb->p_seminib);
199 p_seminib->sematr = sematr;
200 p_seminib->isemcnt = isemcnt;
201 p_seminib->maxsem = maxsem;
202
203 queue_initialize(&(p_semcb->wait_queue));
204 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
205 ercd = SEMID(p_semcb);
206 }
207 unlock_cpu();
208
209 error_exit:
210 LOG_ACRE_SEM_LEAVE(ercd);
211 return(ercd);
212}
213
214#endif /* TOPPERS_acre_sem */
215
216/*
217 * セマフォの削除
218 */
219#ifdef TOPPERS_del_sem
220
221ER
222del_sem(ID semid)
223{
224 SEMCB *p_semcb;
225 SEMINIB *p_seminib;
226 ER ercd;
227
228 LOG_DEL_SEM_ENTER(semid);
229 CHECK_TSKCTX_UNL();
230 CHECK_ID(VALID_SEMID(semid));
231 p_semcb = get_semcb(semid);
232
233 lock_cpu();
234 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
235 ercd = E_NOEXS;
236 }
237 else if (semid <= tmax_ssemid) {
238 ercd = E_OBJ;
239 }
240 else {
241 init_wait_queue(&(p_semcb->wait_queue));
242 p_seminib = (SEMINIB *)(p_semcb->p_seminib);
243 p_seminib->sematr = TA_NOEXS;
244 queue_insert_prev(&free_semcb, &(p_semcb->wait_queue));
245 if (p_runtsk != p_schedtsk) {
246 dispatch();
247 }
248 ercd = E_OK;
249 }
250 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
264ER
265sig_sem(ID semid)
266{
267 SEMCB *p_semcb;
268 TCB *p_tcb;
269 ER ercd;
270
271 LOG_SIG_SEM_ENTER(semid);
272 CHECK_UNL();
273 CHECK_ID(VALID_SEMID(semid));
274 p_semcb = get_semcb(semid);
275
276 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 wait_complete(p_tcb);
283 if (p_runtsk != p_schedtsk) {
284 if (!sense_context()) {
285 dispatch();
286 }
287 else {
288 request_dispatch();
289 }
290 }
291 ercd = E_OK;
292 }
293 else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
294 p_semcb->semcnt += 1;
295 ercd = E_OK;
296 }
297 else {
298 ercd = E_QOVR;
299 }
300 unlock_cpu();
301
302 error_exit:
303 LOG_SIG_SEM_LEAVE(ercd);
304 return(ercd);
305}
306
307#endif /* TOPPERS_sig_sem */
308
309/*
310 * セマフォ資源の獲得
311 */
312#ifdef TOPPERS_wai_sem
313
314ER
315wai_sem(ID semid)
316{
317 SEMCB *p_semcb;
318 WINFO_SEM winfo_sem;
319 ER ercd;
320
321 LOG_WAI_SEM_ENTER(semid);
322 CHECK_DISPATCH();
323 CHECK_ID(VALID_SEMID(semid));
324 p_semcb = get_semcb(semid);
325
326 lock_cpu_dsp();
327 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
328 ercd = E_NOEXS;
329 }
330 else if (p_runtsk->raster) {
331 ercd = E_RASTER;
332 }
333 else if (p_semcb->semcnt >= 1) {
334 p_semcb->semcnt -= 1;
335 ercd = E_OK;
336 }
337 else {
338 p_runtsk->tstat = TS_WAITING_SEM;
339 wobj_make_wait((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem);
340 dispatch();
341 ercd = winfo_sem.winfo.wercd;
342 }
343 unlock_cpu_dsp();
344
345 error_exit:
346 LOG_WAI_SEM_LEAVE(ercd);
347 return(ercd);
348}
349
350#endif /* TOPPERS_wai_sem */
351
352/*
353 * セマフォ資源の獲得(ポーリング)
354 */
355#ifdef TOPPERS_pol_sem
356
357ER
358pol_sem(ID semid)
359{
360 SEMCB *p_semcb;
361 ER ercd;
362
363 LOG_POL_SEM_ENTER(semid);
364 CHECK_TSKCTX_UNL();
365 CHECK_ID(VALID_SEMID(semid));
366 p_semcb = get_semcb(semid);
367
368 lock_cpu();
369 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
370 ercd = E_NOEXS;
371 }
372 else if (p_semcb->semcnt >= 1) {
373 p_semcb->semcnt -= 1;
374 ercd = E_OK;
375 }
376 else {
377 ercd = E_TMOUT;
378 }
379 unlock_cpu();
380
381 error_exit:
382 LOG_POL_SEM_LEAVE(ercd);
383 return(ercd);
384}
385
386#endif /* TOPPERS_pol_sem */
387
388/*
389 * セマフォ資源の獲得(タイムアウトあり)
390 */
391#ifdef TOPPERS_twai_sem
392
393ER
394twai_sem(ID semid, TMO tmout)
395{
396 SEMCB *p_semcb;
397 WINFO_SEM winfo_sem;
398 TMEVTB tmevtb;
399 ER ercd;
400
401 LOG_TWAI_SEM_ENTER(semid, tmout);
402 CHECK_DISPATCH();
403 CHECK_ID(VALID_SEMID(semid));
404 CHECK_PAR(VALID_TMOUT(tmout));
405 p_semcb = get_semcb(semid);
406
407 lock_cpu_dsp();
408 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
409 ercd = E_NOEXS;
410 }
411 else if (p_runtsk->raster) {
412 ercd = E_RASTER;
413 }
414 else if (p_semcb->semcnt >= 1) {
415 p_semcb->semcnt -= 1;
416 ercd = E_OK;
417 }
418 else if (tmout == TMO_POL) {
419 ercd = E_TMOUT;
420 }
421 else {
422 p_runtsk->tstat = TS_WAITING_SEM;
423 wobj_make_wait_tmout((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem,
424 &tmevtb, tmout);
425 dispatch();
426 ercd = winfo_sem.winfo.wercd;
427 }
428 unlock_cpu_dsp();
429
430 error_exit:
431 LOG_TWAI_SEM_LEAVE(ercd);
432 return(ercd);
433}
434
435#endif /* TOPPERS_twai_sem */
436
437/*
438 * セマフォの再初期化
439 */
440#ifdef TOPPERS_ini_sem
441
442ER
443ini_sem(ID semid)
444{
445 SEMCB *p_semcb;
446 ER ercd;
447
448 LOG_INI_SEM_ENTER(semid);
449 CHECK_TSKCTX_UNL();
450 CHECK_ID(VALID_SEMID(semid));
451 p_semcb = get_semcb(semid);
452
453 lock_cpu();
454 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
455 ercd = E_NOEXS;
456 }
457 else {
458 init_wait_queue(&(p_semcb->wait_queue));
459 p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
460 if (p_runtsk != p_schedtsk) {
461 dispatch();
462 }
463 ercd = E_OK;
464 }
465 unlock_cpu();
466
467 error_exit:
468 LOG_INI_SEM_LEAVE(ercd);
469 return(ercd);
470}
471
472#endif /* TOPPERS_ini_sem */
473
474/*
475 * セマフォの状態参照
476 */
477#ifdef TOPPERS_ref_sem
478
479ER
480ref_sem(ID semid, T_RSEM *pk_rsem)
481{
482 SEMCB *p_semcb;
483 ER ercd;
484
485 LOG_REF_SEM_ENTER(semid, pk_rsem);
486 CHECK_TSKCTX_UNL();
487 CHECK_ID(VALID_SEMID(semid));
488 p_semcb = get_semcb(semid);
489
490 lock_cpu();
491 if (p_semcb->p_seminib->sematr == TA_NOEXS) {
492 ercd = E_NOEXS;
493 }
494 else {
495 pk_rsem->wtskid = wait_tskid(&(p_semcb->wait_queue));
496 pk_rsem->semcnt = p_semcb->semcnt;
497 ercd = E_OK;
498 }
499 unlock_cpu();
500
501 error_exit:
502 LOG_REF_SEM_LEAVE(ercd, pk_rsem);
503 return(ercd);
504}
505
506#endif /* TOPPERS_ref_sem */
Note: See TracBrowser for help on using the repository browser.