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

📄 trglib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	           default:                       intUnlock(level);		       return(FALSE);	           }	    case TRIGGER_LEQ: 	       switch (pTrg->condType)	           {	           case TRIGGER_COND_VAR:                        retval = ((* ((BOOL *)pTrg->condEx1) <= pTrg->condEx2));                       intUnlock(level);                       return(retval);	           case TRIGGER_COND_FUNC:		       retval = (((* ((FUNCPTR)pTrg->condEx1)) () <= pTrg->condEx2));                       intUnlock(level);                       return(retval);	           default:                       intUnlock(level);		       return(FALSE);	           }	    case TRIGGER_OR: 	       switch (pTrg->condType)	           {	           case TRIGGER_COND_VAR:                        retval = ((* ((BOOL *)pTrg->condEx1) || pTrg->condEx2));                       intUnlock(level);                       return(retval);	           case TRIGGER_COND_FUNC:		       retval = (((* ((FUNCPTR)pTrg->condEx1)) () || pTrg->condEx2));                       intUnlock(level);                       return(retval);	           default:                       intUnlock(level);		       return(FALSE);	           }	    case TRIGGER_AND: 	       switch (pTrg->condType)	           {	           case TRIGGER_COND_VAR:                        retval = ((* ((BOOL *)pTrg->condEx1) && pTrg->condEx2));                       intUnlock(level);                       return(retval);	           case TRIGGER_COND_FUNC:		       retval = (((* ((FUNCPTR)pTrg->condEx1)) () && pTrg->condEx2));                       intUnlock(level);                       return(retval);	           default:                       intUnlock(level);		       return(FALSE);	           }	    default:               intUnlock(level);	       return (FALSE);	    }    intUnlock(level);    }/********************************************************************************* trgActionPerform - perform the action associated to a trigger ** INTERNAL* FIXME** RETURNS: * SEE ALSO: FIXME()* NOMANUAL*/void trgActionPerform    (    TRIGGER_ID pTrg    )    {    switch (pTrg->actionType)       {       case TRG_ACT_WV_START:       case TRG_ACT_WV_STOP:       case TRG_ACT_FUNC:           if ( pTrg->actionFunc != NULL)               {               (* (pTrg->actionFunc)) (pTrg->actionArg);               }       }    }/********************************************************************************* trgActionDefPerform - perform the trigger action in deferred mode** INTERNAL* FIXME** RETURNS: * SEE ALSO: FIXME()* NOMANUAL*/STATUS trgActionDefPerform ()    {    /* loop, executing actions and pending on the next request */    if ((trgDefSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY)) == NULL)        {        return (ERROR);        }    while (TRUE)        {         semTake (trgDefSem, WAIT_FOREVER);  /* pend on event semaphore */	if ( trgWorkQFullNotify )	    {            logMsg ("Error: Triggering Work Queue overflow! \n",		     0,0,0,0,0,0);	    trgWorkQFullNotify = FALSE;	    }	while (TRUE)	    {	    if (trgWorkQ[trgWorkQReader] != NULL)		{		/* there is an entry here on the queue. Process it */		trgActionPerform ((TRIGGER_ID)trgWorkQ[trgWorkQReader]);		trgWorkQ[trgWorkQReader] = NULL;		}	    else		{		if (trgWorkQReader == trgWorkQWriter)		    {		    /*		     * this entry is marked as unused and the read pointer		     * has caught up the write pointer. The queue is now		     * empty		     */		    break; /* exit the inner loop */		    }		}	    /* increment the read pointer so it remains valid at all times */	    if (trgWorkQReader >= (TRG_MAX_REQUESTS - 1))		trgWorkQReader = 0;	    else		trgWorkQReader++;	    }        }     /* never returns */    return (OK);    }  /********************************************************************************* trgCheck - check if there is a trigger associated to the event** INTERNAL** This routine is the core of the triggering mechanism. It is called whenever* an event point is hit. It determines if a trigger exists for this event and* performs the action associated to the trigger. In order to verify a trigger* has been set for the event point, the routine performs the following steps:*  - selects the trigger list the event belongs to, so not to look for all*     triggers. Triggers are divided in different lists, depending on the class*     they belong to. Classes are similar but not identical to the Windview ones.*  - verifies the trigger is a valid object*  - verifies the type of event matches the trigger event id*  - verifies the object ID of the event point (if any) matches the one defined*    in the trigger (if any)*  - check the contect we are in is the same as the one specified in the trigger.*    Contexts can be of the following type: ANY, ANY_TASK, TASK, SYSTEM, ANY_ISR.*  - if a condition is also defined for the trigger, it checks it is verified.*    Conditions, can be a function, a var or a library function. They can use*    different operands (==, !=, >, <, ...) and are matched against a value*  - if we ever get here, well, we have hit a trigger! At this point 3 things,*    not necessarily mutually exclusive can happen:*        . disable the current trigger (we want the action performed only once)*        . perform an action*        . enable a chained trigger (similar to a state machine)** The action can be either a user/system defined routine or a library (such* as WV_START/STOP). Action axecution represent the most complex part of the* triggering mechanism. Event points are often set in critical regions of the* kernel where the number of actions that can be performed is limited. In order* to avoid conflicts and still allow the user full range of action, we have * provided a deferred execution mode. In this way, when an action should be * performed a request is sent to a task. Therefore the action itself will not be* executed in the context where the event happens, but in a safer one. If a user* really needs the action to be performed on the spot, this mode can be switched* off. The way the deferred mode is implemented represent the critical part of* the code, and it is still a work in progress.* The first approach we followed was to use message queues. It logically satisfies* the need we had to send information to a task pending waiting for it.* The implementation of this approach raised a few issues:*    - recursion: msgQSend/Receive (directly and indirectly) refer to several event*      points. Things get worse if a trigger is set on one of them. First of all,*      we are introducing a form of intrusion, since the triggers will be fired on*      events generated by the trigger itself. More than that, if triggers are not*      disabled, it will go into a loop.*    - context switch: msgQSend can generate a context switch, which is not the most*      desirable thing.*    - queue does not work well with interrupts: if we are in an interrupt we can not*      use the WAITFOREVER option. This will generate potential inconsistency in the*      queue.* * A second approach was to put a task on the workQueue, using workQAdd, but this will * cause the execution of the action when we are doing windExit.* A solution to this problem would be to add some "harmless" action in the workQueue, * that does not cause context switch, and eventually will wake up the task. Therefore,* the idea of semBGiveDefer. The problem now is to tell the pending task what to do.* This is solved by putting the request into a triggering work queue.* This is the current implementation. The work queue mechanism needs definitely to be* revised. Atthe moment it could cause starvation. The requests are executed from the* top of the list down, but a new request will be put at the top of the list, even if* the list is not empty. This could be solved by using a rotation mechanism, so that * request are alway put at the end of the queue. This part has not been implemented yet.** It requires two arguments and a few optional ones.** RETURNS:* SEE ALSO: FIXME()* NOMANUAL*/void trgCheck    (    event_t event,    int	    index,    int     obj,      int     arg1,    int     arg2,    int     arg3,    int     arg4,    int     arg5    )    {    TRIGGER_ID pTrg = NULL;     int level;    int any = 0;    pTrg = trgList[index];restart:    if (index == TRG_CLASS_3_ON)	trgNone = 20;    while (pTrg != NULL)         { 	if (OBJ_VERIFY (pTrg, trgClassId) != OK)	    pTrg = pTrg->next;	else if ( pTrg->status != TRG_ENABLE )	    pTrg = pTrg->next;	else if ((pTrg->eventId != EVENT_ANY_EVENT) && 	         (pTrg->eventId != event) )	    pTrg = pTrg->next;	else if ((pTrg->objId != NULL) && (((OBJ_ID)obj != NULL) &&	         ((OBJ_ID)obj != pTrg->objId)) )	    pTrg = pTrg->next;        else	    {            switch ( pTrg->contextType )	        {	        case TRG_CTX_ANY:	            break;	        case TRG_CTX_SYSTEM:	            if (kernelState) 	                break;	            else	                goto end;	        case TRG_CTX_TASK:	            if ((!kernelState) && (!INT_CONTEXT ()) &&	                 ((WIND_TCB *)(pTrg->contextId) == taskIdCurrent) )		        break;		    else		        goto end;	        case TRG_CTX_ANY_TASK:		    if ((!kernelState) && (!INT_CONTEXT ())) 		        break;		    else		        goto end;	        case TRG_CTX_ISR:	        case TRG_CTX_ANY_ISR:		    if (INT_CONTEXT ())		        break;		    else		        goto end;	        default:		        goto end;	        }            /* check if it is a conditional trigger and in case             * test the condition             */            if ((pTrg->conditional == TRIGGER_COND_YES) &&                 (pTrg->condEx1 != NULL) && (trgCondTest(pTrg,obj) == FALSE))                        goto end;            level = intLock();            /* disable the current trigger, if requested */            if ((pTrg->disable == TRUE) && (trgDisable(pTrg) == ERROR))                {                intUnlock(level);                goto end;                }            intUnlock(level);            pTrg->hitCnt++;	    /* perform the action associated with the trigger, if any */            if ( pTrg->actionType != TRG_ACT_NONE )	        {		if ( pTrg->actionDef == FALSE )                    trgActionPerform(pTrg);		else /* defer the action */		    {		    /*		     * This will put a request in the triggering work queue		     * and release a semaphore so that the task trgActDef		     * can execute the request once we are out of this		     * code. We might be in Kernel state and we do not want		     * to perform action here, if possible.		     */		    level = intLock();		    if ( trgWorkQ[trgWorkQWriter] == NULL )			{		        trgWorkQ[trgWorkQWriter] = pTrg;			/*			 * Increment the writer index.			 * Ensure that trgWorkQWriter NEVER goes to an invalid			 * value when wrapping round. This assurance is needed			 * in the trgActDef task			 */			if (trgWorkQWriter >= (TRG_MAX_REQUESTS - 1))		            trgWorkQWriter = 0;			else			    trgWorkQWriter++;			}		    else		 	{			/* If the workQ is full need to stop triggering */			trgWorkQFullNotify = TRUE;			trgOff();		    	intUnlock(level);			return ;			}			#if (CPU_FAMILY == I80X86)                    portWorkQAdd1((FUNCPTR)semBGiveDefer,                                  (int)trgDefSem);#else                    workQAdd1((FUNCPTR)semBGiveDefer,                              (int)trgDefSem);#endif /* CPU_FAMILY == I80X86 */		    intUnlock(level);		    }		 }            /* check if there is any trigger chained to the current             * one, and if any, enable it	    if (OBJ_VERIFY (&(pTrg->chain), trgClassId) == OK)             */            if ( pTrg->chain != NULL )	        {                trgEnable(pTrg->chain);		if (!TRG_ACTION_IS_SET)		    trgOn();		}                 	    /* 	     * let's loop for the next one!             */end:	    pTrg = pTrg->next;	    }        }    if ((any == 0) && (trgList[TRG_ANY_EVENT_INDEX] != NULL))        {	any = 1;    	pTrg = trgList[TRG_ANY_EVENT_INDEX];	goto restart;	}    }/* Conditional library fn */int isTaskNew(int taskId, int arg){    REG_SET regs;    /* Load the regs of the task being resumed */    taskRegsGet (taskId,&regs);    /* Compare the current PC with the initial entry point */#if 0logMsg("entry = %p, pc = %p\n",((WIND_TCB *) taskId)->entry,regs.pc,0,0,0,0);#endif    if ((FUNCPTR) regs.pc == (FUNCPTR) vxTaskEntry)        {        /*         *  Task is at entry point, we can therefore deduce it has         *  just been created.         */        /* now match actual user entry point */        if((int) ((WIND_TCB *) taskId)->entry != 0 &&           (int) ((WIND_TCB *) taskId)->entry == arg)            {            /* Suspend the task! */#if 0logMsg ("Suspending task %p\n",taskId);#endif#if 1#if (CPU_FAMILY == I80X86)            portWorkQAdd1 ((FUNCPTR)taskSuspend, taskId);#else            workQAdd1 ((FUNCPTR)taskSuspend, taskId);#endif /* CPU_FAMILY == I80X86 */#else            excJobAdd ((VOIDFUNCPTR)taskSuspend, taskId,0,0,0,0,0);#endif            return (TRUE);            }        else            {            /* This is not the entry point of interest */            return (FALSE);            }        }    else        {        /*         *  Task is been resumed after running on from entry point.         */        return (FALSE);        }}/********************************************************************************* trgEvent - trigger a user-defined event ** This routine triggers a user event. A trigger must exist and triggering must * have been started with trgOn() or from the triggering GUI to use this routine.  * The <evtId> should be in the range 40000-65535. * * RETURNS: N/A** SEE ALSO: dbgLib, e()** INTERNAL**/void trgEvent    (    event_t    evtId      /* event */    )    {    trgCheck (evtId, TRG_USER_INDEX, 0, 0, 0, 0, 0, 0);    }

⌨️ 快捷键说明

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