📄 eventlib.c
字号:
/* eventLib.c - VxWorks events library *//* Copyright 2001-2003 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01e,13nov02,bwa Fix bad signal handling when task waiting for events (SPR 83740). Added option to allow not to clear unwanted events in a call to eventReceive() (SPR 84417).01d,09nov01,aeg changed eventPendQ to global symbol vxEventPendQ for WindSh; fixed problem in eventStart() where a re-registration would not delete the previous one.01c,30oct01,bwa Corrected use of windview instrumentation for task-state transition logging. Added eventRsrcSend().01b,25oct01,tcr remove #undef WV_INSTRUMENTATION01a,20sep01,bwa written*//*DESCRIPTIONEvents are a means of communication between tasks and interrupt routines,based on a synchronous model. Only tasks can receive events, and both tasksand ISRs can send them.Events are similar to signals in that they are directed at one task but differin the fact that they are synchronous in nature. Thus, the receiving task mustpend when waiting for events to occur. Also, unlike signals, a handler is notneeded since, when wanted events are received, the pending task continues itsexecution (like after a call to msgQReceive() or semTake()).Each task has its own events field that can be filled by having tasks (evenitself) and/or ISRs sending events to the task. Each event's meaning isdifferent for every task. Event X when received can be interpreted differentlyby separate tasks. Also, it should be noted that events are not accumulated.If the same event is received several times, it counts as if it were receivedonly once. It is not possible to track how many times each event has been sent to a task.There are some VxWorks objects that can send events when they become available.They are referred to as 'resources' in the context of events. They includesemaphores and message queues. For example, when a semaphore becomes free,events can be sent to a task that asked for it.INTERNAL: WINDVIEW INSTRUMENTATIONLevel 1: eventSend () causes EVENT_EVENTSEND eventReceive() causes EVENT_EVENTRECEIVELevel 2: eventSend () causes EVENT_OBJ_EVENTSEND eventReceive () causes EVENT_OBJ_EVENTRECEIVELevel 3: N/AINCLUDE FILES: eventLib.hSEE ALSO: taskLib, semLib, semBLib, semCLib, semMLib, msgQLib,<VxWorks Programmer's Guide: Basic OS>*//* includes */#include "vxWorks.h"#include "qLib.h"#include "taskLib.h"#include "intLib.h"#include "errnoLib.h"#include "eventLib.h"#include "taskArchLib.h"#include "private/workQLibP.h"#include "private/eventLibP.h"#include "private/kernelLibP.h"#include "private/windLibP.h"#include "private/sigLibP.h"#include "private/taskLibP.h"/* function prototypes */LOCAL void eventPendQRemove (WIND_TCB * pTcb);/* globals */Q_HEAD vxEventPendQ;#ifdef WV_INSTRUMENTATIONVOIDFUNCPTR eventEvtRtn; /* windview - level 1 event logging */#endif/********************************************************************************* eventLibInit - Initialize events library** Initialize the pending queue that will be used for all event operations.* This routine is called automatically when the events module is included.** NOMANUAL*/void eventLibInit (void) { qInit (&vxEventPendQ, Q_FIFO); }/********************************************************************************* eventInit - initializes event-related info for a resource** Initializes event-related data for a given resource. It shouldn't be used* outside of resource initialization.** NOMANUAL*/void eventInit ( EVENTS_RSRC * evRsrc ) { evRsrc->taskId = (int)NULL; evRsrc->registered = 0x0; evRsrc->options = 0x0; }/********************************************************************************* eventTerminate - Terminate event-related operations for a resource** Wakes up task waiting on events that should be sent from a resource.** WARNING: - This function shouldn't be used outside of resource destruction.* - Function must be called with kernelState == TRUE** NOMANUAL*/void eventTerminate ( const EVENTS_RSRC * evRsrc ) { WIND_TCB * pTcb = (WIND_TCB *)evRsrc->taskId; if (pTcb != NULL) { int level; /* * must intLock to prevent an ISR from doing an eventSend that also * wakes up the task. */ level = intLock (); if (TASK_ID_VERIFY(pTcb) != OK) { intUnlock (level); return; } /* only wakeup task if it is waiting */ if (pTcb->events.sysflags & EVENTS_SYSFLAGS_WAITING) { /* task will not be waiting anymore */ pTcb->events.sysflags &= ~EVENTS_SYSFLAGS_WAITING; intUnlock (level); /* remove task from the pend Q and put it back on the ready Q */ if ((pTcb->status & WIND_PEND) == WIND_PEND) { windPendQRemove (pTcb); windReadyQPut (pTcb); /* * windExit() will return ERROR: errorStatus is set so that * task will know what caused the error */ taskRtnValueSet (pTcb, ERROR); pTcb->errorStatus = S_objLib_OBJ_DELETED; } else { /* * The task that is waiting for events from the resource * is executing a signal handler that is deleting the * resource */ pTcb->events.sysflags |= EVENTS_SYSFLAGS_DEL_RSRC; } } else intUnlock (level); } }/********************************************************************************* eventReceive - Wait for event(s)** Pends task until one or all specified <events> have occurred. When* they have, <pEventsReceived> will be filled with those that did occur.** The <options> parameter is used for four user options. Firstly, it is used * to specify if the task is going to wait for all events to occur or only one * of them. One of the following has to be selected:* .iP "EVENTS_WAIT_ANY (0x1)"* only one event has to occur* .iP "EVENTS_WAIT_ALL (0x0)"* will wait until all events occur.* .LP* Secondly, it is used to specify if the events returned in <pEventsReceived>* will be only those received and wanted, or all events received (even the* ones received before eventReceive() was called). By default it returns* only the events wanted.* .iP "EVENTS_RETURN_ALL (0x2)"* When this option is turned on, it causes the function to return received* events, both wanted and unwanted. All events are cleared when this option* is selected.* .LP* Thirdly, the user can specify if the events received but not wanted are to* be cleared or not in the calling task's events register. They are cleared* by default. Wanted events are always cleared.* .iP "EVENTS_KEEP_UNWANTED (0x4)"* Tells the system not to clear the unwanted events. In the case that the* option EVENTS_RETURN_ALL is used, all events are cleared even if this one* is selected.* .LP* Lastly, it can be used to retrieve what events have been received by the* current task.* .iP "EVENTS_FETCH (0x80)"* If this option is set, then <pEventsReceived> will be filled with the events* that have already been received and will return immediately. In this case,* the parameters <events> and <timeout>, as well as all the other options, are* ignored. Also, events are not cleared, allowing to get a peek at the events* that have already been received.* .LP** The <timeout> parameter specifies the number of ticks to wait for wanted* events to be sent to the waiting task. It can also have the following * special values:* .iP "NO_WAIT (0)"* return immediately, even if no events have arrived.* .iP "WAIT_FOREVER (-1)"* never time out.* .LP** The parameter <pEventsReceived> is always filled with the events received* even when the function returns an error, except if a value of NULL was* passed.** WARNING: This routine may not be used from interrupt level.** RETURNS:* OK on success or ERROR.** ERRNO* .iP "S_eventLib_TIMEOUT"* Wanted events not received before specified time expired.* .iP "S_eventLib_NOT_ALL_EVENTS"* Specified NO_WAIT as the timeout parameter and wanted events were not already* received when the routine was called.* .iP "S_objLib_OBJ_DELETED"* Task is waiting for some events from a resource that is subsequently deleted.* .iP "S_intLib_NOT_ISR_CALLABLE"* Function has been called from ISR.* .iP "S_eventLib_ZERO_EVENTS"* The <events> parameter has been passed a value of 0.** SEE ALSO: semEvLib, msgQEvLib, eventSend()*/STATUS eventReceive ( UINT32 events, /* events task is waiting to occur */ UINT8 options, /* user options */ int timeout, /* ticks to wait */ UINT32 *pEventsReceived /* events occured are returned through this */ ) { int level; STATUS status; UINT32 received; if (INT_RESTRICT () != OK) return (ERROR); /* special case: only return received events */ if (options & EVENTS_FETCH) { if (pEventsReceived != NULL) *pEventsReceived = taskIdCurrent->events.received; return (OK); } if (events == 0x0) { errnoSet (S_eventLib_ZERO_EVENTS); return ERROR; }#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging */ EVT_OBJ_EVENT(EVENT_EVENTRECEIVE, 3, events, timeout, options);#endif /* WV_INSTRUMENTATION */again: /* * This caching of value is done to reduce the amount of time we spend * with the interrupts locked. If not used, the whole function has to * be within an intLock()...intUnlock() pair. */ /* * Caching the value causes a compiler warning since we remove the * volatile property of the structure member. This is what we want to * achieve so that error must NOT be corrected. */ received = taskIdCurrent->events.received; /* check if wanted events have not already been received */ if ((options & EVENTS_WAIT_MASK) == EVENTS_WAIT_ALL) { /* * In the case that ALL events are wanted, all the events must already * have been received. */ if ((events & received) == events) { /* only return events if user passed a valid return container */ level = intLock (); if (pEventsReceived != NULL) { if (options & EVENTS_RETURN_ALL) *pEventsReceived = taskIdCurrent->events.received; else *pEventsReceived = events; } /* clear events */ if (!(options & EVENTS_KEEP_UNWANTED) || (options & EVENTS_RETURN_ALL)) { taskIdCurrent->events.received = 0x0; } else taskIdCurrent->events.received &= ~events; intUnlock (level); return (OK); } } else { /* * In the case that ANY events are wanted, if even only one of them has * already been received, we have what we wanted. */ if ((events & received) != 0x0) { /* only return events if user passed a valid return container */ level = intLock (); if (pEventsReceived != NULL) { if (options & EVENTS_RETURN_ALL) *pEventsReceived = taskIdCurrent->events.received; else *pEventsReceived = events & taskIdCurrent->events.received; } /* clear events */ if (!(options & EVENTS_KEEP_UNWANTED) || (options & EVENTS_RETURN_ALL)) { taskIdCurrent->events.received = 0x0; } else taskIdCurrent->events.received &= ~events; intUnlock (level); return (OK); } } /* if we got here, we have not already received the events we wanted */ /* look if events have been received while we were not intLocked */ level = intLock (); if (taskIdCurrent->events.received != received) { intUnlock (level); goto again; } /* * if we do not want to wait, no more events will be received so the * request is not satisfied. */ if (timeout == NO_WAIT) { /* only return events if user passed a valid return container */ if (pEventsReceived != NULL) { if (options & EVENTS_RETURN_ALL) *pEventsReceived = taskIdCurrent->events.received; else *pEventsReceived = events & taskIdCurrent->events.received; } /* clear events */ if (!(options & EVENTS_KEEP_UNWANTED) || (options & EVENTS_RETURN_ALL)) taskIdCurrent->events.received = 0x0; else taskIdCurrent->events.received &= ~events; intUnlock (level); errnoSet (S_eventLib_NOT_ALL_EVENTS); return (ERROR); } /* We want to wait: fill needed fields */ taskIdCurrent->events.options = options; taskIdCurrent->events.wanted = events; taskIdCurrent->events.sysflags = EVENTS_SYSFLAGS_WAITING; kernelState = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -