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

VxWorks

开发平台:

C/C++

  1. /* eventLib.c - VxWorks events library */
  2. /* Copyright 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01d,09nov01,aeg  changed eventPendQ to global symbol vxEventPendQ for WindSh;
  8.  fixed problem in eventStart() where a re-registration would
  9.  not delete the previous one.
  10. 01c,30oct01,bwa  Corrected use of windview instrumentation for task-state
  11.                  transition logging. Added eventRsrcSend().
  12. 01b,25oct01,tcr  remove #undef WV_INSTRUMENTATION
  13. 01a,20sep01,bwa  written
  14. */
  15. /*
  16. DESCRIPTION
  17. Events are a means of communication between tasks and interrupt routines,
  18. based on a synchronous model. Only tasks can receive events, and both tasks
  19. and ISRs can send them.
  20. Events are similar to signals in that they are directed at one task but differ
  21. in the fact that they are synchronous in nature. Thus, the receiving task must
  22. pend when waiting for events to occur. Also, unlike signals, a handler is not
  23. needed since, when wanted events are received, the pending task continues its
  24. execution (like after a call to msgQReceive() or semTake()).
  25. Each task has its own events field that can be filled by having tasks (even
  26. itself) and/or ISRs sending events to the task. Each event's meaning is
  27. different for every task. Event X when received can be interpreted differently
  28. by separate tasks. Also, it should be noted that events are not accumulated.
  29. If the same event is received several times, it counts as if it were received
  30. only once. It is not possible to track how many times each event has been sent 
  31. to a task.
  32. There are some VxWorks objects that can send events when they become available.
  33. They are referred to as 'resources' in the context of events. They include
  34. semaphores and message queues. For example, when a semaphore becomes free,
  35. events can be sent to a task that asked for it.
  36. INTERNAL:
  37. WINDVIEW INSTRUMENTATION
  38. Level 1:
  39. eventSend () causes EVENT_EVENTSEND
  40. eventReceive() causes EVENT_EVENTRECEIVE
  41. Level 2:
  42. eventSend () causes EVENT_OBJ_EVENTSEND
  43. eventReceive () causes EVENT_OBJ_EVENTRECEIVE
  44. Level 3:
  45. N/A
  46. INCLUDE FILES: eventLib.h
  47. SEE ALSO: taskLib, semLib, semBLib, semCLib, semMLib, msgQLib,
  48. <VxWorks Programmer's Guide: Basic OS>
  49. */
  50. /* includes */
  51. #include "vxWorks.h"
  52. #include "qLib.h"
  53. #include "taskLib.h"
  54. #include "intLib.h"
  55. #include "errnoLib.h"
  56. #include "eventLib.h"
  57. #include "taskArchLib.h"
  58. #include "private/workQLibP.h"
  59. #include "private/eventLibP.h"
  60. #include "private/kernelLibP.h"
  61. #include "private/windLibP.h"
  62. #include "private/sigLibP.h"
  63. /* function prototypes */
  64. LOCAL void eventPendQRemove (WIND_TCB * pTcb);
  65. /* globals */
  66. Q_HEAD vxEventPendQ;
  67. #ifdef WV_INSTRUMENTATION
  68. VOIDFUNCPTR eventEvtRtn; /* windview - level 1 event logging */
  69. #endif
  70. /*******************************************************************************
  71. *
  72. * eventLibInit - Initialize events library
  73. *
  74. * Initialize the pending queue that will be used for all event operations.
  75. * This routine is called automatically when the events module is included.
  76. *
  77. * NOMANUAL
  78. */
  79. void eventLibInit (void)
  80.     {
  81.     qInit (&vxEventPendQ, Q_FIFO);
  82.     }
  83. /*******************************************************************************
  84. *
  85. * eventInit - initializes event-related info for a resource
  86. *
  87. * Initializes event-related data for a given resource. It shouldn't be used
  88. * outside of resource initialization.
  89. *
  90. * NOMANUAL
  91. */
  92. void eventInit
  93.     (
  94.     EVENTS_RSRC * evRsrc
  95.     )
  96.     {
  97.     evRsrc->taskId = (int)NULL;
  98.     evRsrc->registered = 0x0;
  99.     evRsrc->options = 0x0;
  100.     }
  101. /*******************************************************************************
  102. *
  103. * eventTerminate - Terminate event-related operations for a resource
  104. *
  105. * Wakes up task waiting on events that should be sent from a resource.
  106. *
  107. * WARNING: - This function shouldn't be used outside of resource destruction.
  108. *          - Function must be called with kernelState == TRUE
  109. *
  110. * NOMANUAL
  111. */
  112. void eventTerminate
  113.     (
  114.     const EVENTS_RSRC * evRsrc
  115.     )
  116.     {
  117.     WIND_TCB * pTcb = (WIND_TCB *)evRsrc->taskId;
  118.     if (pTcb != NULL)
  119. {
  120. int level;
  121. /*
  122.  * must intLock to prevent an ISR from doing an eventSend that also
  123.  * wakes up the task.
  124.  */
  125. level = intLock ();
  126. if (TASK_ID_VERIFY(pTcb) != OK)
  127.     {
  128.     intUnlock (level);
  129.     return;
  130.     }
  131. /* only wakeup task if it is waiting */
  132. if (pTcb->events.sysflags & EVENTS_SYSFLAGS_WAITING)
  133.     {
  134.     /* task will not be waiting anymore */
  135.     pTcb->events.sysflags &= ~EVENTS_SYSFLAGS_WAITING;
  136.     intUnlock (level);
  137.     /* remove task from the pend Q and put it back on the ready Q */
  138.             windPendQRemove (pTcb);
  139.             windReadyQPut (pTcb);
  140.     /*
  141.      * windExit() will return ERROR: errorStatus is set so that 
  142.      * task will know what caused the error
  143.      */
  144.             taskRtnValueSet (pTcb, ERROR);
  145.     pTcb->errorStatus = S_objLib_OBJ_DELETED;
  146.     }
  147. else
  148.     intUnlock (level);
  149. }
  150.     }
  151. /*******************************************************************************
  152. *
  153. * eventReceive - Wait for event(s)
  154. *
  155. * Pends task until one or all specified <events> have occurred. When
  156. * they have,<pEventsReceived> will be filled with those that did occur.
  157. *
  158. * The <options> parameter is used for three user options. Firstly, it is used 
  159. * to specify if the task is going to wait for all events to occur or only one 
  160. * of them. One of the following has to be selected:
  161. * .iP "EVENTS_WAIT_ANY (0x1)"
  162. * only one event has to occur
  163. * .iP "EVENTS_WAIT_ALL (0x0)"
  164. * will wait until all events occur.
  165. * .LP
  166. * Secondly, it is used to specify if the events returned in <pEventsReceived>
  167. * will be only those received and wanted, or all events received (even the
  168. * ones received before eventReceive() was called). By default it returns
  169. * only the events wanted. Performing a bitwise-OR of the following: 
  170. * .iP "EVENTS_RETURN_ALL (0x2)"
  171. * causes the function to return received events, both wanted and unwanted.
  172. * .LP
  173. * Thirdly, it can be used to retrieve what events have been received by the
  174. * current task. If the option
  175. * .iP "EVENTS_FETCH (0x80)"
  176. * is chosen by the user, then <pEventsReceived> will be filled with the events
  177. * that have already been received and will return immediately. In this case,
  178. * the parameters <events> and <timeout>, as well as all the other options, are
  179. * ignored. Also, events are not cleared, allowing to get a peek at the events
  180. * that have already been received.
  181. * .LP
  182. *
  183. * The <timeout> parameter specifies the number of ticks to wait for wanted
  184. * events to be sent to the waiting task. It can also have the following 
  185. * special values:
  186. * .iP "NO_WAIT  (0)"
  187. * return immediately, even if no events have arrived.
  188. * .iP "WAIT_FOREVER  (-1)"
  189. * never time out.
  190. * .LP
  191. *
  192. * It must also be noted that events sent to the receiving task are cleared
  193. * prior to returning, as if a call to eventClear() was done.
  194. *
  195. * The parameter <pEventsReceived> is always filled with the events received
  196. * even when the function returns an error, except if a value of NULL was
  197. * passed.
  198. *
  199. * WARNING: This routine may not be used from interrupt level.
  200. *
  201. * RETURNS:
  202. * OK on success or ERROR.
  203. *
  204. * ERRNO
  205. * .iP "S_eventLib_TIMEOUT"
  206. * Wanted events not received before specified time expired.
  207. * .iP "S_eventLib_NOT_ALL_EVENTS"
  208. * Specified NO_WAIT as the timeout parameter and wanted events were not already
  209. * received when the routine was called.
  210. * .iP "S_objLib_OBJ_DELETED"
  211. * Task is waiting for some events from a resource that is subsequently deleted.
  212. * .iP "S_intLib_NOT_ISR_CALLABLE"
  213. * Function has been called from ISR.
  214. * .iP "S_eventLib_ZERO_EVENTS"
  215. * The <events> parameter has been passed a value of 0.
  216. *
  217. * SEE ALSO: semEvLib, msgQEvLib, eventSend()
  218. */
  219. STATUS eventReceive 
  220.     (
  221.     UINT32 events, /* events task is waiting to occur */
  222.     UINT8 options, /* user options */
  223.     int timeout, /* ticks to wait */
  224.     UINT32 *pEventsReceived /* events occured are returned through this */
  225.     )
  226.     {
  227.     int level;
  228.     STATUS status;
  229.     UINT32 received;
  230.     if (INT_RESTRICT () != OK)
  231. return (ERROR);
  232.     /* special case: only return received events */
  233.     if (options & EVENTS_FETCH)
  234. {
  235. if (pEventsReceived != NULL)
  236.     *pEventsReceived = taskIdCurrent->events.received;
  237. return (OK);
  238. }
  239.     if (events == 0x0)
  240. {
  241. errnoSet (S_eventLib_ZERO_EVENTS);
  242. return ERROR;
  243. }
  244. #ifdef WV_INSTRUMENTATION
  245.     /* windview - level 1 event logging */
  246.     EVT_OBJ_EVENT(EVENT_EVENTRECEIVE, 3, events, timeout, options);
  247. #endif /* WV_INSTRUMENTATION */
  248. again:
  249.     /*
  250.      * This caching of value is done to reduce the amount of time we spend
  251.      * with the interrupts locked. If not used, the whole function has to
  252.      * be within an intLock()...intUnlock() pair.
  253.      */
  254.     /*
  255.      * Caching the value causes a compiler warning since we remove the
  256.      * volatile property of the structure member. This is what we want to
  257.      * achieve so that error must NOT be corrected.
  258.      */
  259.     received = taskIdCurrent->events.received;
  260.     /* check if wanted events have not already been received */
  261.     if ((options & EVENTS_WAIT_MASK) == EVENTS_WAIT_ALL)
  262. {
  263. /*
  264.  * In the case that ALL events are wanted, all the events must already
  265.  * have been received.
  266.  */
  267. if ((events & received) == events)
  268.     {
  269.     /* only return events if user passed a valid return container */
  270.     level = intLock ();
  271.     if (pEventsReceived != NULL)
  272. {
  273. if (options & EVENTS_RETURN_ALL)
  274.     *pEventsReceived = taskIdCurrent->events.received;
  275. else
  276.     *pEventsReceived = events;
  277. }
  278.     /* clear events */
  279.     taskIdCurrent->events.received = 0x0;
  280.     intUnlock (level);
  281.     return (OK);
  282.     }
  283. }
  284.     else
  285. {
  286. /*
  287.  * In the case that ANY events are wanted, if even only one of them has
  288.  * already been received, we have what we wanted.
  289.  */
  290. if ((events & received) != 0x0)
  291.     {
  292.     /* only return events if user passed a valid return container */
  293.     level = intLock ();
  294.     if (pEventsReceived != NULL)
  295. {
  296. if (options & EVENTS_RETURN_ALL)
  297.     *pEventsReceived = taskIdCurrent->events.received;
  298. else
  299.     *pEventsReceived = events & taskIdCurrent->events.received;
  300. }
  301.     /* clear events */
  302.     taskIdCurrent->events.received = 0x0;
  303.     intUnlock (level);
  304.     return (OK);
  305.     }
  306. }
  307.     /* if we got here, we have not already received the events we wanted */
  308.     /* look if events have been received while we were not intLocked */
  309.     level = intLock ();
  310.     if (taskIdCurrent->events.received != received)
  311. {
  312. intUnlock (level);
  313. goto again;
  314. }
  315.     /*
  316.      * if we do not want to wait, no more events will be received so the 
  317.      * request is not satisfied.
  318.      */
  319.     if (timeout == NO_WAIT)
  320. {
  321. /* only return events if user passed a valid return container */
  322. if (pEventsReceived != NULL)
  323.     {
  324.     if (options & EVENTS_RETURN_ALL)
  325. *pEventsReceived = taskIdCurrent->events.received;
  326.     else
  327. *pEventsReceived = events & taskIdCurrent->events.received;
  328.     }
  329. /* clear events */
  330. taskIdCurrent->events.received = 0x0;
  331. intUnlock (level);
  332. errnoSet (S_eventLib_NOT_ALL_EVENTS);
  333. return (ERROR);
  334. }
  335.     /* We want to wait: fill needed fields */
  336.     taskIdCurrent->events.options = options;
  337.     taskIdCurrent->events.wanted  = events;
  338.     taskIdCurrent->events.sysflags = EVENTS_SYSFLAGS_WAITING;
  339.     kernelState = TRUE;
  340.     intUnlock (level);
  341. #ifdef WV_INSTRUMENTATION
  342.     /* windview - level 2 event logging */
  343.     EVT_TASK_0(EVENT_OBJ_EVENTRECEIVE);
  344. #endif /* WV_INSTRUMENTATION */
  345.     windPendQPut (&vxEventPendQ, timeout);
  346.     if ((status = windExit()) == RESTART)
  347. {
  348. timeout = SIG_TIMEOUT_RECALC(timeout);
  349. goto again;
  350. }
  351.     else if (status == ERROR)
  352. {
  353. if (taskIdCurrent->errorStatus == S_objLib_OBJ_TIMEOUT)
  354.     {
  355.     taskIdCurrent->events.sysflags &= ~EVENTS_SYSFLAGS_WAITING;
  356.     /*
  357.      * errno will be set to S_objLib_OBJ_TIMEOUT in windTickAnnounce()
  358.      * but events are not an object so change it to eventLib's timeout
  359.      */
  360.     errnoSet (S_eventLib_TIMEOUT);
  361.     }
  362. }
  363.     /*
  364.      * fill return variable with events received only if the user provided
  365.      * a valid container
  366.      */
  367.     level = intLock ();
  368.     if (pEventsReceived != NULL)
  369. {
  370. if (options & EVENTS_RETURN_ALL)
  371.     *pEventsReceived = taskIdCurrent->events.received;
  372. else
  373.     *pEventsReceived = events & taskIdCurrent->events.received;
  374. }
  375.     /* task has finished receiving events: clear events */
  376.     taskIdCurrent->events.received = 0x0;
  377.     intUnlock (level);
  378.     return (status);
  379.     }
  380. /*******************************************************************************
  381. *
  382. * eventSend - Send event(s)
  383. *
  384. * Sends specified event(s) to specified task. Passing a taskId of NULL sends 
  385. * events to the calling task.
  386. *
  387. * RETURNS:
  388. * OK on success or ERROR.
  389. *
  390. * ERRNO
  391. * .iP "S_objLib_OBJ_ID_ERROR"
  392. * Task ID is invalid.
  393. * .iP "S_eventLib_NULL_TASKID_AT_INT_LEVEL"
  394. * Routine was called from ISR with a taskId of NULL.
  395. *
  396. * SEE ALSO: eventReceive()
  397. */
  398. STATUS eventSend
  399.     (
  400.     int taskId, /* task events will be sent to */
  401.     UINT32 events /* events to send         */
  402.     )
  403.     {
  404.     WIND_TCB *pTcb;
  405.     UINT8 options;
  406.     UINT32 wanted;
  407.     UINT32 received;
  408.     int level;
  409.     if ((INT_CONTEXT()) && (taskId == (int)NULL))
  410. {
  411. errnoSet (S_eventLib_NULL_TASKID_AT_INT_LEVEL);
  412. return (ERROR);
  413. }
  414.     pTcb = (taskId == (int)NULL) ? taskIdCurrent : (WIND_TCB*)taskId;
  415.     level = intLock ();
  416.     if (TASK_ID_VERIFY (pTcb) != OK)
  417. intUnlock (level);
  418. return (ERROR);    /* errno is set by TASK_ID_VERIFY */
  419. }
  420. #ifdef WV_INSTRUMENTATION
  421.     /* windview - level 1 event logging */
  422.     EVT_OBJ_EVENT(EVENT_EVENTSEND, 2, taskId, events, 0);
  423. #endif /* WV_INSTRUMENTATION */
  424.     pTcb->events.received |= events;
  425.     /* if task is not waiting for events, work is done */
  426.     if (!(pTcb->events.sysflags & EVENTS_SYSFLAGS_WAITING))
  427. {
  428. intUnlock (level);
  429. return (OK);
  430. }
  431.     /* helps readability of code */
  432.     received = pTcb->events.received;
  433.     wanted   = pTcb->events.wanted;
  434.     options  = pTcb->events.options;
  435.     /*
  436.      * look for one of two scenarios: 
  437.      * (1) all events wanted have been received; or
  438.      * (2) some events received and waiting for any of them.
  439.      */
  440.     if (((wanted & received) == wanted) ||
  441. (((options & EVENTS_WAIT_MASK) == EVENTS_WAIT_ANY) &&
  442. ((wanted & received) != 0x0)))
  443. {
  444. /* received correct events: task is not waiting anymore... */
  445. pTcb->events.sysflags &= ~EVENTS_SYSFLAGS_WAITING;
  446. /* ...then put it back on the ready queue */
  447. if (kernelState)
  448.     {
  449.     intUnlock (level);
  450.     workQAdd1 ((FUNCPTR)eventPendQRemove, (int)pTcb);
  451.     return (OK);
  452.     }
  453. kernelState = TRUE;
  454. intUnlock (level);
  455. windPendQRemove (pTcb);
  456. #ifdef WV_INSTRUMENTATION
  457.     /* windview - level 2 event logging */
  458.     EVT_TASK_0(EVENT_OBJ_EVENTSEND);
  459. #endif /* WV_INSTRUMENTATION */
  460. windReadyQPut (pTcb);
  461. windExit ();
  462. return (OK);
  463. }
  464.     /* task is still waiting but everything went fine */
  465.     intUnlock (level);
  466.     return (OK);
  467.     }
  468. /*******************************************************************************
  469. *
  470. * eventPendQRemove - remove task from the pend Q and put it on ready Q
  471. *
  472. * Deferred removal from vxEventPendQ. Only executed as draining of the work Q.
  473. *
  474. * NOMANUAL
  475. */
  476. LOCAL void eventPendQRemove
  477.     (
  478.     WIND_TCB * pTcb
  479.     )
  480.     {
  481.     windPendQRemove (pTcb);
  482. #ifdef WV_INSTRUMENTATION
  483.     /* windview - level 2 event logging */
  484.     EVT_TASK_0(EVENT_OBJ_EVENTSEND);
  485. #endif /* WV_INSTRUMENTATION */
  486.     windReadyQPut   (pTcb);
  487.     }
  488. /*******************************************************************************
  489. *
  490. * eventRsrcSend - Send event(s) from a resource
  491. *
  492. * Sends specified event(s) to specified task.
  493. *
  494. * WARNING: Routine must be called with kernelState == TRUE.
  495. *
  496. * RETURNS:
  497. * OK on success or ERROR.
  498. *
  499. * ERRNO
  500. * .iP "S_objLib_OBJ_ID_ERROR"
  501. * Task ID is invalid.
  502. *
  503. * NOMANUAL
  504. */
  505. STATUS eventRsrcSend
  506.     (
  507.     int taskId, /* task events will be sent to */
  508.     UINT32 events /* events to send         */
  509.     )
  510.     {
  511.     WIND_TCB *pTcb;
  512.     UINT8 options;
  513.     UINT32 wanted;
  514.     UINT32 received;
  515.     int level;
  516.     pTcb = (WIND_TCB*)taskId;
  517.     level = intLock ();
  518.     if (TASK_ID_VERIFY (pTcb) != OK)
  519. intUnlock (level);
  520. return (ERROR);    /* errno is set by TASK_ID_VERIFY */
  521. }
  522. #ifdef WV_INSTRUMENTATION
  523.     /* windview - level 1 event logging */
  524.     EVT_OBJ_EVENT(EVENT_EVENTSEND, 2, taskId, events, 0);
  525. #endif /* WV_INSTRUMENTATION */
  526.     pTcb->events.received |= events;
  527.     /* if task is not waiting for events, work is done */
  528.     if ((pTcb->events.sysflags & EVENTS_SYSFLAGS_WAITING) == 0x0)
  529. {
  530. intUnlock (level);
  531. return (OK);
  532. }
  533.     /* helps readability of code */
  534.     received = pTcb->events.received;
  535.     wanted   = pTcb->events.wanted;
  536.     options  = pTcb->events.options;
  537.     /*
  538.      * look for one of two scenarios: 
  539.      * (1) all events wanted have been received; or
  540.      * (2) some events received and waiting for any of them.
  541.      */
  542.     if (((wanted & received) == wanted) ||
  543. (((options & EVENTS_WAIT_MASK) == EVENTS_WAIT_ANY) &&
  544. ((wanted & received) != 0x0)))
  545. {
  546. /* received correct events: task is not waiting anymore... */
  547. pTcb->events.sysflags &= ~EVENTS_SYSFLAGS_WAITING;
  548. /* ...then put it back on the ready queue */
  549. intUnlock (level);
  550. windPendQRemove (pTcb);
  551. #ifdef WV_INSTRUMENTATION
  552.     /* windview - level 2 event logging */
  553.     EVT_TASK_0(EVENT_OBJ_EVENTSEND);
  554. #endif /* WV_INSTRUMENTATION */
  555. windReadyQPut (pTcb);
  556. return (OK);
  557. }
  558.     /* task is still waiting but everything went fine */
  559.     intUnlock (level);
  560.     return (OK);
  561.     }
  562. /*******************************************************************************
  563. *
  564. * eventClear - Clear all events for current task.
  565. *
  566. * This function clears all received events for the calling task.
  567. *
  568. * RETURNS: OK on success or ERROR.
  569. *
  570. * ERRNO
  571. * .iP "S_intLib_NOT_ISR_CALLABLE"
  572. * Routine has been called from interrupt level.
  573. *
  574. * SEE ALSO: 
  575. */
  576. STATUS eventClear
  577.     (
  578.     void
  579.     )
  580.     {
  581.     if (INT_RESTRICT () != OK)
  582. return (ERROR);    /* errno set by INT_RESTRICT() */
  583.     /* if task is currently receiving events, abort */
  584.     taskIdCurrent->events.received = 0x0;
  585.     return (OK);
  586.     }
  587. /*******************************************************************************
  588. *
  589. * eventStart - Common code for resource registration
  590. *
  591. * NOTE: Routine must be called with TASK_LOCK() already done. This function is
  592. * responsible for doing the TASK_UNLOCK().
  593. *
  594. * RETURNS: OK on success or ERROR.
  595. *
  596. * ERRNO
  597. * .iP "S_eventLib_ALREADY_REGISTERED"
  598. * A task is already registered.
  599. * .iP "S_eventLib_EVENTSEND_FAILED"
  600. * A bad taskId was passed to eventSend().
  601. *
  602. * NOMANUAL
  603. */
  604. STATUS eventStart
  605.     (
  606.     OBJ_ID objId, /* resource on which to register events  */
  607.     EVENTS_RSRC * pRsrc,/* ptr to resource control block  */
  608.     FUNCPTR isRsrcFree, /* ptr to fcn determining if rsrc is free*/
  609.     UINT32 events,  /* 32 possible events to register        */
  610.     UINT8 options /* event-related resource options  */
  611.     )
  612.     {
  613.     int level; /* interrupt lock level */
  614.     /*
  615.      * Refuse to register if another task has already done so, but only if
  616.      * the EVENTS_ALLOW_OVERWRITE option is not in use AND if the task trying
  617.      * to do the registration is not the one currently registered.
  618.      */
  619.     if ((pRsrc->options & EVENTS_ALLOW_OVERWRITE) != EVENTS_ALLOW_OVERWRITE)
  620. {
  621. if ((pRsrc->taskId!=(int)NULL) && (pRsrc->taskId != (int)taskIdCurrent))
  622.     {
  623.     TASK_UNLOCK ();
  624.     errnoSet (S_eventLib_ALREADY_REGISTERED);
  625.     return (ERROR);
  626.     }
  627. }
  628.     /* check if user wants to send events */
  629.     level = intLock ();
  630.     if ((options & EVENTS_SEND_IF_FREE) == EVENTS_SEND_IF_FREE)
  631. {
  632. /* find out if resource is free */
  633. if (isRsrcFree (objId))
  634.     {
  635.     intUnlock (level);
  636.     /* only register if user didn't choose one shot */
  637.     if ((options & EVENTS_SEND_ONCE) != EVENTS_SEND_ONCE)
  638. {
  639. pRsrc->registered = events;
  640. pRsrc->options    = options;
  641. pRsrc->taskId     = (int)taskIdCurrent;
  642. }
  643.     else
  644. pRsrc->taskId   = (int) NULL;
  645.     TASK_UNLOCK ();
  646.     if (eventSend ((int)taskIdCurrent, events) != OK)
  647. {
  648. errnoSet (S_eventLib_EVENTSEND_FAILED);
  649. return (ERROR);
  650. }
  651.     else
  652. return (OK);
  653.     }
  654. }
  655.     /*
  656.      * resource not free or user chose not to send events right away:
  657.      * register needed info
  658.      */
  659.     pRsrc->registered = events;
  660.     pRsrc->options    = options;
  661.     pRsrc->taskId     = (int)taskIdCurrent;
  662.     intUnlock (level);
  663.     TASK_UNLOCK ();
  664.     return (OK);
  665.     }