📄 semlib.c
字号:
* to run. The state of the underlying semaphore is unchanged. All* pended tasks will enter the ready queue before having a chance to* execute.** The flush operation is useful as a means of broadcast in* synchronization applications. Its use is illegal for mutual-exclusion* semaphores created with semMCreate().** RETURNS: OK, or ERROR if the semaphore ID is invalid* or the operation is not supported.** ERRNO: S_objLib_OBJ_ID_ERROR** SEE ALSO: semBLib, semCLib, semMLib, semSmLib*/STATUS semFlush ( SEM_ID semId /* semaphore ID to unblock everyone for */ ) { SM_SEM_ID smObjSemId; /* shared semaphore ID */ /* check if semaphore is global (shared) */ if (ID_IS_SHARED (semId)) { smObjSemId = (SM_SEM_ID) SM_OBJ_ID_TO_ADRS(semId); return ((*semFlushTbl[ntohl (smObjSemId->objType) &SEM_TYPE_MASK]) (smObjSemId)); } /* otherwise semaphore is local */ #ifdef WV_INSTRUMENTATION /* windview - level 1 event logging */ EVT_OBJ_4 (OBJ, semId, semClassId, EVENT_SEMFLUSH, semId, semId->state, semId->recurse, &semId->qHead);#endif if (kernelState) return (semFlushDefer (semId)); else return((* semFlushTbl[semId->semType & SEM_TYPE_MASK]) (semId)); }/********************************************************************************* semDelete - delete a semaphore** This routine terminates and deallocates any memory associated with a* specified semaphore. All tasks pending on the semaphore or pending* for the reception of events meant to be sent from the semaphore* will unblock and return ERROR.** WARNING* Take care when deleting semaphores, particularly those used for* mutual exclusion, to avoid deleting a semaphore out from under a* task that already has taken (owns) that semaphore. Applications* should adopt the protocol of only deleting semaphores that the* deleting task has successfully taken.** RETURNS: OK, or ERROR if the semaphore ID is invalid.** ERRNO:* .iP "S_intLib_NOT_ISR_CALLABLE"* Routine cannot be called from ISR.* .iP "S_objLib_OBJ_ID_ERROR"* Semaphore ID is invalid.* .iP "S_smObjLib_NO_OBJECT_DESTROY"* Deleting a shared semaphore is not permitted** SEE ALSO: semBLib, semCLib, semMLib, semSmLib*/STATUS semDelete ( SEM_ID semId /* semaphore ID to delete */ ) { return (semDestroy (semId, TRUE)); }/******************************************************************************** semTerminate - terminate a semaphore** This routine terminates a semaphore. Any pended tasks will be unblocked* and returned ERROR. Unlike semDelete(), this routine does not free any* associated memory.** RETURNS: OK, or ERROR if invalid semaphore ID.** SEE ALSO: semDelete, semBLib, semCLib, semMLib** NOMANUAL*/STATUS semTerminate ( SEM_ID semId /* semaphore ID to initialize */ ) { return (semDestroy (semId, FALSE)); }/********************************************************************************* semDestroy - destroy a semaphore** This routine underlies semDelete() and semTerminate() as the function that* terminates the semaphore and optionally deallocates memory.** RETURNS: OK, or ERROR if invalid semaphore ID.** ERRNO: S_smObjLib_NO_OBJECT_DESTROY** NOMANUAL*/STATUS semDestroy ( SEM_ID semId, /* binary semaphore to destroy */ BOOL dealloc /* deallocate memory associated with semaphore */ ) { int level; if (INT_RESTRICT () != OK) /* restrict isr use */ return (ERROR); if (ID_IS_SHARED (semId)) /* if semaphore is shared */ { errno = S_smObjLib_NO_OBJECT_DESTROY; return (ERROR); /* cannot delete shared sem. */ }#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging */ EVT_OBJ_4 (OBJ, semId, semClassId, EVENT_SEMDELETE, semId, semId->state, semId->recurse, &semId->qHead);#endif level = intLock (); /* LOCK INTERRUPTS */ if (OBJ_VERIFY (semId, semClassId) != OK) /* validate semaphore ID */ { intUnlock (level); /* UNLOCK INTERRUPTS */ return (ERROR); } objCoreTerminate (&semId->objCore); /* INVALIDATE */ kernelState = TRUE; /* KERNEL ENTER */ intUnlock (level); /* UNLOCK INTERRUPTS */ windSemDelete (semId); /* unblock any pending tasks */ eventTerminate (&semId->events); /* unblock task waiting for events*/ TASK_SAFE (); /* TASK SAFE */ windExit (); /* EXIT KERNEL */ if (dealloc) /* dealloc memory if selected */ objFree (semClassId, (char *) semId); TASK_UNSAFE (); /* TASK UNSAFE */ return (OK); }/********************************************************************************* semGiveDefer - add appropriate semGive routine to kernel work q** This routine defers the work of giving a semaphore by adding the work to the* kernel work queue. If the semaphore ID is invalid or the semaphore type is* is inheritance this routine will return ERROR, otherwise OK.** ERRNO: S_intLib_NOT_ISR_CALLABLE** NOMANUAL*/STATUS semGiveDefer ( SEM_ID semId /* semaphore ID to give */ ) { if (OBJ_VERIFY (semId, semClassId) != OK) /* verify semaphore */ return (ERROR); if (semGiveDeferTbl [semId->semType] == NULL) { errno = S_intLib_NOT_ISR_CALLABLE; return (ERROR); } workQAdd1 (semGiveDeferTbl [semId->semType], (int) semId); return (OK); }/********************************************************************************* semFlushDefer - add appropriate semFlush routine to kernel work q** This routine defers the work of giving a semaphore by adding the work to the* kernel work queue. If the semaphore ID is invalid or the semaphore type is* is inheritance this routine will return ERROR, otherwise OK.** RETURNS: OK or ERROR** ERRNO: S_intLib_NOT_ISR_CALLABLE** NOMANUAL*/STATUS semFlushDefer ( SEM_ID semId /* semaphore ID to give */ ) { if (OBJ_VERIFY (semId, semClassId) != OK) /* verify semaphore */ return (ERROR); if (semFlushDeferTbl [semId->semType] == NULL) { errno = S_intLib_NOT_ISR_CALLABLE; return (ERROR); } workQAdd1 (semFlushDeferTbl [semId->semType], (int) semId); return (OK); }/******************************************************************************** semInvalid - invalid semaphore ID or operation** RETURNS: ERROR with appropriate errno.** ERROR: S_semLib_INVALID_OPERATION* NOMANUAL*/STATUS semInvalid ( SEM_ID semId /* semId of invalid operation */ ) { if (OBJ_VERIFY (semId, semClassId) != OK) /* verify semaphore */ return (ERROR); errno = S_semLib_INVALID_OPERATION; /* set errno */ return (ERROR); }/******************************************************************************** semIntRestrict - operation restricted from ISR use** NOMANUAL* ARGSUSED*/STATUS semIntRestrict ( SEM_ID semId /* semId of invalid operation */ ) { return (INT_RESTRICT ()); /* restrict ISR use */ }/******************************************************************************** semQInit - inialize the semaphore queue to the specified queue type** This routine initialized the semaphore queue to the specified type.** RETURNS: OK, or ERROR if queue type not supported.** ERRNO S_semLib_INVALID_QUEUE_TYPE** NOMANUAL*/STATUS semQInit ( SEMAPHORE *pSemaphore, /* semphore core to initialize queue for */ int options /* semphore options */ ) { STATUS status = OK; switch (options & SEM_Q_MASK) { case SEM_Q_FIFO: qInit (&pSemaphore->qHead, Q_FIFO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break; case SEM_Q_PRIORITY: qInit (&pSemaphore->qHead, Q_PRI_LIST, 0, 0, 0, 0, 0, 0, 0, 0, 0,0); break; default: errno = S_semLib_INVALID_QUEUE_TYPE; /* set errno */ status = ERROR; break; } return (status); }/********************************************************************************* semQFlush - unblock all tasks pending on this semaphore** Unblock pending tasks. 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 semQFlush ( SEM_ID semId /* semaphore ID to give */ ) { int level = intLock (); /* LOCK INTERRUPTS */ if (OBJ_VERIFY (semId, semClassId) != OK) { intUnlock (level); /* UNLOCK INTERRUPTS */ return (ERROR); } if (Q_FIRST (&semId->qHead) == NULL) { intUnlock (level); /* UNLOCK INTERRUPTS */ } else { kernelState = TRUE; /* KERNEL ENTER */ intUnlock (level); /* UNLOCK INTERRUPTS */#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_SEMFLUSH, semId);#endif windPendQFlush (&semId->qHead); /* flush blocked tasks */ windExit (); /* KERNEL EXIT */ } return (OK); }/********************************************************************************* semQFlushDefer - unblock pending tasks as deferred work** Unblock pending tasks. 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 semQFlushDefer ( SEM_ID semId /* semaphore ID to give */ ) { if (Q_FIRST (&semId->qHead) != NULL) {#ifdef WV_INSTRUMENTATION /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_SEMFLUSH, semId);#endif windPendQFlush (&semId->qHead); /* flush blocked tasks */ } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -