trgLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:39k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* trgLib.c - trigger events control library  */
  2. /* Copyright 1994-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01x,21mar02,tcr  Fix SPR 74465
  8. 01w,11oct01,tcr  Fix SPR 70133 - trigger action routine cannot take
  9.                  zero-valued argument
  10. 01v,02mar99,dgp  removed reference to e() from trgEvent()
  11. 01u,11sep98,cjtc deferred action queue for triggering modified
  12. 01t,28aug98,dgp  FCS man page edit
  13. 01s,28may98,dgp  final doc editing for WV 2.0 beta
  14. 01r,07may98,dgp  clean up man pages for WV 2.0 beta release
  15. 01q,08apr98,pr   added some comments and some cleanup
  16. 01p,25mar98,pr   deleted portWorkQAdd1 (see rBuffLib.c)
  17. 01p,25mar98,pr   added trgEvent function
  18. 01o,22mar98,pr   replaced workQAdd1 with portable version 
  19. 01n,21feb98,pr   commented out hitCnt reset in trgOn. Fix obj enable in 
  20.  trgCheck.
  21. 01m,22feb98,pr   added hitCnt. Cleanup
  22. 01l,13feb98,nps  made trgDelete more defensive by verifying object exists.
  23. 01k,12feb98,pr   moved trgShow to trgShow.c. Added hitCnt support.
  24. 01j,27jan98,nps  Fix merge errors.
  25. 01i,27jan98,nps  modified switch so all current deferred actions are
  26.                  handled in the same way.
  27.                  incorporated support for library condition fns.
  28. 01h,23jan98,pr   moved _func_trgCheck initialization, replaced macro names.
  29. 01g,16jan98,pr   modified option for msgQSend. 
  30. 01f,14dec97,pr   moved declaration of some global variables into funcBind.c
  31. 01e,14dec97,pr   deleted reference to myCnt
  32. 01d,13dec97,pr   deleted some temporary variables. Reduced the number of
  33.  arguments passed to trgCheck
  34. 01c,20nov97,pr   added the deferred execution of tasks, fixed some bugs
  35.                  added trgChainSet, trgAddTcl
  36.                  modified trgCondTest, added support for EVENT_ANY_EVENT
  37. 01b,09oct97,pr   modified the prototype: changed the structure in an obj
  38.    replaced the list with an array
  39.  modified the search algorithm
  40. 01a,25jun97,pr   written
  41. */
  42. /*
  43. DESCRIPTION
  44. This library provides the interface for triggering events.  The routines
  45. provide tools for creating, deleting, and controlling triggers.  However,
  46. in most cases it is preferable to use the GUI to create and manage
  47. triggers, since all order and dependency factors are automatically
  48. accounted for there.
  49. The event types are defined as in WindView. Triggering and WindView share
  50. the same instrumentation points. Furthermore, one of the main uses of
  51. triggering is to start and stop WindView instrumentation.  Triggering is
  52. started by the routine trgOn(), which sets the shared variable 'evtAction'.
  53. Once the variable is set, when an instrumented point is hit, trgCheck() is
  54. called. The routine looks for triggers that apply to this event.  The
  55. routine trgOff() stops triggering.  The routine trgEnable() enables a
  56. specific trigger that was previously disabled with trgDisable(). (At
  57. creation time all triggers are enabled by default.) This routine also
  58. checks the number of triggers currently enabled, and when this is zero, it
  59. turns triggering off.
  60. NOTE: It is important to create a trigger before calling trgOn(). trgOn()
  61. checks the trigger list to see if there is at least one trigger there, and if
  62. not, it exits without setting 'evtAction'.
  63. INCLUDE FILES: trgLibP.h
  64. SEE ALSO: 
  65. .I WindView User's Guide
  66. */
  67. #include "vxWorks.h"
  68. #include "intLib.h"
  69. #include "taskLib.h"
  70. #include "stdio.h"
  71. #include "logLib.h"
  72. #include "private/trgLibP.h"
  73. #include "private/kernelLibP.h"
  74. #include "private/windLibP.h"
  75. #include "private/workQLibP.h"
  76. /* extern */
  77. extern int trgCnt;
  78. int trgNone;
  79. extern  VOIDFUNCPTR _func_trgCheck;
  80. #if (CPU_FAMILY == I80X86)
  81. extern  void portWorkQAdd1();
  82. #endif /* CPU_FAMILY == I80X86 */
  83. /* global */
  84. UINT  trgWorkQReader; /* work queue index */
  85. UINT  trgWorkQWriter; /* work queue index */
  86. BOOL trgWorkQFullNotify; /* work queue full notification*/
  87. SEM_ID trgDefSem;
  88. OBJ_CLASS trgClass;                   /* trg object Class */
  89. CLASS_ID  trgClassId = &trgClass;     /* trg class ID */
  90. MSG_Q_ID trgActionDefMsgQId = NULL;
  91. UINT32 trgClassList[] = {TRG_CLASS_1, TRG_CLASS_2, TRG_CLASS_3, TRG_CLASS_4, TRG_CLASS_5, TRG_CLASS_6};
  92. /* local */
  93. TRIGGER_ID  trgWorkQ[TRG_MAX_REQUESTS];
  94. TRIGGER_ID  * trgList;
  95. LOCAL BOOL trgLibInstalled = FALSE;   /* protect from multiple inits */
  96. LOCAL BOOL trgActionDefStarted = FALSE;   /* protect from multiple inits */
  97. void trgCheck(event_t event, int index, int obj,int arg1,int arg2,int arg3,int arg4,int arg5);
  98. TRIGGER_ID trgAdd(event_t event, int status, int contextType, UINT32 contextId, 
  99.                   OBJ_ID  objId, int conditional, int condType, int * condEx1, 
  100.   int condOp, int condEx2, BOOL disable, TRIGGER_ID chain, 
  101.   int actionType, FUNCPTR actionFunc, BOOL actionDef, int arg);
  102. STATUS trgInit();
  103. STATUS trgDelete(TRIGGER_ID trgId);
  104. void trgOff();
  105. /*******************************************************************************
  106. *
  107. * trgLibInit - initialize the triggering library
  108. *
  109. * This routine initializes the trigger class. Triggers are VxWorks objects 
  110. * and therefore require a class to be initialized.
  111. *
  112. * RETURNS: OK or ERROR.
  113. *
  114. */
  115. STATUS trgLibInit (void)
  116.     {
  117.     int index;
  118.     if ((!trgLibInstalled) &&
  119.         (classInit (trgClassId, sizeof(TRIGGER),
  120.                     OFFSET(TRIGGER, objCore), (FUNCPTR) trgAdd,
  121.                     (FUNCPTR) trgInit, (FUNCPTR) trgDelete) == OK))
  122.         {
  123.         trgList = (TRIGGER_ID *)malloc (sizeof(TRIGGER_ID)*TRG_MAX_REQUESTS );
  124. if ( trgInit() != OK)
  125.     return(ERROR);
  126. trgWorkQFullNotify   = FALSE;
  127.         trgWorkQReader = 0;
  128.         trgWorkQWriter = 0;
  129.         for (index = 0 ; index < TRG_MAX_REQUESTS ; index ++)
  130.             trgWorkQ[index] = NULL;
  131.         trgLibInstalled = TRUE;
  132.         }
  133.     return ((trgLibInstalled) ? OK : ERROR);
  134.     }
  135. /*******************************************************************************
  136. *
  137. * trgInit - Initializes triggering list and function
  138. *
  139. * initialize/reset the list and the _func_trgCheck pointer
  140. *
  141. * NOMANUAL
  142. *
  143. */
  144. STATUS trgInit ()
  145.     {
  146.     int index;
  147.     if ( trgList == NULL )
  148. return(ERROR);
  149.     for (index = 0 ; index < TRG_MAX_REQUESTS ; index ++)
  150.         trgList[index] = NULL;
  151.     /* set the function for the event points */
  152.     _func_trgCheck = (VOIDFUNCPTR) trgCheck;
  153.     return(OK);                         
  154.     }
  155. /*******************************************************************************
  156. *
  157. * trgActionDefInit - Initializes the daemon for deferred execution of tasks
  158. *
  159. * Tasks can be executed in deferred mode (this is the default). That is, if
  160. * they are in a critical part of the code (i.e. Kernel state) their execution
  161. * does not occur until they are out of the critical code.
  162. * This task will initialize the task for the deferred execution, 
  163. * trgActionDefPerform.
  164. *
  165. * NOMANUAL
  166. *
  167. */
  168. STATUS trgActionDefStart ()
  169.     {
  170.     if ( trgActionDefStarted == TRUE)
  171. return (OK);
  172.     if ((!trgLibInstalled) && (trgLibInit () != OK))
  173.         return (ERROR);
  174.     taskSpawn ("trgActDef",
  175.          TRG_ACT_PRIORITY,
  176.          TRG_ACT_OPTIONS,
  177.          TRG_ACT_SIZE,
  178.          trgActionDefPerform,
  179.          0,0,0,0,0,0,0,0,0,0);
  180.     trgActionDefStarted = TRUE;
  181.     return (OK);
  182.     }
  183. /*******************************************************************************
  184. *
  185. * trgWorkQReset - Resets the trigger work queue task and queue
  186. *
  187. * When a trigger fires, if the assocated action requires a function to be called
  188. * in "safe" mode, a pointer to the required function will be placed on a queue
  189. * known as the "triggering work queue". A system task "tActDef" is spawned to
  190. * action these requests at task level. Should the user have need to reset this
  191. * work queue (e.g. if a called task causes an exception which causes the
  192. * trgActDef task to be SUSPENDED, or if the queue gets out of sync and becomes
  193. * unresponsive), trgWorkQReset() may be called.
  194. *
  195. * Its effect is to delete the trigger work queue task and its associated 
  196. * resources and then recreate them. Any entries pending on the triggering work
  197. * queue will be lost. Calling this function with triggering on will result in
  198. * triggering being turned off before the queue reset takes place. It is the
  199. * responsibility of the user to turn triggering back on.
  200. *
  201. * RETURNS: OK, or ERROR if the triggering task and its associated resources
  202. * cannot be deleted and recreated.
  203. *
  204. */
  205. STATUS trgWorkQReset (void)
  206.     {
  207.     int index;
  208.     if ((!trgLibInstalled) && (trgLibInit () != OK))
  209.         return (ERROR);                         
  210.     if (TRG_ACTION_IS_SET)
  211.         trgOff();
  212.     if (trgActionDefStarted != TRUE)
  213. return OK;
  214.     if (taskDelete (taskNameToId ("trgActDef")) == ERROR)
  215. return ERROR;
  216.     trgActionDefStarted = FALSE;
  217.     if (semDelete (trgDefSem) == ERROR)
  218. return ERROR;
  219.     /* re-initialise the work queue */
  220.     trgWorkQFullNotify   = FALSE;
  221.     trgWorkQReader = 0;
  222.     trgWorkQWriter = 0;
  223.     for (index = 0 ; index < TRG_MAX_REQUESTS ; index ++)
  224.         trgWorkQ[index] = NULL;
  225.     /* restart the work queue task */
  226.     return (trgActionDefStart ());
  227.     }
  228. /*******************************************************************************
  229. *
  230. * trgEvtToIndex - calculate the list the trigger belongs to given the event ID 
  231. *
  232. * The routine returns the index of the list where the trigger belongs to. The
  233. * index are based on WindView event type classification.
  234. *
  235. * NOMANUAL
  236. *
  237. */
  238. int trgEvtToIndex 
  239.     (
  240.     event_t event
  241.     )
  242.     {
  243.     if (event == EVENT_ANY_EVENT)
  244. return(TRG_ANY_EVENT_INDEX);
  245.     if (IS_CLASS1_EVENT(event))
  246. return(TRG_CLASS1_INDEX);
  247.     if (IS_CLASS2_EVENT(event))
  248. return(TRG_CLASS2_INDEX);
  249.     if (IS_CLASS3_EVENT(event))
  250. return(TRG_CLASS3_INDEX);
  251.     if (IS_USER_EVENT(event))
  252. return(TRG_USER_INDEX);
  253. /* this is probably never reached, since it is a subclass of class1 */
  254.     if (IS_INT_ENT_EVENT(event))
  255. return(TRG_INT_ENT_INDEX);
  256. #if 0
  257.     if (IS_CONTROL_EVENT(event))
  258. return(TRG_CONTROL_INDEX);
  259. #endif
  260.     return(ERROR);
  261.     }
  262. /*******************************************************************************
  263. *
  264. * trgAddTcl - calls trgAdd but accepts one single parameter
  265. *
  266. * Since Tcl does not take more than 10 parameters, they have been saved in one
  267. * memory location. This routine retrieves the values and passes them to trgAdd.
  268. *
  269. * NOMANUAL
  270. *
  271. */
  272. TRIGGER_ID trgAddTcl
  273.     (
  274.     char *  buff 
  275.     )
  276.     {
  277.     int * buffIndex = (int *)buff;
  278.     int         event;
  279.     int         status;
  280.     int         conditional;
  281.     int         condType, contextType, actionType;
  282.     int         * condEx1, condOp, condEx2;
  283.     int         actionArg;
  284.     UINT32      contextId;
  285.     OBJ_ID      objId;
  286.     BOOL        disable, actionDef;
  287.     FUNCPTR     actionFunc;
  288.     TRIGGER     *chain;
  289.     event = (int) *buffIndex++;
  290.     status = (int) *buffIndex++;
  291.     contextType = (int) *buffIndex++;
  292.     contextId = (UINT32) *buffIndex++;
  293.     objId = (OBJ_ID) *buffIndex++;
  294.     conditional = (int) *buffIndex++;
  295.     condType = (int) *buffIndex++;
  296.     condEx1 = (int *) *buffIndex++;
  297.     condOp = (int) *buffIndex++;
  298.     condEx2 = (int) *buffIndex++;
  299.     disable = (BOOL) *buffIndex++;
  300.     chain = (TRIGGER *) *buffIndex++;
  301.     actionType = (int) *buffIndex++;
  302.     actionFunc = (FUNCPTR) *buffIndex++;
  303.     actionDef = (BOOL) *buffIndex++;
  304.     actionArg = (int) *buffIndex;
  305. #if 0
  306.  printf ("event = %hd n", (event_t)event);
  307.  printf(" %dn", status);
  308.  printf(" %d n", contextType);
  309.  printf(" %dn", contextId);
  310.  printf(" %pn", objId);
  311.  printf(" %dn", conditional);
  312.  printf("%d n", condType);
  313.  printf(" %pn", condEx1);
  314.  printf(" %dn", condOp);
  315.  printf(" %dn", condEx2);
  316.  printf(" %dn", disable);
  317.  printf(" %pn", chain);
  318.  printf(" %dn", actionType);
  319.  printf(" %pn", actionFunc);
  320.  printf(" %dn", actionDef);
  321.  printf(" %dn", actionArg);
  322. #endif
  323.     return (trgAdd ( (event_t)event, status, contextType, contextId, objId, conditional, 
  324.         condType, condEx1, condOp, condEx2, disable, chain, actionType, 
  325.         actionFunc, actionDef, actionArg ));
  326.     }
  327.  
  328. /*******************************************************************************
  329. *
  330. * trgAdd - add a new trigger to the trigger list
  331. *
  332. * This routine creates a new trigger and adds it to the proper trigger list.  It
  333. * takes the following parameters:
  334. * .iP <event> 50
  335. * as defined in eventP.h for WindView, if given.
  336. * .iP <status>
  337. * the initial status of the trigger (enabled or disabled).
  338. * .iP <contextType>
  339. * the type of context where the event occurs.
  340. * .iP <contextId>
  341. * the ID (if any) of the context where the event occurs.
  342. * .iP <objectId>
  343. * if given and applicable.
  344. * .iP <conditional>
  345. * the indicator that there is a condition on the trigger.
  346. * .iP <condType>
  347. * the indicator that the condition is either a variable or a function.
  348. * .iP <condEx1>
  349. * the first element in the comparison.
  350. * .iP <condOp>
  351. * the type of operator (==, !=, <, <=, >, >=, |, &).
  352. * .iP <condEx2>
  353. * the second element in the comparison (a constant).
  354. * .iP <disable>
  355. * the indicator of whether the trigger must be disabled once it is hit.
  356. * .iP <chain>
  357. * a pointer to another trigger associated to this one (if any).
  358. * .iP <actionType>
  359. * the type of action associated with the trigger (none, func, lib).
  360. * .iP <actionFunc>
  361. * the action associated with the trigger (the function).
  362. * .iP <actionDef>
  363. * the indicator of whether the action can be deferred (deferred is the default).
  364. * .iP <actionArg>
  365. * the argument passed to the function, if any.
  366. * .LP
  367. *
  368. * Attempting to call trgAdd whilst triggering is enabled is not allowed
  369. * and will return NULL.
  370. *
  371. * RETURNS: TRIGGER_ID, or NULL if either the trigger ID can not be allocated,
  372. * or if called whilst triggering is enabled.
  373. *
  374. * SEE ALSO: trgDelete()
  375. */
  376. TRIGGER_ID trgAdd 
  377.     (
  378.     event_t  event, 
  379.     int  status,
  380.     int  contextType,
  381.     UINT32  contextId,
  382.     OBJ_ID   objId, 
  383.     int     conditional, 
  384.     int     condType, 
  385.     int * condEx1, 
  386.     int condOp, 
  387.     int condEx2, 
  388.     BOOL   disable, 
  389.     TRIGGER *chain, 
  390.     int  actionType, 
  391.     FUNCPTR  actionFunc, 
  392.     BOOL     actionDef, 
  393.     int      actionArg
  394.     )
  395.     {
  396.     TRIGGER_ID trgId, pTrg;
  397.     int index;
  398.     if ( TRG_ACTION_IS_SET )
  399.         return (NULL);
  400.     if ((!trgLibInstalled) && (trgLibInit () != OK))
  401.         return (NULL);                         
  402.     
  403.     if ((trgId = (TRIGGER_ID)objAlloc(trgClassId)) == NULL)
  404.        return(NULL);
  405.     objCoreInit (&trgId->objCore, trgClassId);
  406.     /* set all the trigger parameters */
  407.     trgId->eventId = event;
  408.     trgId->conditional = conditional;
  409.     if (conditional == 1)
  410.         {
  411.         trgId->condType = condType;
  412.         /* FIXME: I think this should just be a pointer and not an union
  413.            I am not changing it right now, since I do not want to make
  414.            too many changes at the same time
  415.          */
  416.         switch (condType)
  417.     {
  418.     case TRIGGER_COND_VAR:
  419.                 trgId->condEx1 = condEx1;
  420.         break;
  421.     case TRIGGER_COND_FUNC:
  422.                 trgId->condEx1 = condEx1;
  423.         break;
  424.             case TRIGGER_COND_LIB:
  425.                 trgId->condEx1 = condEx1;
  426.         break;
  427.     }
  428.         trgId->condOp = condOp;
  429.         trgId->condEx2 = condEx2;
  430.         }
  431.     else
  432.         {
  433.         trgId->condType = -1;
  434.         trgId->condEx1 = (void *)(-1);
  435.         trgId->condOp = -1;
  436.         trgId->condEx2 = -1;
  437.         }
  438.     trgId->objId = objId;
  439.     trgId->contextType = contextType;
  440.     trgId->contextId = contextId; 
  441.     trgId->disable = disable;
  442.     trgId->chain = chain;
  443.     trgId->actionType = actionType;
  444.     trgId->actionDef = actionDef;
  445.     trgId->actionFunc = actionFunc;
  446.     trgId->actionArg = actionArg;
  447.     trgId->status = status;
  448.     trgId->hitCnt = 0;
  449.     trgId->next = NULL;
  450.     if ( actionDef  && !trgActionDefStarted ) 
  451. trgActionDefStart();
  452.     if ( status == TRG_ENABLE )
  453.         trgCnt++;
  454.     index = trgEvtToIndex(event);
  455.     TRG_EVTCLASS_SET(trgClassList[index]);
  456. #if 0
  457. printf ("index is %d, class is %xn", index , trgClassList[index]);
  458. printf ("pTrg NULL: trList[%d] is %pn", index , trgList[index]);
  459. #endif
  460.     pTrg = trgList[index];
  461.     /* add the trigger to the list */
  462.    if (trgList[index] == NULL)
  463.        {
  464.        trgList[index] = trgId;
  465.        }
  466.    else
  467.        {
  468.        while (pTrg->next != NULL)
  469.            pTrg = pTrg->next;
  470.        pTrg->next = trgId;
  471.        }
  472.     return(trgId);
  473.     }
  474. /*******************************************************************************
  475. *
  476. * trgDelete - delete a trigger from the trigger list
  477. *
  478. * This routine deletes a trigger by removing it from the trigger list.  It
  479. * also checks that no other triggers are still active.  If there are no
  480. * active triggers and triggering is still on, it turns triggering off.
  481. *
  482. * RETURNS: OK, or ERROR if the trigger is not found.
  483. *
  484. * SEE ALSO: trgAdd()
  485. */
  486. STATUS trgDelete
  487.     (
  488.     TRIGGER_ID trgId
  489.     )
  490.     {
  491.     int index;
  492.     TRIGGER_ID  pTrg;
  493.     /* if the id is NULL, exit */
  494.     if (trgId == NULL)
  495. return(ERROR);
  496.     /* Verify the trigger exists */
  497.     if (OBJ_VERIFY (trgId, trgClassId) != OK) {
  498.         return(ERROR);
  499.     }
  500.     /* if the trigger was still enabled then decrease the counter 
  501.      * and if the counter goes to zero, then turn the instrumentation off
  502.      */
  503.     if ( (trgId->status == TRG_ENABLE) && (--trgCnt == 0))
  504.             trgOff();
  505.     objCoreTerminate(&trgId->objCore);
  506.     /* first, let's find the list where the trigger should be */
  507.     index = trgEvtToIndex(trgId->eventId);
  508.     pTrg = trgList[index];
  509.     /* if it is empty, then there is some mistake: where did the trigger go? */
  510.     if (pTrg == NULL)
  511.         return (ERROR);
  512.     if (pTrg == trgId)
  513. {
  514.      pTrg = pTrg->next;
  515. trgId->next = NULL;
  516. objFree(trgClassId, (char *)trgId);
  517.         trgList[index] = pTrg;
  518. /* if this is the last in the list we should also reset 
  519.  * the trgEvtClass 
  520.  */
  521. if (pTrg == NULL)
  522.     {
  523.     TRG_EVTCLASS_UNSET(trgClassList[index]);
  524.             if ( TRG_EVTCLASS_IS_SET (CLASS_NONE) )
  525.                 trgOff();
  526.     }
  527. return(OK);
  528. }
  529.     while (pTrg->next != NULL)
  530.         {
  531.         if ( pTrg->next != trgId)
  532.             pTrg = pTrg->next;
  533.         else
  534.             break;   
  535.         }
  536.     /* if it is not NULL, then it is the one we are looking for */
  537.     if (pTrg->next != NULL)
  538.         {
  539.         pTrg->next = pTrg->next->next;
  540. trgId->next = NULL;
  541. objFree(trgClassId, (char *)trgId);
  542. return(OK);
  543.         }
  544.  
  545.     return(ERROR); /* if we are here, then we did not found it! */
  546.     }
  547. /*******************************************************************************
  548. *
  549. * trgOn - set triggering on
  550. *
  551. * This routine activates triggering.  From this time on, any time an event
  552. * point is hit, a check for the presence of possible triggers is performed.
  553. * Start triggering only when needed since some overhead is introduced.
  554. *
  555. * NOTE
  556. * If trgOn() is called when there are no triggers in the trigger list, it
  557. * immediately sets triggering off again.  If trgOn() is called with at least
  558. * one trigger in the list, triggering begins.  Triggers should not be 
  559. * added to the list while triggering is on since this can create
  560. * instability.
  561. *
  562. * RETURNS: OK or ERROR.
  563. *
  564. * SEE ALSO: trgOff()
  565. */
  566. STATUS trgOn (void)
  567.     {
  568.     int level; 
  569.     if ( (! TRG_ACTION_IS_SET) &&  (! TRG_EVTCLASS_IS_EMPTY) )
  570.         {
  571.         if ((!trgLibInstalled) && (trgLibInit () != OK))
  572.             return (ERROR);                         
  573.         level = intLock();
  574. TRG_ACTION_SET;
  575.         intUnlock(level);
  576. return (OK);
  577. }
  578.     return (ERROR);
  579.     }
  580. /*******************************************************************************
  581. *
  582. * trgOff - set triggering off
  583. *
  584. * This routine turns triggering off. From this time on, when an event point 
  585. * is hit, no search on triggers is performed.
  586. *
  587. * RETURNS: N/A
  588. *
  589. * SEE ALSO: trgOn()
  590. */
  591. void trgOff (void)
  592.     {
  593.     int level;
  594.     if (TRG_ACTION_IS_SET)
  595. {
  596.         level = intLock();
  597.         /* reset the variable */
  598.         TRG_ACTION_UNSET;
  599.         intUnlock(level);
  600. }
  601.     }
  602. /*******************************************************************************
  603. *
  604. * trgEnable - enable a trigger
  605. *
  606. * This routine enables a trigger that has been created with trgAdd(). A counter
  607. * is incremented to keep track of the total number of enabled triggers so that 
  608. * trgDisable() knows when to set triggering off. If the maximum number of 
  609. * enabled triggers is reached, an error is returned. 
  610. *
  611. * RETURNS: OK, or ERROR if the trigger ID is not found or if the maximum
  612. * number of triggers has already been enabled.
  613. *
  614. * SEE ALSO: trgDisable()
  615. */
  616. STATUS trgEnable
  617.     (
  618.     TRIGGER_ID trgId
  619.     )
  620.     {
  621.     if (trgId == NULL)
  622.         return(ERROR);
  623.     if ( trgId->status != TRG_ENABLE )
  624. {
  625.         trgCnt++;
  626.         trgId->status = TRG_ENABLE;
  627. }
  628.     return(OK);
  629.     }
  630. /*******************************************************************************
  631. *
  632. * trgDisable - turn a trigger off
  633. *
  634. * This routine disables a trigger. It also checks to see if there are triggers
  635. * still active.  If this is the last active trigger it sets triggering off.
  636. *
  637. * RETURNS: OK, or ERROR if the trigger ID is not found.
  638. *
  639. * SEE ALSO: trgEnable()
  640. */
  641. STATUS trgDisable
  642.     (
  643.     TRIGGER_ID trgId
  644.     )
  645.     {
  646.     int level;
  647.     if (trgId == NULL)
  648.         return(ERROR);
  649.     level = intLock();
  650.     if ( trgId->status != TRG_DISABLE )
  651. {
  652.         trgId->status = TRG_DISABLE;
  653. intUnlock(level);
  654.         if ( (--trgCnt == 0) && TRG_ACTION_IS_SET )
  655.             trgOff();
  656. }
  657.     else
  658. {
  659. intUnlock(level);
  660. return(ERROR);
  661. }
  662.     return(OK);
  663.     }
  664. /*******************************************************************************
  665. *
  666. * trgChainSet - chains two triggers
  667. *
  668. * This routine chains two triggers together.  When the first trigger fires, it
  669. * calls trgEnable() for the second trigger.  The second trigger must be created
  670. * disabled in order to maintain the correct sequence.
  671. *
  672. * RETURNS: OK or ERROR.
  673. *
  674. * SEE ALSO: trgEnable()
  675. */
  676. STATUS trgChainSet
  677.     (
  678.     TRIGGER_ID fromId,
  679.     TRIGGER_ID toId
  680.     )
  681.     {
  682.     if ( fromId == NULL )
  683. return(ERROR);
  684.     if ( fromId->chain != NULL && toId != NULL )
  685. return(ERROR);
  686.     fromId->chain = toId;
  687.     return (OK);
  688.     }
  689. /*******************************************************************************
  690. *
  691. * trgContextMatch - show the trigger list
  692. *
  693. * INTERNAL
  694. * FIXME
  695. *
  696. * RETURNS:
  697. * SEE ALSO: FIXME()
  698. * NOMANUAL
  699. */
  700. BOOL trgContextMatch
  701.     (
  702.     TRIGGER_ID pTrg
  703.     )
  704.     {
  705. switch ( pTrg->contextType )
  706.     {
  707.     case TRG_CTX_ANY:
  708. return (TRUE);
  709.     case TRG_CTX_SYSTEM:
  710. return(kernelState); 
  711.     case TRG_CTX_TASK:
  712. return ( (!kernelState) && (!INT_CONTEXT ()) &&
  713.      ((WIND_TCB *)(pTrg->contextId) == taskIdCurrent) );
  714.     case TRG_CTX_ANY_TASK:
  715. return ((!kernelState) && (!INT_CONTEXT ()));
  716.     case TRG_CTX_ISR:
  717.     case TRG_CTX_ANY_ISR:
  718. return (INT_CONTEXT ());
  719.     default:
  720. return(FALSE);
  721.     }
  722. return(FALSE);
  723.     }
  724. /*******************************************************************************
  725. *
  726. * trgCondTest - show the trigger list
  727. *
  728. * INTERNAL
  729. * FIXME
  730. *
  731. * RETURNS:
  732. * SEE ALSO: FIXME()
  733. * NOMANUAL
  734. */
  735. BOOL trgCondTest
  736.     (
  737.     TRIGGER_ID pTrg,
  738.     int        objId
  739.     )
  740.     {
  741.     BOOL retval;
  742.     int level = intLock();
  743. switch (pTrg->condOp)
  744.     {
  745.     case TRIGGER_EQ: 
  746.         switch (pTrg->condType)
  747.         {
  748.         case TRIGGER_COND_VAR: 
  749.                        retval = ((* ((BOOL *)pTrg->condEx1) == pTrg->condEx2));
  750.                        intUnlock(level);
  751.                        return(retval);
  752.         case TRIGGER_COND_FUNC:
  753.        retval = (((* ((FUNCPTR)pTrg->condEx1)) () == pTrg->condEx2));
  754.                        intUnlock(level);
  755.                        return(retval);
  756.                 case TRIGGER_COND_LIB:
  757.        retval = (*((FUNCPTR)pTrg->condEx1)) (objId,pTrg->condEx2);
  758.                        intUnlock(level);
  759.                        return(retval);
  760.         default:
  761.                     intUnlock(level);
  762.     return(FALSE);
  763.         }
  764.     case TRIGGER_NEQ: 
  765.        switch (pTrg->condType)
  766.            {
  767.            case TRIGGER_COND_VAR: 
  768.                        retval = ((* ((BOOL *)pTrg->condEx1) != pTrg->condEx2));
  769.                        intUnlock(level);
  770.                        return(retval);
  771.            case TRIGGER_COND_FUNC:
  772.        retval = (((* ((FUNCPTR)pTrg->condEx1)) () != pTrg->condEx2));
  773.                        intUnlock(level);
  774.                        return(retval);
  775.            default:
  776.                        intUnlock(level);
  777.        return(FALSE);
  778.            }
  779.     case TRIGGER_GRT: 
  780.        switch (pTrg->condType)
  781.            {
  782.            case TRIGGER_COND_VAR: 
  783.                        retval = ((* ((BOOL *)pTrg->condEx1) > pTrg->condEx2));
  784.                        intUnlock(level);
  785.                        return(retval);
  786.            case TRIGGER_COND_FUNC:
  787.        retval = (((* ((FUNCPTR)pTrg->condEx1)) () > pTrg->condEx2));
  788.                        intUnlock(level);
  789.                        return(retval);
  790.            default:
  791.                        intUnlock(level);
  792.        return(FALSE);
  793.            }
  794.     case TRIGGER_LSS: 
  795.        switch (pTrg->condType)
  796.            {
  797.            case TRIGGER_COND_VAR: 
  798.                        retval = ((* ((BOOL *)pTrg->condEx1) < pTrg->condEx2));
  799.                        intUnlock(level);
  800.                        return(retval);
  801.            case TRIGGER_COND_FUNC:
  802.        retval = (((* ((FUNCPTR)pTrg->condEx1)) () < pTrg->condEx2));
  803.                        intUnlock(level);
  804.                        return(retval);
  805.            default:
  806.                        intUnlock(level);
  807.        return(FALSE);
  808.            }
  809.     case TRIGGER_GEQ: 
  810.        switch (pTrg->condType)
  811.            {
  812.            case TRIGGER_COND_VAR: 
  813.                        retval = ((* ((BOOL *)pTrg->condEx1) >= pTrg->condEx2));
  814.                        intUnlock(level);
  815.                        return(retval);
  816.            case TRIGGER_COND_FUNC:
  817.        retval = (((* ((FUNCPTR)pTrg->condEx1)) () >= pTrg->condEx2));
  818.                        intUnlock(level);
  819.                        return(retval);
  820.            default:
  821.                        intUnlock(level);
  822.        return(FALSE);
  823.            }
  824.     case TRIGGER_LEQ: 
  825.        switch (pTrg->condType)
  826.            {
  827.            case TRIGGER_COND_VAR: 
  828.                        retval = ((* ((BOOL *)pTrg->condEx1) <= pTrg->condEx2));
  829.                        intUnlock(level);
  830.                        return(retval);
  831.            case TRIGGER_COND_FUNC:
  832.        retval = (((* ((FUNCPTR)pTrg->condEx1)) () <= pTrg->condEx2));
  833.                        intUnlock(level);
  834.                        return(retval);
  835.            default:
  836.                        intUnlock(level);
  837.        return(FALSE);
  838.            }
  839.     case TRIGGER_OR: 
  840.        switch (pTrg->condType)
  841.            {
  842.            case TRIGGER_COND_VAR: 
  843.                        retval = ((* ((BOOL *)pTrg->condEx1) || pTrg->condEx2));
  844.                        intUnlock(level);
  845.                        return(retval);
  846.            case TRIGGER_COND_FUNC:
  847.        retval = (((* ((FUNCPTR)pTrg->condEx1)) () || pTrg->condEx2));
  848.                        intUnlock(level);
  849.                        return(retval);
  850.            default:
  851.                        intUnlock(level);
  852.        return(FALSE);
  853.            }
  854.     case TRIGGER_AND: 
  855.        switch (pTrg->condType)
  856.            {
  857.            case TRIGGER_COND_VAR: 
  858.                        retval = ((* ((BOOL *)pTrg->condEx1) && pTrg->condEx2));
  859.                        intUnlock(level);
  860.                        return(retval);
  861.            case TRIGGER_COND_FUNC:
  862.        retval = (((* ((FUNCPTR)pTrg->condEx1)) () && pTrg->condEx2));
  863.                        intUnlock(level);
  864.                        return(retval);
  865.            default:
  866.                        intUnlock(level);
  867.        return(FALSE);
  868.            }
  869.     default:
  870.                intUnlock(level);
  871.        return (FALSE);
  872.     }
  873.     intUnlock(level);
  874.     }
  875. /*******************************************************************************
  876. *
  877. * trgActionPerform - perform the action associated to a trigger 
  878. *
  879. * INTERNAL
  880. * FIXME
  881. *
  882. * RETURNS: 
  883. * SEE ALSO: FIXME()
  884. * NOMANUAL
  885. */
  886. void trgActionPerform
  887.     (
  888.     TRIGGER_ID pTrg
  889.     )
  890.     {
  891.     switch (pTrg->actionType)
  892.        {
  893.        case TRG_ACT_WV_START:
  894.        case TRG_ACT_WV_STOP:
  895.        case TRG_ACT_FUNC:
  896.            if ( pTrg->actionFunc != NULL)
  897.                {
  898.                (* (pTrg->actionFunc)) (pTrg->actionArg);
  899.                }
  900.        }
  901.     }
  902. /*******************************************************************************
  903. *
  904. * trgActionDefPerform - perform the trigger action in deferred mode
  905. *
  906. * INTERNAL
  907. * FIXME
  908. *
  909. * RETURNS: 
  910. * SEE ALSO: FIXME()
  911. * NOMANUAL
  912. */
  913. STATUS trgActionDefPerform ()
  914.     {
  915.     /* loop, executing actions and pending on the next request */
  916.     if ((trgDefSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY)) == NULL)
  917.         {
  918.         return (ERROR);
  919.         }
  920.     while (TRUE)
  921.         { 
  922.         semTake (trgDefSem, WAIT_FOREVER);  /* pend on event semaphore */
  923. if ( trgWorkQFullNotify )
  924.     {
  925.             logMsg ("Error: Triggering Work Queue overflow! n",
  926.      0,0,0,0,0,0);
  927.     trgWorkQFullNotify = FALSE;
  928.     }
  929. while (TRUE)
  930.     {
  931.     if (trgWorkQ[trgWorkQReader] != NULL)
  932. {
  933. /* there is an entry here on the queue. Process it */
  934. trgActionPerform ((TRIGGER_ID)trgWorkQ[trgWorkQReader]);
  935. trgWorkQ[trgWorkQReader] = NULL;
  936. }
  937.     else
  938. {
  939. if (trgWorkQReader == trgWorkQWriter)
  940.     {
  941.     /*
  942.      * this entry is marked as unused and the read pointer
  943.      * has caught up the write pointer. The queue is now
  944.      * empty
  945.      */
  946.     break; /* exit the inner loop */
  947.     }
  948. }
  949.     /* increment the read pointer so it remains valid at all times */
  950.     if (trgWorkQReader >= (TRG_MAX_REQUESTS - 1))
  951. trgWorkQReader = 0;
  952.     else
  953. trgWorkQReader++;
  954.     }
  955.         }
  956.  
  957.     /* never returns */
  958.     return (OK);
  959.     }
  960.  
  961.  
  962. /*******************************************************************************
  963. *
  964. * trgCheck - check if there is a trigger associated to the event
  965. *
  966. * INTERNAL
  967. *
  968. * This routine is the core of the triggering mechanism. It is called whenever
  969. * an event point is hit. It determines if a trigger exists for this event and
  970. * performs the action associated to the trigger. In order to verify a trigger
  971. * has been set for the event point, the routine performs the following steps:
  972. *  - selects the trigger list the event belongs to, so not to look for all
  973. *     triggers. Triggers are divided in different lists, depending on the class
  974. *     they belong to. Classes are similar but not identical to the Windview ones.
  975. *  - verifies the trigger is a valid object
  976. *  - verifies the type of event matches the trigger event id
  977. *  - verifies the object ID of the event point (if any) matches the one defined
  978. *    in the trigger (if any)
  979. *  - check the contect we are in is the same as the one specified in the trigger.
  980. *    Contexts can be of the following type: ANY, ANY_TASK, TASK, SYSTEM, ANY_ISR.
  981. *  - if a condition is also defined for the trigger, it checks it is verified.
  982. *    Conditions, can be a function, a var or a library function. They can use
  983. *    different operands (==, !=, >, <, ...) and are matched against a value
  984. *  - if we ever get here, well, we have hit a trigger! At this point 3 things,
  985. *    not necessarily mutually exclusive can happen:
  986. *        . disable the current trigger (we want the action performed only once)
  987. *        . perform an action
  988. *        . enable a chained trigger (similar to a state machine)
  989. *
  990. * The action can be either a user/system defined routine or a library (such
  991. * as WV_START/STOP). Action axecution represent the most complex part of the
  992. * triggering mechanism. Event points are often set in critical regions of the
  993. * kernel where the number of actions that can be performed is limited. In order
  994. * to avoid conflicts and still allow the user full range of action, we have 
  995. * provided a deferred execution mode. In this way, when an action should be 
  996. * performed a request is sent to a task. Therefore the action itself will not be
  997. * executed in the context where the event happens, but in a safer one. If a user
  998. * really needs the action to be performed on the spot, this mode can be switched
  999. * off. The way the deferred mode is implemented represent the critical part of
  1000. * the code, and it is still a work in progress.
  1001. * The first approach we followed was to use message queues. It logically satisfies
  1002. * the need we had to send information to a task pending waiting for it.
  1003. * The implementation of this approach raised a few issues:
  1004. *    - recursion: msgQSend/Receive (directly and indirectly) refer to several event
  1005. *      points. Things get worse if a trigger is set on one of them. First of all,
  1006. *      we are introducing a form of intrusion, since the triggers will be fired on
  1007. *      events generated by the trigger itself. More than that, if triggers are not
  1008. *      disabled, it will go into a loop.
  1009. *    - context switch: msgQSend can generate a context switch, which is not the most
  1010. *      desirable thing.
  1011. *    - queue does not work well with interrupts: if we are in an interrupt we can not
  1012. *      use the WAITFOREVER option. This will generate potential inconsistency in the
  1013. *      queue.
  1014. * A second approach was to put a task on the workQueue, using workQAdd, but this will 
  1015. * cause the execution of the action when we are doing windExit.
  1016. * A solution to this problem would be to add some "harmless" action in the workQueue, 
  1017. * that does not cause context switch, and eventually will wake up the task. Therefore,
  1018. * the idea of semBGiveDefer. The problem now is to tell the pending task what to do.
  1019. * This is solved by putting the request into a triggering work queue.
  1020. * This is the current implementation. The work queue mechanism needs definitely to be
  1021. * revised. Atthe moment it could cause starvation. The requests are executed from the
  1022. * top of the list down, but a new request will be put at the top of the list, even if
  1023. * the list is not empty. This could be solved by using a rotation mechanism, so that 
  1024. * request are alway put at the end of the queue. This part has not been implemented yet.
  1025. *
  1026. * It requires two arguments and a few optional ones.
  1027. *
  1028. * RETURNS:
  1029. * SEE ALSO: FIXME()
  1030. * NOMANUAL
  1031. */
  1032. void trgCheck
  1033.     (
  1034.     event_t event,
  1035.     int     index,
  1036.     int     obj,  
  1037.     int     arg1,
  1038.     int     arg2,
  1039.     int     arg3,
  1040.     int     arg4,
  1041.     int     arg5
  1042.     )
  1043.     {
  1044.     TRIGGER_ID pTrg = NULL; 
  1045.     int level;
  1046.     int any = 0;
  1047.     pTrg = trgList[index];
  1048. restart:
  1049.     if (index == TRG_CLASS_3_ON)
  1050. trgNone = 20;
  1051.     while (pTrg != NULL) 
  1052.         { 
  1053. if (OBJ_VERIFY (pTrg, trgClassId) != OK)
  1054.     pTrg = pTrg->next;
  1055. else if ( pTrg->status != TRG_ENABLE )
  1056.     pTrg = pTrg->next;
  1057. else if ((pTrg->eventId != EVENT_ANY_EVENT) && 
  1058.          (pTrg->eventId != event) )
  1059.     pTrg = pTrg->next;
  1060. else if ((pTrg->objId != NULL) && (((OBJ_ID)obj != NULL) &&
  1061.          ((OBJ_ID)obj != pTrg->objId)) )
  1062.     pTrg = pTrg->next;
  1063.         else
  1064.     {
  1065.             switch ( pTrg->contextType )
  1066.         {
  1067.         case TRG_CTX_ANY:
  1068.             break;
  1069.         case TRG_CTX_SYSTEM:
  1070.             if (kernelState) 
  1071.                 break;
  1072.             else
  1073.                 goto end;
  1074.         case TRG_CTX_TASK:
  1075.             if ((!kernelState) && (!INT_CONTEXT ()) &&
  1076.                  ((WIND_TCB *)(pTrg->contextId) == taskIdCurrent) )
  1077.         break;
  1078.     else
  1079.         goto end;
  1080.         case TRG_CTX_ANY_TASK:
  1081.     if ((!kernelState) && (!INT_CONTEXT ())) 
  1082.         break;
  1083.     else
  1084.         goto end;
  1085.         case TRG_CTX_ISR:
  1086.         case TRG_CTX_ANY_ISR:
  1087.     if (INT_CONTEXT ())
  1088.         break;
  1089.     else
  1090.         goto end;
  1091.         default:
  1092.         goto end;
  1093.         }
  1094.             /* check if it is a conditional trigger and in case
  1095.              * test the condition
  1096.              */
  1097.             if ((pTrg->conditional == TRIGGER_COND_YES) && 
  1098.                 (pTrg->condEx1 != NULL) && (trgCondTest(pTrg,obj) == FALSE))
  1099.                         goto end;
  1100.             level = intLock();
  1101.             /* disable the current trigger, if requested */
  1102.             if ((pTrg->disable == TRUE) && (trgDisable(pTrg) == ERROR))
  1103.                 {
  1104.                 intUnlock(level);
  1105.                 goto end;
  1106.                 }
  1107.             intUnlock(level);
  1108.             pTrg->hitCnt++;
  1109.     /* perform the action associated with the trigger, if any */
  1110.             if ( pTrg->actionType != TRG_ACT_NONE )
  1111.         {
  1112. if ( pTrg->actionDef == FALSE )
  1113.                     trgActionPerform(pTrg);
  1114. else /* defer the action */
  1115.     {
  1116.     /*
  1117.      * This will put a request in the triggering work queue
  1118.      * and release a semaphore so that the task trgActDef
  1119.      * can execute the request once we are out of this
  1120.      * code. We might be in Kernel state and we do not want
  1121.      * to perform action here, if possible.
  1122.      */
  1123.     level = intLock();
  1124.     if ( trgWorkQ[trgWorkQWriter] == NULL )
  1125. {
  1126.         trgWorkQ[trgWorkQWriter] = pTrg;
  1127. /*
  1128.  * Increment the writer index.
  1129.  * Ensure that trgWorkQWriter NEVER goes to an invalid
  1130.  * value when wrapping round. This assurance is needed
  1131.  * in the trgActDef task
  1132.  */
  1133. if (trgWorkQWriter >= (TRG_MAX_REQUESTS - 1))
  1134.             trgWorkQWriter = 0;
  1135. else
  1136.     trgWorkQWriter++;
  1137. }
  1138.     else
  1139.   {
  1140. /* If the workQ is full need to stop triggering */
  1141. trgWorkQFullNotify = TRUE;
  1142. trgOff();
  1143.      intUnlock(level);
  1144. return ;
  1145. }
  1146. #if (CPU_FAMILY == I80X86)
  1147.                     portWorkQAdd1((FUNCPTR)semBGiveDefer,
  1148.                                   (int)trgDefSem);
  1149. #else
  1150.                     workQAdd1((FUNCPTR)semBGiveDefer,
  1151.                               (int)trgDefSem);
  1152. #endif /* CPU_FAMILY == I80X86 */
  1153.     intUnlock(level);
  1154.     }
  1155.  }
  1156.             /* check if there is any trigger chained to the current
  1157.              * one, and if any, enable it
  1158.     if (OBJ_VERIFY (&(pTrg->chain), trgClassId) == OK)
  1159.              */
  1160.             if ( pTrg->chain != NULL )
  1161.         {
  1162.                 trgEnable(pTrg->chain);
  1163. if (!TRG_ACTION_IS_SET)
  1164.     trgOn();
  1165. }
  1166.                  
  1167.     /* 
  1168.      * let's loop for the next one!
  1169.              */
  1170. end:
  1171.     pTrg = pTrg->next;
  1172.     }
  1173.         }
  1174.     if ((any == 0) && (trgList[TRG_ANY_EVENT_INDEX] != NULL))
  1175.         {
  1176. any = 1;
  1177.      pTrg = trgList[TRG_ANY_EVENT_INDEX];
  1178. goto restart;
  1179. }
  1180.     }
  1181. /* Conditional library fn */
  1182. int isTaskNew(int taskId, int arg)
  1183. {
  1184.     REG_SET regs;
  1185.     /* Load the regs of the task being resumed */
  1186.     taskRegsGet (taskId,&regs);
  1187.     /* Compare the current PC with the initial entry point */
  1188. #if 0
  1189. logMsg("entry = %p, pc = %pn",((WIND_TCB *) taskId)->entry,regs.pc,0,0,0,0);
  1190. #endif
  1191.     if ((FUNCPTR) regs.pc == (FUNCPTR) vxTaskEntry)
  1192.         {
  1193.         /*
  1194.          *  Task is at entry point, we can therefore deduce it has
  1195.          *  just been created.
  1196.          */
  1197.         /* now match actual user entry point */
  1198.         if((int) ((WIND_TCB *) taskId)->entry != 0 &&
  1199.            (int) ((WIND_TCB *) taskId)->entry == arg)
  1200.             {
  1201.             /* Suspend the task! */
  1202. #if 0
  1203. logMsg ("Suspending task %pn",taskId);
  1204. #endif
  1205. #if 1
  1206. #if (CPU_FAMILY == I80X86)
  1207.             portWorkQAdd1 ((FUNCPTR)taskSuspend, taskId);
  1208. #else
  1209.             workQAdd1 ((FUNCPTR)taskSuspend, taskId);
  1210. #endif /* CPU_FAMILY == I80X86 */
  1211. #else
  1212.             excJobAdd ((VOIDFUNCPTR)taskSuspend, taskId,0,0,0,0,0);
  1213. #endif
  1214.             return (TRUE);
  1215.             }
  1216.         else
  1217.             {
  1218.             /* This is not the entry point of interest */
  1219.             return (FALSE);
  1220.             }
  1221.         }
  1222.     else
  1223.         {
  1224.         /*
  1225.          *  Task is been resumed after running on from entry point.
  1226.          */
  1227.         return (FALSE);
  1228.         }
  1229. }
  1230. /*******************************************************************************
  1231. *
  1232. * trgEvent - trigger a user-defined event 
  1233. *
  1234. * This routine triggers a user event. A trigger must exist and triggering must 
  1235. * have been started with trgOn() or from the triggering GUI to use this routine.  
  1236. * The <evtId> should be in the range 40000-65535. 
  1237. * RETURNS: N/A
  1238. *
  1239. * SEE ALSO: dbgLib, e()
  1240. *
  1241. * INTERNAL
  1242. *
  1243. */
  1244. void trgEvent
  1245.     (
  1246.     event_t    evtId      /* event */
  1247.     )
  1248.     {
  1249.     trgCheck (evtId, TRG_USER_INDEX, 0, 0, 0, 0, 0, 0);
  1250.     }