📄 eventlib.c
字号:
/* eventLib.c - VxWorks events library *//* Copyright 2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------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"/* 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 */ 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 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 three 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. Performing a bitwise-OR of the following: * .iP "EVENTS_RETURN_ALL (0x2)"* causes the function to return received events, both wanted and unwanted.* .LP* Thirdly, it can be used to retrieve what events have been received by the* current task. If the option* .iP "EVENTS_FETCH (0x80)"* is chosen by the user, 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** It must also be noted that events sent to the receiving task are cleared* prior to returning, as if a call to eventClear() was done.** 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 */ taskIdCurrent->events.received = 0x0; 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 */ taskIdCurrent->events.received = 0x0; 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 */ taskIdCurrent->events.received = 0x0; 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; intUnlock (level);#ifdef WV_INSTRUMENTATION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -