|
|
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 によって生成されました。 |