⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 semsmlib.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
📖 第 1 页 / 共 3 页
字号:
* 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.* For now, the only available shared semaphore queueing style is * first-in-first-out, type SEM_Q_FIFO defined as 0 in semLib.h.** The semaphore address parameter is the local address of a shared semaphore * structure. ** RETURNS: OK, or ERROR if queue type or initial state is invalid.* * SEE ALSO: semBSmCreate** ERRNO: S_semLib_INVALID_QUEUE_TYPE, S_semLib_INVALID_STATE   ** 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 initialize sem pend Q */    if (!semSmLibInstalled)		semSmLibInit ();		/* initialize package */    if (options != SEM_Q_FIFO)		/* only FIFO queuing for now */	{	errno = S_semLib_INVALID_QUEUE_TYPE;	return (ERROR);	}    pSem->objType = htonl (SEM_TYPE_SM_BINARY);	/* semaphore type is binary */    pSem->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:            pSem->state.flag = htonl (initialState);               break;        default:            errno = S_semLib_INVALID_STATE;            return (ERROR);        }    /* verify field must contain the global address of semaphore */    pSem->verify = (UINT32) htonl (LOC_TO_GLOB_ADRS (pSem));	    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 (the number of* times the semaphore should be taken before it can be given) 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.** 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** 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;    /* allocate semaphore structure from shared semaphore dedicated pool */    smSemId = (SM_SEM_ID) smMemPartAlloc (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 (smSemPartId, (char *) smSemId);        return (NULL);        }    			/* update shared memory objects statistics */    pSmObjHdr->curNumSemC = htonl (ntohl (pSmObjHdr->curNumSemC) + 1);    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* is initialized to the specified initial count.** 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 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 initialize sem pend Q */    if (!semSmLibInstalled)        semSmLibInit ();                /* initialize package */    if (options != SEM_Q_FIFO)          /* only FIFO queuing for now */        {        errno = S_semLib_INVALID_QUEUE_TYPE;        return (ERROR);        }    pSem->objType = htonl(SEM_TYPE_SM_COUNTING);/* fill semaphore type */    pSem->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 */    pSem->state.count = htonl (initialCount);  	/* set initial count */    /* verify field must contain the global address of semaphore */    pSem->verify = (UINT32) htonl (LOC_TO_GLOB_ADRS (pSem));    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 shared binary semaphore, if the semaphore is already full (it has * been given but not taken) this call is essentially a no-op.** For 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 convert 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 */    SM_OBJ_TCB *  firstSmTcb;   /* first pending shared memory tcb */    int           level;	/* processor specific inLock return value */    SM_DL_LIST    eventList;	/* list of events used to notify give */        if (INT_RESTRICT () != OK)		/* not ISR callable */	return (ERROR);    if (SM_OBJ_VERIFY (smSemId) != 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 *) SM_DL_FIRST (&smSemId->smPendQ);    if (firstSmTcb == (SM_OBJ_TCB *) LOC_NULL)      /* pendQ is empty */	{	if (ntohl (smSemId->objType) == SEM_TYPE_SM_BINARY) 						    /* binary semaphore */	    smSemId->state.flag = htonl (SEM_FULL); /* sem available */        else 	                                    /* counting semaphore */	    					    /* increment sem count */	    smSemId->state.count = htonl (ntohl (smSemId->state.count) + 1);	SM_OBJ_LOCK_GIVE (&smSemId->lock, level);   /* EXIT LOCKED SECTION */	return (OK);	}    /* 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.     */    kernelState = TRUE;				/* ENTER KERNEL */    Q_REMOVE (&pendQ, (SM_DL_NODE *) firstSmTcb);						/* remove from pending list */    SM_OBJ_LOCK_GIVE (&smSemId->lock, level);/* EXIT LOCKED SECTION */    if (ntohl (firstSmTcb->ownerCpu) == smObjProcNum)/* pending task is local */	{	/* 	 * 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 have taken the semaphore is remote, 	 * a 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 shared TCB to be screwed up.	 */ 	firstSmTcb->removedByGive = htonl (FALSE);	/* windview - level 2 event logging */	EVT_TASK_1 (EVENT_OBJ_SEMGIVE, smSemId);	windReadyQPut ((WIND_TCB *) ntohl ((int) firstSmTcb->localTcb));	}    else					/* pending task is remote */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -