📄 semsmlib.c
字号:
** NOMANUAL*/STATUS semSmBInit ( SM_SEMAPHORE * pSem, /* pointer to semaphore to initialize */ int options, /* semaphore options */ SEM_B_STATE initialState /* initial semaphore state */ ) { Q_FIFO_G_HEAD pseudoPendQ; /* pseudo pendQ to init sem pend Q */ SM_SEMAPHORE volatile * pSemv = (SM_SEMAPHORE volatile *) pSem; int temp; /* temp storage */ if (!semSmLibInstalled) { semSmLibInit (); /* initialize package */ } if (options != SEM_Q_FIFO) /* only FIFO queuing for now */ { errno = S_semLib_INVALID_QUEUE_TYPE; return (ERROR); } pSemv->objType = htonl (SEM_TYPE_SM_BINARY); /* semaphore type is binary */ pSemv->lock = 0; /* lock available */ /* initialize pseudo multi way queue */ pseudoPendQ.pLock = NULL; /* we already have the lock */ pseudoPendQ.pFifoQ = &pSem->smPendQ; /* address of actual queue */ pseudoPendQ.pQClass = qFifoGClassId; /* global fifo multi way Q */ qFifoGInit (&pseudoPendQ); /* initialize sem pend Q */ /* fill state flag according to initial state */ switch (initialState) { case SEM_EMPTY: case SEM_FULL: pSemv->state.flag = htonl (initialState); break; default: errno = S_semLib_INVALID_STATE; return (ERROR); } /* verify field must contain the global address of semaphore */ pSemv->verify = (UINT32) htonl (LOC_TO_GLOB_ADRS (pSem)); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pSemv->lock; /* BRIDGE FLUSH [SPR 68334] */ return (OK); }/******************************************************************************* semCSmCreate - create and initialize a shared memory counting semaphore (VxMP Option)** This routine allocates and initializes a shared memory counting* semaphore. The initial count value of the semaphore is specified* by <initialCount>.** The semaphore ID returned by this routine can be used directly by the* generic semaphore-handling routines in semLib -- semGive(), semTake() and* semFlush() -- and the show routines, such as show() and semShow().** The queuing style for blocked tasks is set by <options>; the only* supported queuing style for shared memory semaphores is first-in-first-out,* selected by SEM_Q_FIFO .** Before this routine can be called, the shared memory objects facility must* be initialized (see semSmLib).** The maximum number of shared memory semaphores (binary plus counting) that* can be created is SM_OBJ_MAX_SEM , a configurable paramter.** AVAILABILITY* This routine is distributed as a component of the unbundled shared memory* support option, VxMP.* * RETURNS: The semaphore ID, or NULL if memory cannot be allocated* from the shared semaphore dedicated memory partition.** ERRNO: S_memLib_NOT_ENOUGH_MEMORY, S_semLib_INVALID_QUEUE_TYPE,* S_smObjLib_LOCK_TIMEOUT** SEE ALSO: semLib, semCLib, smObjLib, semShow,* \tb VxWorks Programmer's Guide: Basic OS** INTERNAL* The least significant bit of the semaphore ID is set to 1 in order to* differentiate shared and local semaphores.*/SEM_ID semCSmCreate ( int options, /* semaphore options */ int initialCount /* initial semaphore count */ ) { SM_SEM_ID smSemId; int temp; /* temp storage */ /* allocate semaphore structure from shared semaphore dedicated pool */ smSemId = (SM_SEM_ID) smMemPartAlloc ((SM_PART_ID) smSemPartId, sizeof (SM_SEMAPHORE)); if (smSemId == NULL) { return (NULL); } bzero ((char *) smSemId, sizeof(SM_SEMAPHORE)); /* initialize allocated semaphore */ if (semSmCInit ((SM_SEMAPHORE *) (smSemId), options, initialCount) != OK) { smMemPartFree ((SM_PART_ID) smSemPartId, (char *) smSemId); return (NULL); } /* update shared memory objects statistics */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pSmObjHdr->curNumSemC; /* PCI bridge bug [SPR 68844]*/ pSmObjHdr->curNumSemC = htonl (ntohl (pSmObjHdr->curNumSemC) + 1); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pSmObjHdr->curNumSemC; /* BRIDGE FLUSH [SPR 68334] */ return ((SEM_ID) (SM_OBJ_ADRS_TO_ID (smSemId))); }/******************************************************************************* semSmCInit - initialize a declared shared counting semaphore** The initialization of a static counting semaphore, or a shared * counting semaphore embedded in some larger object need not deal * with allocation.* This routine may be called to initialize such a semaphore. The semaphore* <pSem> is initialized to the specified <initialCount>.** Counting semaphore <options> include the queuing style for blocked tasks.* The only available pending queue type is first-in-first-out, type* SEM_Q_FIFO defined as 0 in semLib.h.** The semaphore address parameter <pSem> is the local address of a* shared semaphore data structure.** RETURNS: OK or ERROR if queue type invalid.** ERRNO: S_semLib_INVALID_QUEUE_TYPE** SEE ALSO: semCSmCreate()** NOMANUAL*/STATUS semSmCInit ( SM_SEMAPHORE * pSem, /* pointer to semaphore to initialize */ int options, /* semaphore options */ int initialCount /* initial semaphore count */ ) { Q_FIFO_G_HEAD pseudoPendQ; /* pseudo pendQ to init sem pend Q */ SM_SEMAPHORE volatile * pSemv = (SM_SEMAPHORE volatile *) pSem; int temp; /* temp storage */ if (!semSmLibInstalled) { semSmLibInit (); /* initialize package */ } if (options != SEM_Q_FIFO) /* only FIFO queuing for now */ { errno = S_semLib_INVALID_QUEUE_TYPE; return (ERROR); } pSemv->objType = htonl(SEM_TYPE_SM_COUNTING);/* fill semaphore type */ pSemv->lock = 0; /* lock available */ /* initialize pseudo multi way queue */ pseudoPendQ.pLock = NULL; /* we already have the lock */ pseudoPendQ.pFifoQ = &pSem->smPendQ; /* address of actual queue */ pseudoPendQ.pQClass = qFifoGClassId; /* global fifo multi way Q */ qFifoGInit (&pseudoPendQ); /* initialize sem pend Q */ pSemv->state.count = htonl (initialCount); /* set initial count */ /* verify field must contain the global address of semaphore */ pSemv->verify = (UINT32) htonl (LOC_TO_GLOB_ADRS (pSem)); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pSemv->lock; /* BRIDGE FLUSH [SPR 68334] */ return (OK); }/******************************************************************************* semSmGive - give shared memory binary or counting 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. If that task is local to this CPU and is of* higher priority than the task that does the semGive, it will preempt this* task. If the first pended task is located on a remote processor, the* availability of the semaphore is made known to the remote processor via* an internal notification mecanism.* * For a shared binary semaphore, if the semaphore is already full (it has* been given but not taken), this call is essentially a no-op.** For a shared counting semaphore, if the semaphore count is already* greater than 0 (semaphore was given but not taken), this call is* essentially a no-op.** The <smSemId> passed to this routine must be the local semaphore address.** This routine is usually called by semGive() which first converts the* semaphore ID to the shared semaphore local address.** WARNING* This routine may not be used from interrupt level.** RETURNS: OK or ERROR.** ERRNO: S_intLib_NOT_ISR_CALLABLE, S_objLib_OBJ_ID_ERROR,* S_smObjLib_LOCK_TIMEOUT** NOMANUAL*/STATUS semSmGive ( SM_SEM_ID smSemId /* global semaphore ID to give */ ) { Q_FIFO_G_HEAD pendQ; /* temporary pendQ to unpend task */ int level; /* processor specific inLock return value */ SM_DL_LIST eventList; /* list of events used to notify give */ SM_OBJ_TCB volatile * firstSmTcb; /* first pending shared memory tcb */ SM_SEM_ID volatile smSemIdv = (SM_SEM_ID volatile) smSemId; int temp; /* temp storage */ if (INT_RESTRICT () != OK) /* not ISR callable */ { return (ERROR); } CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = smSemIdv->verify; /* PCI bridge bug [SPR 68844]*/ if (SM_OBJ_VERIFY (smSemIdv) != OK) /* check semaphore id */ { return (ERROR); } /* ENTER LOCKED SECTION */ if (SM_OBJ_LOCK_TAKE (&smSemId->lock, &level) != OK) { smObjTimeoutLogMsg ("semGive", (char *) &smSemId->lock); return (ERROR); /* can't take lock */ } /* get first pending shared TCB */ firstSmTcb = (SM_OBJ_TCB volatile *) SM_DL_FIRST (&smSemId->smPendQ); /* pendQ is empty */ if (firstSmTcb == (SM_OBJ_TCB volatile *) LOC_NULL) { /* binary semaphore: sem available */ if (ntohl (smSemIdv->objType) == SEM_TYPE_SM_BINARY) { smSemIdv->state.flag = htonl (SEM_FULL); } /* counting semaphore: increment sem count */ else { smSemIdv->state.count = htonl (ntohl (smSemIdv->state.count) + 1); } /* EXIT LOCKED SECTION */ SM_OBJ_LOCK_GIVE (&smSemId->lock, level); return (OK); } /* pendQ is not empty, initialize pseudo multi way queue */ pendQ.pLock = NULL; /* we already have the lock */ pendQ.pFifoQ = &smSemId->smPendQ; /* address of actual queue */ pendQ.pQClass = qFifoGClassId; /* global fifo multi way Q */ /* * Do now the necessary manipulations in shared memory * in order to be able to release lock access ASAP * thus reducing interrupt latency. */ /* ENTER KERNEL */ kernelState = TRUE; /* remove from pending list */ Q_REMOVE (&pendQ, (SM_DL_NODE *) firstSmTcb); /* EXIT LOCKED SECTION */ SM_OBJ_LOCK_GIVE (&smSemId->lock, level); /* pending task is local */ if (ntohl (firstSmTcb->ownerCpu) == smObjProcNum) { /* * The shared TCB has been removed from the shared semaphore * pendQ by qFifoGRemove(), during that call removedByGive is * set to TRUE to avoid non-null notification time race. * Then, if the task that has taken the semaphore is remote, * an event notification is done and removedByGive is reset * by smObjEventProcess() on the remote processor. * If the pended task is local removedByGive must be reset * here to avoid the shared TCB being screwed up. */ firstSmTcb->removedByGive = htonl (FALSE); /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_SEMGIVE, smSemId); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = (int) firstSmTcb->localTcb; /* PCI bridge bug [SPR 68844]*/ windReadyQPut ((WIND_TCB *) ntohl ((int) firstSmTcb->localTcb)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -