semaphore.c

説明を見る。
00001 /*
00002  *  TOPPERS/FDMP Kernel
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      Function Distributed Multiprocessor Kernel
00005  *
00006  *  Copyright (C) 2000-2004 by Embedded and Real-Time Systems Laboratory
00007  *                              Toyohashi Univ. of Technology, JAPAN
00008  *  Copyright (C) 2005-2006 by Embedded and Real-Time Systems Laboratory
00009  *              Graduate School of Information Science, Nagoya Univ., JAPAN
00010  * 
00011  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
00012  *  によって公表されている GNU General Public License の Version 2 に記
00013  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
00014  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
00015  *  利用と呼ぶ)することを無償で許諾する.
00016  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00017  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00018  *      スコード中に含まれていること.
00019  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00020  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00021  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00022  *      の無保証規定を掲載すること.
00023  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00024  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00025  *      と.
00026  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00027  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00028  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00029  *        報告すること.
00030  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00031  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00032  * 
00033  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00034  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
00035  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
00036  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
00037  * 
00038  *  @(#) $Id: semaphore.c,v 1.3 2006/03/14 04:37:54 honda Exp $
00039  */
00040 
00045 #include "fdmp_kernel.h"
00046 #include "check.h"
00047 #include "task.h"
00048 #include "wait.h"
00049 #include "semaphore.h"
00050 
00054 extern const ID tmax_semid;
00055 
00059 extern const SEMINIB    seminib_table[];
00060 
00064 extern SEMCB    semcb_table[];
00065 
00069 #define TNUM_SEM    ((UINT)(tmax_semid - TMIN_ID + 1))
00070 
00071 /*
00072  *  セマフォIDからセマフォ管理ブロックを取り出すためのマクロ
00073  */
00074 #define INDEX_SEM(semid)    ((UINT)((semid) - TMIN_ID))
00075 #define get_semcb(ccb, semid)   (&(((SEMCB *)(ccb->sem.cb_table))[INDEX_SEM(semid)]))
00076 
00077 
00078 /* 
00079  *  セマフォ機能の初期化
00080  */
00081 #ifdef __semini
00082 
00083 void
00084 semaphore_initialize()
00085 {
00086     UINT    i;
00087     SEMCB   *semcb;
00088 
00089     for (semcb = semcb_table, i = 0; i < TNUM_SEM; semcb++, i++) {
00090         queue_initialize(&(semcb->wait_queue));
00091         semcb->seminib = &(seminib_table[i]);
00092         semcb->semcnt = semcb->seminib->isemcnt;
00093     }
00094 
00095     my_local_exccb->sem.cb_table = &semcb_table[0];
00096     my_local_exccb->sem.max_id   = tmax_semid;  
00097 }
00098 
00099 #endif /* __semini */
00100 
00105 #ifdef __sig_sem
00106 
00107 SYSCALL ER
00108 sig_sem(ID semid)
00109 {
00110     SEMCB   *semcb;
00111     TCB     *tcb;
00112     ER      ercd;
00113     CCB     *ccb, *tccb;
00114     BOOL    dspreq = FALSE;
00115     
00116     LOG_SIG_SEM_ENTER(semid);
00117     CHECK_TSKCTX_UNL();
00118     ccb = T_CHECK_CLSID_CCB(semid);
00119     semid = remove_clsid(semid);
00120     CHECK_SEMID(ccb, semid);
00121     semcb = get_semcb(ccb, semid);
00122 
00123   retry:    
00124     T_ACQUIRE_LOCK(ccb->obj_lock);
00125     if (!(queue_empty(&(semcb->wait_queue)))) {
00126         /*
00127          * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00128          * 繰り返し実行するため,この間非破壊コードでなければならない.
00129          */ 
00130         tcb = (TCB *)(semcb->wait_queue.next);
00131         tccb = get_ccb(tcb->clsid);
00132         T_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00133         /* 待ちキューから削除する */
00134         queue_delete((QUEUE *) tcb);
00135         if (wait_complete(tccb, tcb)) {
00136             dspreq = dispatch_request(tccb->prcid);
00137         }
00138         T_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00139         ercd = E_OK;
00140     }
00141     else if (semcb->semcnt < semcb->seminib->maxsem) {
00142         semcb->semcnt += 1;
00143         ercd = E_OK;
00144     }
00145     else {
00146         ercd = E_QOVR;
00147     }
00148     T_RELEASE_LOCK_AND_DISPATCH(ccb->obj_lock, dspreq);
00149 
00150   exit:
00151     LOG_SIG_SEM_LEAVE(ercd);
00152     return(ercd);
00153 }
00154 
00155 #endif /* __sig_sem */
00156 
00160 #ifdef __isig_sem
00161 
00162 SYSCALL ER
00163 isig_sem(ID semid)
00164 {
00165     SEMCB   *semcb;
00166     TCB     *tcb;
00167     ER      ercd;
00168     CCB     *ccb, *tccb;
00169     
00170     LOG_ISIG_SEM_ENTER(semid);
00171     CHECK_INTCTX_UNL();
00172     ccb = I_CHECK_CLSID_CCB(semid);
00173     semid = remove_clsid(semid);
00174     CHECK_SEMID(ccb, semid);
00175     semcb = get_semcb(ccb, semid);
00176 
00177   retry:
00178     I_ACQUIRE_LOCK(ccb->obj_lock);  
00179     if (!queue_empty(&(semcb->wait_queue))) {
00180         /*
00181          * T_ACQUIRE_NESTED_LOCK()は,T_ACQUIRE_LOCK()との間をリトライで
00182          * 繰り返し実行するため,この間非破壊コードでなければならない.
00183          */      
00184         tcb = (TCB *)(semcb->wait_queue.next);
00185         tccb = get_ccb(tcb->clsid);
00186         I_ACQUIRE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00187         /* 待ちキューから削除する */
00188         queue_delete_next(&(semcb->wait_queue));
00189         if (wait_complete(tccb, tcb)) {
00190             if (dispatch_request(tccb->prcid)){
00191                 reqflg = TRUE;
00192             }
00193         }
00194         I_RELEASE_NESTED_LOCK(tccb->tsk_lock, ccb->obj_lock);
00195         ercd = E_OK;
00196     }
00197     else if (semcb->semcnt < semcb->seminib->maxsem) {
00198         semcb->semcnt += 1;
00199         ercd = E_OK;
00200     }
00201     else {
00202         ercd = E_QOVR;
00203     }
00204     I_RELEASE_LOCK(ccb->obj_lock);
00205 
00206   exit:
00207     LOG_ISIG_SEM_LEAVE(ercd);
00208     return(ercd);
00209 }
00210 
00211 #endif /* __isig_sem */
00212 
00216 #ifdef __wai_sem
00217 
00218 SYSCALL ER
00219 wai_sem(ID semid)
00220 {
00221     SEMCB   *semcb;
00222     WINFO_WOBJ winfo;
00223     ER      ercd;
00224     CCB     *ccb;
00225 
00226     LOG_WAI_SEM_ENTER(semid);
00227     CHECK_DISPATCH();
00228     ccb = T_CHECK_CLSID_CCB(semid);
00229     semid = remove_clsid(semid);
00230     CHECK_SEMID(ccb, semid);
00231     semcb = get_semcb(ccb, semid);
00232 
00233   retry:    
00234     T_ACQUIRE_LOCK(ccb->obj_lock);
00235     if (semcb->semcnt >= 1) {
00236         semcb->semcnt -= 1;
00237         RELEASE_LOCK(ccb->obj_lock);
00238         ercd = E_OK;
00239     }
00240     else {
00241         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00242         wobj_make_wait(ccb, (WOBJCB *) semcb, &winfo);
00243         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00244         RELEASE_LOCK(ccb->obj_lock);
00245         dispatch();
00246         ercd = winfo.winfo.wercd;
00247     }
00248     t_unlock_cpu();
00249 
00250   exit:
00251     LOG_WAI_SEM_LEAVE(ercd);
00252     return(ercd);
00253 }
00254 
00255 #endif /* __wai_sem */
00256 
00260 #ifdef __pol_sem
00261 
00262 SYSCALL ER
00263 pol_sem(ID semid)
00264 {
00265     SEMCB   *semcb;
00266     ER      ercd;
00267     CCB     *ccb;
00268     
00269     LOG_POL_SEM_ENTER(semid);
00270     CHECK_TSKCTX_UNL();
00271     ccb = T_CHECK_CLSID_CCB(semid);
00272     semid = remove_clsid(semid);
00273     CHECK_SEMID(ccb, semid);
00274     semcb = get_semcb(ccb, semid);
00275     
00276   retry:
00277     T_ACQUIRE_LOCK(ccb->obj_lock);
00278     if (semcb->semcnt >= 1) {
00279         semcb->semcnt -= 1;
00280         ercd = E_OK;
00281     }
00282     else {
00283         ercd = E_TMOUT;
00284     }
00285     T_RELEASE_LOCK(ccb->obj_lock);
00286 
00287   exit:
00288     LOG_POL_SEM_LEAVE(ercd);
00289     return(ercd);
00290 }
00291 
00292 #endif /* __pol_sem */
00293 
00297 #ifdef __twai_sem
00298 
00299 SYSCALL ER
00300 twai_sem(ID semid, TMO tmout)
00301 {
00302     SEMCB   *semcb;
00303     WINFO_WOBJ winfo;
00304     TMEVTB  tmevtb;
00305     ER  ercd;
00306     CCB *ccb;
00307 
00308     LOG_TWAI_SEM_ENTER(semid, tmout);
00309     CHECK_DISPATCH();
00310     ccb = T_CHECK_CLSID_CCB(semid);
00311     semid = remove_clsid(semid);
00312     CHECK_SEMID(ccb, semid);
00313     semcb = get_semcb(ccb, semid);
00314 
00315   retry:    
00316     T_ACQUIRE_LOCK(ccb->obj_lock);
00317     if (semcb->semcnt >= 1) {
00318         semcb->semcnt -= 1;
00319         RELEASE_LOCK(ccb->obj_lock);
00320         ercd  = E_OK;
00321     }
00322     else if (tmout == TMO_POL) {
00323         RELEASE_LOCK(ccb->obj_lock);
00324         ercd = E_TMOUT;
00325         
00326     }
00327     else {
00328         T_ACQUIRE_NESTED_LOCK_AND_CHECK_RUNNABLE(ccb->obj_lock);
00329         wobj_make_wait_tmout(ccb, (WOBJCB *) semcb, &winfo, &tmevtb, tmout);
00330         T_RELEASE_NESTED_LOCK(runccb->tsk_lock, ccb->obj_lock);
00331         RELEASE_LOCK(ccb->obj_lock);
00332         dispatch();
00333         ercd = winfo.winfo.wercd;
00334     }
00335     t_unlock_cpu();
00336 
00337   exit:
00338     LOG_TWAI_SEM_LEAVE(ercd);
00339     return(ercd);
00340 }
00341 
00342 #endif /* __twai_sem */

Copyright © 2006 by TAKAGI Nobuhisa.
このページは Mon Apr 3 23:49:13 2006 に Doxygen によって生成されました。