📄 semblib.c
字号:
}/********************************************************************************* semBInit - initialize a declared binary semaphore** The initialization of a static binary semaphore, or a binary semaphore* embedded in some larger object need not deal with allocation.* This routine may be called to initialize such a semaphore. The semaphore* is initialized to the specified initial state of either SEM_FULL or SEM_EMPTY.** Binary semaphore options include the queuing style for blocked tasks.* Tasks can be queued on the basis of their priority or first-in-first-out.* These options are SEM_Q_PRIORITY and SEM_Q_FIFO respectively.** SEE ALSO: semBCreate()** NOMANUAL*/STATUS semBInit ( SEMAPHORE *pSemaphore, /* pointer to semaphore to initialize */ int options, /* semaphore options */ SEM_B_STATE initialState /* initial semaphore state */ ) { if ((!semBLibInstalled) && (semBLibInit () != OK)) /* initialize package */ return (ERROR); if (semQInit (pSemaphore, options) != OK) /* initialize queue */ return (ERROR); return (semBCoreInit (pSemaphore, options, initialState)); }/********************************************************************************* semBCoreInit - initialize a binary semaphore with queue already initialized** To initialize a semaphore with some special queuing algorithm, this routine* is used. This routine will initialize a binary semaphore without* initializing the queue.** ERRNO: S_semLib_INVALID_OPTION, S_semLib_INVALID_STATE** NOMANUAL*/STATUS semBCoreInit ( SEMAPHORE *pSemaphore, /* pointer to semaphore to initialize */ int options, /* semaphore options */ SEM_B_STATE initialState /* initial semaphore state */ ) { if ((options & SEM_INVERSION_SAFE) || (options & SEM_DELETE_SAFE)) { errno = S_semLib_INVALID_OPTION; return (ERROR); } switch (initialState) { case SEM_EMPTY: pSemaphore->semOwner = taskIdCurrent; /* semaphore empty */ break; case SEM_FULL: pSemaphore->semOwner = NULL; /* semaphore full */ break; default: errno = S_semLib_INVALID_STATE; return (ERROR); } pSemaphore->recurse = 0; /* no recursive takes */ pSemaphore->options = options; /* stow away options */ pSemaphore->semType = SEM_TYPE_BINARY; /* type is binary */ eventInit (&pSemaphore->events); /* initialize events */#ifdef WV_INSTRUMENTATION /* windview - connect instrumented class for level 1 event logging */ if (wvObjIsEnabled) objCoreInit (&pSemaphore->objCore, semInstClassId); else #endif objCoreInit (&pSemaphore->objCore, semClassId); /* initialize core */ return (OK); }#ifdef semBLib_PORTABLE/********************************************************************************* semBGive - give semaphore** Gives the semaphore. If a higher priority task has already taken* the semaphore (so that it is now pended waiting for it), that task* will now become ready to run, and preempt the task that does the semGive().* If the semaphore is already full (it has been given but not taken) this* call is essentially a no-op.** NOMANUAL*/STATUS semBGive ( SEM_ID semId /* semaphore ID to give */ ) { int level = intLock (); /* LOCK INTERRUPTS */ WIND_TCB * pOwner; if (OBJ_VERIFY (semId, semClassId) != OK) { intUnlock (level); /* UNLOCK INTERRUPTS */ return (ERROR); } pOwner = semId->semOwner; if ((semId->semOwner = (WIND_TCB *) Q_FIRST (&semId->qHead)) == NULL) { int oldErrno; STATUS evStatus; STATUS retStatus; retStatus = OK; /* check change of state; if so, send events */ if ((semId->events.taskId != (int)NULL) && (pOwner != NULL)) { kernelState = TRUE; intUnlock (level); /* UNLOCK INTERRUPTS */ oldErrno = errno; evStatus = eventRsrcSend(semId->events.taskId, semId->events.registered); if (evStatus != OK) { if ((semId->options & SEM_EVENTSEND_ERR_NOTIFY) != 0x0) { retStatus = ERROR; oldErrno = S_eventLib_EVENTSEND_FAILED; } semId->events.taskId = (int)NULL; } else if ((semId->events.options & EVENTS_SEND_ONCE) != 0x0) semId->events.taskId = (int)NULL; windExit (); errno = oldErrno; return (retStatus); } else intUnlock (level); } else { kernelState = TRUE; /* KERNEL ENTER */ intUnlock (level); /* UNLOCK INTERRUPTS */#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_SEMGIVE, semId);#endif windPendQGet (&semId->qHead); /* unblock a task */ windExit (); /* KERNEL EXIT */ } return (OK); }/********************************************************************************* semBTake - take semaphore** Takes the semaphore. If the semaphore is empty, i.e., it has not been given* since the last semTake() or semInit(), this task will become pended until* the semaphore becomes available by some other task doing a semGive()* of it. If the semaphore is already available, this call will empty* the semaphore, so that no other task can take it until this task gives* it back, and this task will continue running.** WARNING* This routine may not be used from interrupt level.** NOMANUAL*/STATUS semBTake ( SEM_ID semId, /* semaphore ID to take */ int timeout /* timeout in ticks */ ) { int level; int status; if (INT_RESTRICT () != OK) return (ERROR);again: level = intLock (); /* LOCK INTERRUPTS */ if (OBJ_VERIFY (semId, semClassId) != OK) { intUnlock (level); /* UNLOCK INTERRUPTS */ return (ERROR); } if (semId->semOwner == NULL) { semId->semOwner = taskIdCurrent; /* update semaphore state */ intUnlock (level); /* UNLOCK INTERRUPTS */ return (OK); } kernelState = TRUE; /* KERNEL ENTER */ intUnlock (level); /* UNLOCK INTERRUPTS */#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_SEMTAKE, semId);#endif if (windPendQPut (&semId->qHead, timeout) != OK) { windExit (); /* KERNEL EXIT */ return (ERROR); } if ((status = windExit ()) == RESTART) /* KERNEL EXIT */ { timeout = SIG_TIMEOUT_RECALC(timeout); goto again; } return (status); }#endif /* semBLib_PORTABLE *//********************************************************************************* semBGiveDefer - give semaphore as deferred work** Gives the semaphore. If a higher priority task has already taken* the semaphore (so that it is now pended waiting for it), that task* will now become ready to run, and preempt the task that does the semGive().* If the semaphore is already full (it has been given but not taken) this* call is essentially a no-op.** NOMANUAL*/void semBGiveDefer ( SEM_ID semId /* semaphore ID to give */ ) { WIND_TCB * pOwner = semId->semOwner; if ((semId->semOwner = (WIND_TCB *) Q_FIRST (&semId->qHead)) != NULL) {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_SEMGIVE, semId);#endif windPendQGet (&semId->qHead); /* unblock a task */ } else /* check for change of state, send events if registered */ { if ((semId->events.taskId != (int)NULL) && (pOwner != NULL)) { if (eventRsrcSend(semId->events.taskId, semId->events.registered) != OK) { semId->events.taskId = (int)NULL; } else if ((semId->events.options & EVENTS_SEND_ONCE) != 0x0 ) semId->events.taskId = (int)NULL; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -