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

📄 semmlib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#else    objCoreInit (&pSemaphore->objCore, semClassId);#endif    return (OK);    }#ifdef semMLib_PORTABLE/********************************************************************************* semMGive - give a 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.** If deletion safe option is enabled, an implicit taskUnsafe() operation will* occur.** If priority inversion safe option is enabled, and this is the last priority* inversion safe semaphore to be released, the calling task will revert to* its normal priority.** WARNING* This routine may not be used from interrupt level.** ERRNO: S_semLib_INVALID_OPERATION** INTERNAL* The use of the variables kernWork and semMGiveKernWork looks pretty lame.  It* is, in fact, necessary to facilitate the optimized version of this routine.* An optimized version would utilize a register for kernWork and stick the* value in semMGiveKernWork as a parameter to semMGiveKern().  This form of* parameter passing saves costly stack manipulation.** NOMANUAL*/STATUS semMGive    (    FAST SEM_ID semId   /* semaphore ID to give */    )    {    FAST int level;    FAST int kernWork = 0;    if (INT_RESTRICT () != OK)			/* restrict isr use */	return (ERROR);    level = intLock ();				/* LOCK INTERRUPTS */    if (OBJ_VERIFY (semId, semClassId) != OK)	/* check validity */	{	intUnlock (level);	return (ERROR);	}    if (taskIdCurrent != semId->semOwner)	/* check for ownership */	{	intUnlock (level);	errnoSet (S_semLib_INVALID_OPERATION);	return (ERROR);	}    if (semId->recurse > 0)			/* check recurse count */	{	semId->recurse --;			/* decrement recurse count */	intUnlock (level);	return (OK);	}    if ((semId->options & SEM_INVERSION_SAFE) &&	(-- taskIdCurrent->priMutexCnt == 0))        {	if (taskIdCurrent->priority != taskIdCurrent->priNormal)	    kernWork |= SEM_M_PRI_RESORT;	}    if ((semId->semOwner = (WIND_TCB *) Q_FIRST (&semId->qHead)) != NULL)	kernWork |= SEM_M_Q_GET;    else if (semId->events.taskId != (int)NULL)	kernWork |= SEM_M_SEND_EVENTS;    if ((semId->options & SEM_DELETE_SAFE) && 	(-- taskIdCurrent->safeCnt == 0) &&	(Q_FIRST (&taskIdCurrent->safetyQHead) != NULL))	kernWork |= SEM_M_SAFE_Q_FLUSH;    if (kernWork == 0)	{	intUnlock (level);			/* UNLOCK INTERRUPTS */	return (OK);	}    kernelState = TRUE;				/* KERNEL ENTER */    intUnlock (level);				/* UNLOCK INTERRUPTS */    semMGiveKernWork = kernWork;		/* setup the work to do */    return (semMGiveKern (semId));		/* do the work */    }/********************************************************************************* semMTake - take a 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.** If deletion safe option is enabled, an implicit taskSafe() operation will* occur.** If priority inversion safe option is enabled, and the calling task blocks,* and the priority of the calling task is greater than the semaphore owner,* the owner will inherit the caller's priority.** WARNING* This routine may not be used from interrupt level.** NOMANUAL*/STATUS semMTake    (    FAST 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 */	if (semId->options & SEM_INVERSION_SAFE)	    taskIdCurrent->priMutexCnt ++;	/* update inherit count */	if (semId->options & SEM_DELETE_SAFE)	    taskIdCurrent->safeCnt ++;		/* update safety count */	intUnlock (level);			/* UNLOCK INTERRUPTS */	return (OK);	}    if (semId->semOwner == taskIdCurrent)	/* check for recursion */	{	semId->recurse ++;			/* keep recursion count */	intUnlock (level);			/* UNLOCK INTERRUPTS */	return (OK);	}    kernelState = TRUE;				/* KERNEL ENTER */    intUnlock (level);				/* UNLOCK INTERRUPTS */	    if (semMPendQPut (semId, timeout) != OK)	{	windExit ();				/* windPendQPut failed */	return (ERROR);	}    if ((status = windExit ()) == RESTART)	/* KERNEL EXIT */	{	timeout = SIG_TIMEOUT_RECALC(timeout);	goto again;				/* we got signalled */	}    return (status);    }#endif	/* semMLib_PORTABLE *//********************************************************************************* semMGiveForce - give a mutual-exclusion semaphore without restrictions** This routine gives a mutual-exclusion semaphore, regardless of semaphore* ownership.  It is intended as a debugging aid only.** The routine is particularly useful when a task dies while holding some* mutual-exclusion semaphore, because the semaphore can be resurrected.  The* routine will give the semaphore to the next task in the pend queue or make* the semaphore full if no tasks are pending.  In effect, execution will* continue as if the task owning the semaphore had actually given the* semaphore.** CAVEATS* This routine should be used only as a debugging aid, when the condition of* the semaphore is known.** RETURNS: OK, or ERROR if the semaphore ID is invalid.** SEE ALSO: semGive()*/STATUS semMGiveForce    (    FAST SEM_ID semId   /* semaphore ID to give */    )    {    STATUS status = OK;    int oldErrno = errno;    if (INT_RESTRICT () != OK)			/* restrict isr use */	return (ERROR);    if (OBJ_VERIFY (semId, semClassId) != OK)	/* check validity */	return (ERROR);#ifdef WV_INSTRUMENTATION    /* windview - level 1 event logging */    EVT_OBJ_3 (OBJ, semId, semClassId,	       EVENT_SEMMGIVEFORCE, semId, semId->options, semId->state);#endif    /* if semaphore is not taken, nothing has to be done. */    if (semId->semOwner == NULL)	return OK;    /* first see if we are giving away one of calling task's semaphores */    if (semId->semOwner == taskIdCurrent)	/* give semaphore until avail */	{	while (semId->semOwner == taskIdCurrent)/* loop until recurse == 0 */	    semGive (semId);			/* give semaphore */	return (OK);				/* done */	}    /* give another task's semaphore away.  Djkstra be damned... */    kernelState = TRUE;				/* KERNEL ENTER */    semId->recurse = 0;				/* initialize recurse count */    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 receiver */	semId->semOwner->pPriMutex = NULL;	/* receiver no longer pended */	if (semId->options & SEM_DELETE_SAFE)	    semId->semOwner->safeCnt ++;	/* increment receiver safety */	if (semId->options & SEM_INVERSION_SAFE)	    semId->semOwner->priMutexCnt ++;	/* update inherit count */	}    else	{	if (semId->events.taskId != (int)NULL)	/* sem is free, send events */	    {	    if (eventRsrcSend (semId->events.taskId,			       semId->events.registered) != OK)		{		if ((semId->options & SEM_EVENTSEND_ERR_NOTIFY) != 0x0)		    {		    status = ERROR;		    }		semId->events.taskId = (int)NULL;		}	    else if ((semId->events.options & EVENTS_SEND_ONCE) != 0x0)		semId->events.taskId = (int)NULL;	    }	}    if (status == ERROR)	{	windExit ();			/* KERNEL EXIT */	errnoSet (S_eventLib_EVENTSEND_FAILED);	}    else	{	errnoSet (oldErrno);	return (windExit ());		/* KERNEL EXIT */	}    return (status);    }/********************************************************************************* semMGiveKern - put current task on mutex semaphore pend queue** This routine is called if something of consequence occured in giving the* mutual exclusion semaphore that involved more lengthy processing.  Things* of consequence are: task to be unblocked, priority to be uninherited, or* task safety queue of deleters to be flushed.** INTERNAL* The use of the variables kernWork and semMGiveKernWork looks pretty lame.* It is, in fact, necessary to facilitate the optimized version of this routine.* An optimized version would utilize a register for kernWork and stick the* value in semMGiveKernWork as a parameter to semMGiveKern().  This form of* parameter passing saves costly stack manipulation.** NOMANUAL*/STATUS semMGiveKern    (    FAST SEM_ID semId   /* semaphore ID to take */    )    {    STATUS evStatus;    STATUS retStatus = OK;    int oldErrno = errno;    if (semMGiveKernWork & SEM_M_Q_GET)	{#ifdef WV_INSTRUMENTATION    	/* windview - level 2 event logging */	EVT_TASK_1 (EVENT_OBJ_SEMGIVE, semId);#endif	windPendQGet (&semId->qHead);		/* unblock receiver */	semId->semOwner->pPriMutex = NULL;	/* receiver no longer pended */	if (semId->options & SEM_DELETE_SAFE)	    semId->semOwner->safeCnt ++;	/* increment receiver safety */	if (semId->options & SEM_INVERSION_SAFE)	semId->semOwner->priMutexCnt ++;	/* update inherit count */	}    if (semMGiveKernWork & SEM_M_PRI_RESORT)	{	windPrioritySet (taskIdCurrent, taskIdCurrent->priNormal);	}    if (semMGiveKernWork & SEM_M_SAFE_Q_FLUSH)	{#ifdef WV_INSTRUMENTATION    	/* windview - level 2 event logging */	EVT_TASK_1 (EVENT_OBJ_SEMGIVE, semId);#endif	windPendQFlush (&taskIdCurrent->safetyQHead);	}    if ((semMGiveKernWork & SEM_M_SEND_EVENTS) != 0x0)	/* send events */	{	evStatus = eventRsrcSend (semId->events.taskId,			          semId->events.registered);	if (evStatus != OK)	    {	    if ((semId->options & SEM_EVENTSEND_ERR_NOTIFY) != 0x0)		{		oldErrno = S_eventLib_EVENTSEND_FAILED;		retStatus = ERROR;		}	    semId->events.taskId = (int)NULL;	    }	else if ((semId->events.options & EVENTS_SEND_ONCE) != 0x0)	    semId->events.taskId = (int)NULL;	}    if (retStatus == ERROR)	{	windExit ();	errnoSet (oldErrno);	}    else	{	errnoSet (oldErrno);	retStatus = windExit ();			/* KERNEL EXIT */	}    return (retStatus);    }/********************************************************************************* semMPendQPut - put current task on mutex semaphore pend queue** This routine is called if the mutex semaphore is empty and the caller must* pend.  It is called inside the kernel with kernelState == TRUE!  It is* pulled out of semMTake so optimized versions need not bother with the* following code.** RETURNS: OK, or ERROR if windPendQPut failed.* NOMANUAL*/STATUS semMPendQPut    (    FAST SEM_ID semId,  /* semaphore ID to take */    int timeout         /* timeout in ticks */    )    {#ifdef WV_INSTRUMENTATION    /* windview - level 2 event logging */    EVT_TASK_1 (EVENT_OBJ_SEMTAKE, semId);#endif    if (windPendQPut (&semId->qHead, timeout) != OK)	return (ERROR);    /* if taskIdCurrent is of a higher priority than the task that owns     * this semaphore, reprioritize the owner.     */    if (semId->options & SEM_INVERSION_SAFE)	{	taskIdCurrent->pPriMutex = semId;	/* track mutex we pend on */        if (taskIdCurrent->priority < semId->semOwner->priority)	    {	    windPrioritySet (semId->semOwner, taskIdCurrent->priority);	    }	}    return (OK);    }

⌨️ 快捷键说明

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