semaphore.c

説明を見る。
00001 /*
00002  *  TOPPERS/ASP Kernel
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      Advanced Standard Profile Kernel
00005  * 
00006  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
00007  *                              Toyohashi Univ. of Technology, JAPAN
00008  *  Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory
00009  *              Graduate School of Information Science, Nagoya Univ., JAPAN
00010  * 
00011  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
00012  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
00013  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
00014  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00015  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00016  *      スコード中に含まれていること.
00017  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00018  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00019  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00020  *      の無保証規定を掲載すること.
00021  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00022  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00023  *      と.
00024  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00025  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00026  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00027  *        報告すること.
00028  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00029  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00030  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
00031  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
00032  *      免責すること.
00033  * 
00034  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00035  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
00036  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
00037  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
00038  *  の責任を負わない.
00039  * 
00040  *  @(#) $Id: semaphore.c 748 2008-03-07 17:18:06Z hiro $
00041  */
00042 
00043 /*
00044  *      セマフォ機能
00045  */
00046 
00047 #include "kernel_impl.h"
00048 #include "check.h"
00049 #include "task.h"
00050 #include "wait.h"
00051 #include "semaphore.h"
00052 
00053 /*
00054  *  トレースログマクロのデフォルト定義
00055  */
00056 #ifndef LOG_SIG_SEM_ENTER
00057 #define LOG_SIG_SEM_ENTER(semid)
00058 #endif /* LOG_SIG_SEM_ENTER */
00059 
00060 #ifndef LOG_SIG_SEM_LEAVE
00061 #define LOG_SIG_SEM_LEAVE(ercd)
00062 #endif /* LOG_SIG_SEM_LEAVE */
00063 
00064 #ifndef LOG_ISIG_SEM_ENTER
00065 #define LOG_ISIG_SEM_ENTER(semid)
00066 #endif /* LOG_ISIG_SEM_ENTER */
00067 
00068 #ifndef LOG_ISIG_SEM_LEAVE
00069 #define LOG_ISIG_SEM_LEAVE(ercd)
00070 #endif /* LOG_ISIG_SEM_LEAVE */
00071 
00072 #ifndef LOG_WAI_SEM_ENTER
00073 #define LOG_WAI_SEM_ENTER(semid)
00074 #endif /* LOG_WAI_SEM_ENTER */
00075 
00076 #ifndef LOG_WAI_SEM_LEAVE
00077 #define LOG_WAI_SEM_LEAVE(ercd)
00078 #endif /* LOG_WAI_SEM_LEAVE */
00079 
00080 #ifndef LOG_POL_SEM_ENTER
00081 #define LOG_POL_SEM_ENTER(semid)
00082 #endif /* LOG_POL_SEM_ENTER */
00083 
00084 #ifndef LOG_POL_SEM_LEAVE
00085 #define LOG_POL_SEM_LEAVE(ercd)
00086 #endif /* LOG_POL_SEM_LEAVE */
00087 
00088 #ifndef LOG_TWAI_SEM_ENTER
00089 #define LOG_TWAI_SEM_ENTER(semid, tmout)
00090 #endif /* LOG_TWAI_SEM_ENTER */
00091 
00092 #ifndef LOG_TWAI_SEM_LEAVE
00093 #define LOG_TWAI_SEM_LEAVE(ercd)
00094 #endif /* LOG_TWAI_SEM_LEAVE */
00095 
00096 #ifndef LOG_INI_SEM_ENTER
00097 #define LOG_INI_SEM_ENTER(semid)
00098 #endif /* LOG_INI_SEM_ENTER */
00099 
00100 #ifndef LOG_INI_SEM_LEAVE
00101 #define LOG_INI_SEM_LEAVE(ercd)
00102 #endif /* LOG_INI_SEM_LEAVE */
00103 
00104 #ifndef LOG_REF_SEM_ENTER
00105 #define LOG_REF_SEM_ENTER(semid, pk_rsem)
00106 #endif /* LOG_REF_SEM_ENTER */
00107 
00108 #ifndef LOG_REF_SEM_LEAVE
00109 #define LOG_REF_SEM_LEAVE(ercd, pk_rsem)
00110 #endif /* LOG_REF_SEM_LEAVE */
00111 
00112 /*
00113  *  セマフォの数
00114  */
00115 #define tnum_sem    ((uint_t)(tmax_semid - TMIN_SEMID + 1))
00116 
00117 /*
00118  *  セマフォIDからセマフォ管理ブロックを取り出すためのマクロ
00119  */
00120 #define INDEX_SEM(semid)    ((uint_t)((semid) - TMIN_SEMID))
00121 #define get_semcb(semid)    (&(semcb_table[INDEX_SEM(semid)]))
00122 
00123 /* 
00124  *  セマフォ機能の初期化
00125  */
00126 #ifdef TOPPERS_semini
00127 
00128 void
00129 initialize_semaphore(void)
00130 {
00131     uint_t  i;
00132     SEMCB   *p_semcb;
00133 
00134     for (p_semcb = semcb_table, i = 0; i < tnum_sem; p_semcb++, i++) {
00135         queue_initialize(&(p_semcb->wait_queue));
00136         p_semcb->p_seminib = &(seminib_table[i]);
00137         p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
00138     }
00139 }
00140 
00141 #endif /* TOPPERS_semini */
00142 
00143 /*
00144  *  セマフォ資源の返却
00145  */
00146 #ifdef TOPPERS_sig_sem
00147 
00148 ER
00149 sig_sem(ID semid)
00150 {
00151     SEMCB   *p_semcb;
00152     TCB     *p_tcb;
00153     ER      ercd;
00154     
00155     LOG_SIG_SEM_ENTER(semid);
00156     CHECK_TSKCTX_UNL();
00157     CHECK_SEMID(semid);
00158     p_semcb = get_semcb(semid);
00159 
00160     t_lock_cpu();
00161     if (!queue_empty(&(p_semcb->wait_queue))) {
00162         p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
00163         if (wait_complete(p_tcb)) {
00164             dispatch();
00165         }
00166         ercd = E_OK;
00167     }
00168     else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
00169         p_semcb->semcnt += 1;
00170         ercd = E_OK;
00171     }
00172     else {
00173         ercd = E_QOVR;
00174     }
00175     t_unlock_cpu();
00176 
00177   error_exit:
00178     LOG_SIG_SEM_LEAVE(ercd);
00179     return(ercd);
00180 }
00181 
00182 #endif /* TOPPERS_sig_sem */
00183 
00184 /*
00185  *  セマフォ資源の返却(非タスクコンテキスト用)
00186  */
00187 #ifdef TOPPERS_isig_sem
00188 
00189 ER
00190 isig_sem(ID semid)
00191 {
00192     SEMCB   *p_semcb;
00193     TCB     *p_tcb;
00194     ER      ercd;
00195     
00196     LOG_ISIG_SEM_ENTER(semid);
00197     CHECK_INTCTX_UNL();
00198     CHECK_SEMID(semid);
00199     p_semcb = get_semcb(semid);
00200 
00201     i_lock_cpu();
00202     if (!queue_empty(&(p_semcb->wait_queue))) {
00203         p_tcb = (TCB *) queue_delete_next(&(p_semcb->wait_queue));
00204         if (wait_complete(p_tcb)) {
00205             reqflg = true;
00206         }
00207         ercd = E_OK;
00208     }
00209     else if (p_semcb->semcnt < p_semcb->p_seminib->maxsem) {
00210         p_semcb->semcnt += 1;
00211         ercd = E_OK;
00212     }
00213     else {
00214         ercd = E_QOVR;
00215     }
00216     i_unlock_cpu();
00217 
00218   error_exit:
00219     LOG_ISIG_SEM_LEAVE(ercd);
00220     return(ercd);
00221 }
00222 
00223 #endif /* TOPPERS_isig_sem */
00224 
00225 /*
00226  *  セマフォ資源の獲得
00227  */
00228 #ifdef TOPPERS_wai_sem
00229 
00230 ER
00231 wai_sem(ID semid)
00232 {
00233     SEMCB   *p_semcb;
00234     WINFO_SEM winfo_sem;
00235     ER      ercd;
00236 
00237     LOG_WAI_SEM_ENTER(semid);
00238     CHECK_DISPATCH();
00239     CHECK_SEMID(semid);
00240     p_semcb = get_semcb(semid);
00241 
00242     t_lock_cpu();
00243     if (p_semcb->semcnt >= 1) {
00244         p_semcb->semcnt -= 1;
00245         ercd = E_OK;
00246     }
00247     else {
00248         p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
00249         wobj_make_wait((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem);
00250         dispatch();
00251         ercd = winfo_sem.winfo.wercd;
00252     }
00253     t_unlock_cpu();
00254 
00255   error_exit:
00256     LOG_WAI_SEM_LEAVE(ercd);
00257     return(ercd);
00258 }
00259 
00260 #endif /* TOPPERS_wai_sem */
00261 
00262 /*
00263  *  セマフォ資源の獲得(ポーリング)
00264  */
00265 #ifdef TOPPERS_pol_sem
00266 
00267 ER
00268 pol_sem(ID semid)
00269 {
00270     SEMCB   *p_semcb;
00271     ER      ercd;
00272 
00273     LOG_POL_SEM_ENTER(semid);
00274     CHECK_TSKCTX_UNL();
00275     CHECK_SEMID(semid);
00276     p_semcb = get_semcb(semid);
00277 
00278     t_lock_cpu();
00279     if (p_semcb->semcnt >= 1) {
00280         p_semcb->semcnt -= 1;
00281         ercd = E_OK;
00282     }
00283     else {
00284         ercd = E_TMOUT;
00285     }
00286     t_unlock_cpu();
00287 
00288   error_exit:
00289     LOG_POL_SEM_LEAVE(ercd);
00290     return(ercd);
00291 }
00292 
00293 #endif /* TOPPERS_pol_sem */
00294 
00295 /*
00296  *  セマフォ資源の獲得(タイムアウトあり)
00297  */
00298 #ifdef TOPPERS_twai_sem
00299 
00300 ER
00301 twai_sem(ID semid, TMO tmout)
00302 {
00303     SEMCB   *p_semcb;
00304     WINFO_SEM winfo_sem;
00305     TMEVTB  tmevtb;
00306     ER      ercd;
00307 
00308     LOG_TWAI_SEM_ENTER(semid, tmout);
00309     CHECK_DISPATCH();
00310     CHECK_SEMID(semid);
00311     CHECK_TMOUT(tmout);
00312     p_semcb = get_semcb(semid);
00313 
00314     t_lock_cpu();
00315     if (p_semcb->semcnt >= 1) {
00316         p_semcb->semcnt -= 1;
00317         ercd = E_OK;
00318     }
00319     else if (tmout == TMO_POL) {
00320         ercd = E_TMOUT;
00321     }
00322     else {
00323         p_runtsk->tstat = (TS_WAITING | TS_WAIT_SEM);
00324         wobj_make_wait_tmout((WOBJCB *) p_semcb, (WINFO_WOBJ *) &winfo_sem,
00325                                                         &tmevtb, tmout);
00326         dispatch();
00327         ercd = winfo_sem.winfo.wercd;
00328     }
00329     t_unlock_cpu();
00330 
00331   error_exit:
00332     LOG_TWAI_SEM_LEAVE(ercd);
00333     return(ercd);
00334 }
00335 
00336 #endif /* TOPPERS_twai_sem */
00337 
00338 /*
00339  *  セマフォの再初期化
00340  */
00341 #ifdef TOPPERS_ini_sem
00342 
00343 ER
00344 ini_sem(ID semid)
00345 {
00346     SEMCB   *p_semcb;
00347     bool_t  dspreq;
00348     ER      ercd;
00349     
00350     LOG_INI_SEM_ENTER(semid);
00351     CHECK_TSKCTX_UNL();
00352     CHECK_SEMID(semid);
00353     p_semcb = get_semcb(semid);
00354 
00355     t_lock_cpu();
00356     dspreq = init_wait_queue(&(p_semcb->wait_queue));
00357     p_semcb->semcnt = p_semcb->p_seminib->isemcnt;
00358     if (dspreq) {
00359         dispatch();
00360     }
00361     ercd = E_OK;
00362     t_unlock_cpu();
00363 
00364   error_exit:
00365     LOG_INI_SEM_LEAVE(ercd);
00366     return(ercd);
00367 }
00368 
00369 #endif /* TOPPERS_ini_sem */
00370 
00371 /*
00372  *  セマフォの状態参照
00373  */
00374 #ifdef TOPPERS_ref_sem
00375 
00376 ER
00377 ref_sem(ID semid, T_RSEM *pk_rsem)
00378 {
00379     SEMCB   *p_semcb;
00380     ER      ercd;
00381     
00382     LOG_REF_SEM_ENTER(semid, pk_rsem);
00383     CHECK_TSKCTX_UNL();
00384     CHECK_SEMID(semid);
00385     p_semcb = get_semcb(semid);
00386 
00387     t_lock_cpu();
00388     pk_rsem->wtskid = wait_tskid(&(p_semcb->wait_queue));
00389     pk_rsem->semcnt = p_semcb->semcnt;
00390     ercd = E_OK;
00391     t_unlock_cpu();
00392 
00393   error_exit:
00394     LOG_REF_SEM_LEAVE(ercd, pk_rsem);
00395     return(ercd);
00396 }
00397 
00398 #endif /* TOPPERS_ref_sem */

Copyright © 2008 by Kijineko Inc.

ホームページ制作