📄 msgqlib.c
字号:
/* msgQLib.c - message queue library *//* Copyright 1990-2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------02n,10dec01,bwa Added comment about MSG_Q_EVENTSEND_ERR_NOTIFY msgQCreate option (SPR 72058).02m,26oct01,bwa Added msgQEvLib and eventLib to the list of 'SEE ALSO' modules.02l,12oct01,cjj Added documentation regarding S_eventLib_EVENTSEND_FAILED error02k,09oct01,gls merged in 02j, 02i, 02h, 02g below from AE.02j,22feb01,ahm ensured errno does'nt change if msgQDelete() is successful (SPR#34643)02i,19sep00,bwa passed extra argument (msgQid) to calls to qJobGet() added errnoSet after calls to qJobGet()(SPR #34057) 02h,06sep00,aeg doc: mentioned INCLUDE_MSG_Q component name.02g,11aug00,aeg fixed updating of timeout stats in msgQSend/Receive (SPR 33683)02f,07sep01,bwa Added VxWorks events support. Fixed SPR #31241 (corrected msgQReceive comment for NO_WAIT).02e,18dec00,pes Correct compiler warnings02d,19may98,drm merged code from 3rd party to add distributed message queue support. - merged code was originally based on version 02a 02c,11may98,cjtc fix problem with problem fix!! Multiple calls to object instrumentation in msgQDestroy02b,11may98,nps fixed msgQDestroy instrumentation anomaly.02c,17apr98,rlp canceled msgQInit and msgQSend modifications for backward compatibility.02b,04nov97,rlp modified msgQInit and msgQSend for tracking messages sent.02a,24jun96,sbs made windview instrumentation conditionally compiled01z,22oct95,jdi doc: added bit values for options (SPR 4276).02d,14apr94,smb fixed class dereferencing for instrumentation macros02c,15mar94,smb modified instrumentation macros02b,24jan94,smb added instrumentation macros02a,18jan94,smb added instrumentation corrections for msgQDelete01z,10dec93,smb added instrumentation01y,30jun93,jmm changed msgQDestroy to look at msgQ as well as freeQ (spr 2070)01x,02feb93,jdi documentation cleanup for 5.1.01w,13nov92,jcf package init called with object creation.01v,19oct92,pme added reference to shared message queue documentation.01u,23aug92,jcf balanced taskSafe with taskUnsafe.01t,11aug92,jcf fixed msgQDestroy safety problem.01s,30jul92,rrr added restart and msgQ fix01r,29jul92,pme added NULL function pointer check for smObj routines.01q,29jul92,jcf package init called with object initialization.01p,22jul92,pme made msgQDestroy return S_smObjLib_NO_OBJECT_DESTROY when trying to destroy a shared message queue.01o,19jul92,pme added shared message queue support.01n,18jul92,smb Changed errno.h to errnoLib.h.01m,04jul92,jcf show routine removed.01l,26may92,rrr the tree shuffle01k,13dec91,gae ANSI fixes. 01j,19nov91,rrr shut up some ansi warnings.01i,04oct91,rrr passed through the ansification filter -changed functions to ansi style -changed includes to have absolute path from h/ -changed VOID to void -changed copyright notice01h,10aug91,del changed interface to qInit to pass all "optional" args.01g,05apr91,jdi documentation -- removed header parens and x-ref numbers; doc review by dnw.01f,22jan91,jaa documentation.01e,08oct90,dnw lint01d,01oct90,dnw fixed bug of msgQSend() not returning ERROR on timeout. removed msgQSendArgs()/ReceiveArgs(). reordered parameters of msgQ{Send,Receive}(). simplified msgQInfoGet() interface. added msgQNumMsgs(). made msgQDestroy() LOCAL. made msgQ{LibInit,Init,Terminate}() be NOMANUAL. finished documentation.01c,19jul90,dnw added VARARGS to msgQ{Send,Receive}Args()01b,19jul90,dnw changed call to objAlloc() to objAllocExtra() made msgQShow() prettier lint01a,10may90,dnw written*//*DESCRIPTIONThis library contains routines for creating and using message queues, the primary intertask communication mechanism within a single CPU. Messagequeues allow a variable number of messages (varying in length) to bequeued in first-in-first-out (FIFO) order. Any task or interrupt serviceroutine can send messages to a message queue. Any task can receivemessages from a message queue. Multiple tasks can send to and receivefrom the same message queue. Full-duplex communication between two tasksgenerally requires two message queues, one for each direction.To provide message queue support for a system, VxWorks must be configuredwith the INCLUDE_MSG_Q component.CREATING AND USING MESSAGE QUEUESA message queue is created with msgQCreate(). Its parameters specify themaximum number of messages that can be queued to that message queue and the maximum length in bytes of each message. Enough buffer space will be pre-allocated to accommodate the specified number of messages of specified length.A task or interrupt service routine sends a message to a message queuewith msgQSend(). If no tasks are waiting for messages on the message queue,the message is simply added to the buffer of messages for that queue.If any tasks are already waiting to receive a message from the messagequeue, the message is immediately delivered to the first waiting task.A task receives a message from a message queue with msgQReceive().If any messages are already available in the message queue's buffer,the first message is immediately dequeued and returned to the caller.If no messages are available, the calling task will block and be added toa queue of tasks waiting for messages. This queue of waiting tasks canbe ordered either by task priority or FIFO, as specified in an optionparameter when the queue is created.TIMEOUTSBoth msgQSend() and msgQReceive() take timeout parameters. When sending amessage, if no buffer space is available to queue the message, the timeoutspecifies how many ticks to wait for space to become available. Whenreceiving a message, the timeout specifies how many ticks to wait if nomessage is immediately available. The <timeout> parameter canhave the special values NO_WAIT (0) or WAIT_FOREVER (-1). NO_WAIT means the routine should return immediately; WAIT_FOREVER means the routineshould never time out.URGENT MESSAGESThe msgQSend() routine allows the priority of a message to be specifiedas either normal or urgent, MSG_PRI_NORMAL (0) and MSG_PRI_URGENT (1),respectively. Normal priority messages are added to the tail of the listof queued messages, while urgent priority messages are added to the headof the list.VXWORKS EVENTSIf a task has registered with a message queue via msgQEvStart(), events willbe sent to that task when a message arrives on that message queue, on thecondition that no other task is pending on the queue.INTERNAL: WINDVIEW INSTRUMENTATIONLevel 1: msgQCreate() causes EVENT_MSGQCREATE msgQDestroy() causes EVENT_MSGQDELETE msgQSend() causes EVENT_MSGQSEND msgQReceive() causes EVENT_MSGQRECEIVELevel 2: N/ALevel 3: N/AINCLUDE FILES: msgQLib.hSEE ALSO: pipeDrv, msgQSmLib, msgQEvLib, eventLib,.pG "Basic OS"*/#include "vxWorks.h"#include "stdlib.h"#include "string.h"#include "taskLib.h"#include "intLib.h"#include "smObjLib.h"#include "errnoLib.h"#include "private/eventLibP.h"#include "private/classLibP.h"#include "private/objLibP.h"#include "private/msgQLibP.h"#include "private/msgQSmLibP.h"#include "private/distObjTypeP.h"#include "private/sigLibP.h"#include "private/eventP.h"#include "private/windLibP.h"#include "private/kernelLibP.h"/* locals */LOCAL OBJ_CLASS msgQClass;/* globals */CLASS_ID msgQClassId = &msgQClass;/* Instrumentation locals and globals */#ifdef WV_INSTRUMENTATIONLOCAL OBJ_CLASS msgQInstClass;CLASS_ID msgQInstClassId = &msgQInstClass;#endif/* shared memory objects function pointers */FUNCPTR msgQSmSendRtn;FUNCPTR msgQSmReceiveRtn;FUNCPTR msgQSmNumMsgsRtn;/* distributed objects function pointers */FUNCPTR msgQDistSendRtn;FUNCPTR msgQDistReceiveRtn;FUNCPTR msgQDistNumMsgsRtn;/* forward declarations */LOCAL STATUS msgQDestroy (MSG_Q_ID msgQId, BOOL dealloc);/* locals */LOCAL BOOL msgQLibInstalled; /* protect from muliple inits *//********************************************************************************* msgQLibInit - initialize message queue library** This routine initializes message queue facility.* It is called once in kernelInit().** RETURNS: OK or ERROR** NOMANUAL*/STATUS msgQLibInit (void) { /* initialize shared memory objects function pointers */ if (!msgQLibInstalled) { if (classInit (msgQClassId, sizeof (MSG_Q), OFFSET (MSG_Q, objCore), (FUNCPTR)msgQCreate, (FUNCPTR)msgQInit, (FUNCPTR)msgQDestroy) == OK) {#ifdef WV_INSTRUMENTATION /* Instrumented class for windview */ msgQClassId->initRtn = msgQInstClassId; classInstrument (msgQClassId,msgQInstClassId);#endif msgQEvLibInit (); /* pull msgQLib in kernel */ msgQLibInstalled = TRUE; } } return ((msgQLibInstalled) ? OK : ERROR); }/********************************************************************************* msgQCreate - create and initialize a message queue** This routine creates a message queue capable of holding up to <maxMsgs>* messages, each up to <maxMsgLength> bytes long. The routine returns * a message queue ID used to identify the created message queue in all * subsequent calls to routines in this library. The queue can be created * with the following options:* .iP "MSG_Q_FIFO (0x00)" 8* queue pended tasks in FIFO order.* .iP "MSG_Q_PRIORITY (0x01)"* queue pended tasks in priority order.* .iP "MSG_Q_EVENTSEND_ERR_NOTIFY (0x02)"* When a message is sent, if a task is registered for events and the* actual sending of events fails, a value of ERROR is returned and the errno* is set accordingly. This option is off by default.* .LP** RETURNS:* MSG_Q_ID, or NULL if error.** ERRNO: S_memLib_NOT_ENOUGH_MEMORY, S_intLib_NOT_ISR_CALLABLE** SEE ALSO: msgQSmLib*/MSG_Q_ID msgQCreate ( int maxMsgs, /* max messages that can be queued */ int maxMsgLength, /* max bytes in a message */ int options /* message queue options */ ) { MSG_Q_ID msgQId; void * pPool; /* pointer to memory for messages */ UINT size = (UINT) maxMsgs * MSG_NODE_SIZE (maxMsgLength); if (INT_RESTRICT () != OK) /* restrict ISR from calling */ return (NULL); if ((!msgQLibInstalled) && (msgQLibInit () != OK)) return (NULL); /* package init problem */ if ((msgQId = (MSG_Q_ID)objAllocExtra (msgQClassId, size, &pPool)) == NULL) return (NULL); if (msgQInit (msgQId, maxMsgs, maxMsgLength, options, pPool) != OK) { objFree (msgQClassId, (char *) msgQId); return (NULL); }#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging routine */ EVT_OBJ_4 (OBJ, msgQId, msgQClassId, EVENT_MSGQCREATE, msgQId, maxMsgs, maxMsgLength, options);#endif return ((MSG_Q_ID) msgQId); }/********************************************************************************* msgQInit - initialize a message queue** This routine initializes a message queue data structure. Like msgQCreate()* the resulting message queue is capable of holding up to <maxMsgs> messages,* each of up to <maxMsgLength> bytes long.* However, instead of dynamically allocating the MSG_Q data structure,* this routine takes a pointer <pMsgQ> to the MSG_Q data structure to be* initialized, and a pointer <pMsgPool> to the buffer to be use to hold* queued messages. <pMsgPool> must point to a 4 byte aligned buffer* that is (<maxMsgs> * MSG_NODE_SIZE (<maxMsgLength>)).** The queue can be created with the following options:** MSG_Q_FIFO queue pended tasks in FIFO order* MSG_Q_PRIORITY queue pended tasks in priority order** RETURNS: OK or ERROR.** ERRNO: S_msgQLib_INVALID_QUEUE_TYPE** SEE ALSO: msgQCreate()** NOMANUAL*/STATUS msgQInit ( FAST MSG_Q *pMsgQ, /* pointer to msg queue to initialize */ int maxMsgs, /* max messages that can be queued */ int maxMsgLength, /* max bytes in a message */ int options, /* message queue options */ void * pMsgPool /* pointer to memory for messages */ ) { FAST int nodeSize = MSG_NODE_SIZE (maxMsgLength); FAST int ix; FAST Q_CLASS_ID msgQType; if ((!msgQLibInstalled) && (msgQLibInit () != OK)) return (ERROR); /* package init problem */ bzero ((char *) pMsgQ, sizeof (*pMsgQ)); /* clear out msg q structure */ /* initialize internal job queues */ switch (options & MSG_Q_TYPE_MASK) { case MSG_Q_FIFO: msgQType = Q_FIFO; break; case MSG_Q_PRIORITY: msgQType = Q_PRI_LIST; break; default: errnoSet (S_msgQLib_INVALID_QUEUE_TYPE); return (ERROR); } if ((qInit ((Q_HEAD *) &pMsgQ->msgQ, qJobClassId, msgQType, 0, 0, 0, 0, 0, 0, 0, 0, 0) != OK) || (qInit ((Q_HEAD *) &pMsgQ->freeQ, qJobClassId, msgQType, 0, 0, 0, 0, 0, 0, 0, 0, 0) != OK)) return (ERROR); /* put msg nodes on free list */ for (ix = 0; ix < maxMsgs; ix++) { qJobPut (pMsgQ, &pMsgQ->freeQ, (Q_JOB_NODE *) pMsgPool, Q_JOB_PRI_DONT_CARE); pMsgPool = (void *) (((char *) pMsgPool) + nodeSize); } /* initialize rest of msg q */ pMsgQ->options = options; pMsgQ->maxMsgs = maxMsgs; pMsgQ->maxMsgLength = maxMsgLength; eventInit (&pMsgQ->events);#ifdef WV_INSTRUMENTATION if (wvObjIsEnabled) { /* windview - connect level 1 event logging routine */ objCoreInit (&pMsgQ->objCore, msgQInstClassId); } else#endif objCoreInit (&pMsgQ->objCore, msgQClassId); return (OK); }/******************************************************************************** msgQTerminate - terminate message queue** This routine terminates a static message queue that was initialized with* msgQInit.** RETURNS: OK or ERROR.** NOMANUAL*/STATUS msgQTerminate ( MSG_Q_ID msgQId /* message queue id to terminate */ ) { return (msgQDestroy (msgQId, FALSE)); }/********************************************************************************* msgQDelete - delete a message queue** This routine deletes a message queue. All tasks pending on either* msgQSend(), msgQReceive() or pending for the reception of events* meant to be sent from the message queue will unblock and return* ERROR. When this function returns, <msgQId> is no longer a valid * message queue ID.** RETURNS: OK on success or ERROR otherwise.** ERRNO:* .iP "S_objLib_OBJ_ID_ERROR"* Message queue ID is invalid* .iP "S_intLib_NOT_ISR_CALLABLE"* Routine cannot be called from ISR* .iP "S_distLib_NO_OBJECT_DESTROY"* Deleting a distributed message queue is not permitted* .iP "S_smObjLib_NO_OBJECT_DESTROY"* Deleting a shared message queue is not permitted* SEE ALSO: msgQSmLib*/STATUS msgQDelete ( MSG_Q_ID msgQId /* message queue to delete */ ) { return (msgQDestroy (msgQId, TRUE)); }/********************************************************************************* msgQDestroy - destroy message queue** RETURNS: OK or ERROR.** ERRNO: S_distLib_NO_OBJECT_DESTROY**/LOCAL STATUS msgQDestroy ( MSG_Q_ID msgQId, /* message queue to destroy */ BOOL dealloc /* deallocate memory associated with message queue */ ) { Q_JOB_NODE *pNode; FAST int timeout; FAST int nMsgs; int errnoCopy;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -