?? msgqlib.c
字號:
if (ID_IS_SHARED (msgQId)) /* message Q is shared?*/ { if (ID_IS_DISTRIBUTED (msgQId)) /* message queue is distributed? */ { errno = S_distLib_NO_OBJECT_DESTROY; return (ERROR); /* cannot delete distributed msgQ */ } errno = S_smObjLib_NO_OBJECT_DESTROY; return (ERROR); /* cannot delete sm. msgQ */ } if (INT_RESTRICT () != OK) /* restrict isr use */ return (ERROR); TASK_SAFE (); /* TASK SAFE */ TASK_LOCK (); /* LOCK PREEMPTION */#ifdef WV_INSTRUMENTATION /* Indicate that msgQDelete has been initiated */ /* windview - level 1 event logging routine */ EVT_OBJ_1 (OBJ, msgQId, msgQClassId, EVENT_MSGQDELETE, msgQId);#endif if (OBJ_VERIFY (msgQId, msgQClassId) != OK) /* validate message queue id */ { TASK_UNLOCK (); /* UNLOCK PREEMPTION */ TASK_UNSAFE (); /* TASK UNSAFE */ return (ERROR); } objCoreTerminate (&msgQId->objCore); /* INVALIDATE */#ifdef WV_INSTRUMENTATION /* Indicate that the msgQDelete has succeeded (before TASK_UNLOCK, as * that causes unnecessary WV parser confusion). */ /* windview - level 2 instrumentation * EVENT_OBJ_MSGDELETE needs to return the msgQId so MSG_OFFSET is * used to calulate the msgQId from the pQHead */ EVT_TASK_1 (EVENT_OBJ_MSGDELETE, msgQId);#endif TASK_UNLOCK (); /* UNLOCK PREEMPTION */ /* gobble up all messages in the message and free queues */ timeout = NO_WAIT; /* first time through gobble without waiting */ nMsgs = 0; errnoCopy = errnoGet (); while (nMsgs < msgQId->maxMsgs) { while (((pNode = qJobGet (msgQId, &msgQId->freeQ, timeout)) != NULL) && (pNode != (Q_JOB_NODE *) NONE)) nMsgs++; while (((pNode = qJobGet (msgQId, &msgQId->msgQ, timeout)) != NULL) && (pNode != (Q_JOB_NODE *) NONE)) nMsgs++; timeout = 1; /* after first time, wait a bit */ } errnoSet (errnoCopy); /* terminate both the queues */ /* * Since eventTerminate() can wake up a task, we want to put all tasks * in the ready queue before doing a windExit(), so that it is sure that * the task of highest priority runs first. To achieve that, the * statements 'kernelState = TRUE;' and 'windExit();' have been moved * from qJobTerminate() to here. This is the only place that qJobTerminate * is called. */ kernelState = TRUE; qJobTerminate (&msgQId->msgQ); qJobTerminate (&msgQId->freeQ); eventTerminate (&msgQId->events);/* free task waiting for events if any */ windExit (); if (dealloc) objFree (msgQClassId, (char *) msgQId); TASK_UNSAFE (); /* TASK UNSAFE */ return (OK); }/********************************************************************************* msgQSend - send a message to a message queue** This routine sends the message in <buffer> of length <nBytes> to the message* queue <msgQId>. If any tasks are already waiting to receive messages* on the queue, the message will immediately be delivered to the first* waiting task. If no task is waiting to receive messages, the message* is saved in the message queue and if a task has previously registered to * receive events from the message queue, these events are sent in the context * of this call. This may result in the unpending of the task waiting for * the events. If the message queue fails to send events and if it was * created using the MSG_Q_EVENTSEND_ERR_NOTIFY option, ERROR is returned * even though the send operation was successful.** The <timeout> parameter specifies the number of ticks to wait for free* space if the message queue is full. The <timeout> parameter can also have * the following special values:* .iP "NO_WAIT (0)" 8* return immediately, even if the message has not been sent. * .iP "WAIT_FOREVER (-1)"* never time out.* .LP** The <priority> parameter specifies the priority of the message being sent.* The possible values are:* .iP "MSG_PRI_NORMAL (0)" 8* normal priority; add the message to the tail of the list of queued * messages.* .iP "MSG_PRI_URGENT (1)"* urgent priority; add the message to the head of the list of queued messages.* .LP** USE BY INTERRUPT SERVICE ROUTINES* This routine can be called by interrupt service routines as well as* by tasks. This is one of the primary means of communication* between an interrupt service routine and a task. When called from an* interrupt service routine, <timeout> must be NO_WAIT.** RETURNS: OK on success or ERROR otherwise.** ERRNO:* .iP "S_distLib_NOT_INITIALIZED"* Distributed objects message queue library (VxFusion) not initialized.* .iP "S_smObjLib_NOT_INITIALIZED"* Shared memory message queue library (VxMP Option) not initialized.* .iP "S_objLib_OBJ_ID_ERROR"* Invalid message queue ID.* .iP "S_objLib_OBJ_DELETED"* Message queue deleted while calling task was pended.* .iP "S_objLib_OBJ_UNAVAILABLE"* No free buffer space when NO_WAIT timeout specified.* .iP "S_objLib_OBJ_TIMEOUT"* Timeout occurred while waiting for buffer space.* .iP "S_msgQLib_INVALID_MSG_LENGTH"* Message length exceeds limit.* .iP "S_msgQLib_NON_ZERO_TIMEOUT_AT_INT_LEVEL"* Called from ISR with non-zero timeout.* .iP "S_eventLib_EVENTSEND_FAILED"* Message queue failed to send events to registered task. This errno * value can only exist if the message queue was created with the * MSG_Q_EVENTSEND_ERR_NOTIFY option.* .LP** SEE ALSO: msgQSmLib, msgQEvStart*/STATUS msgQSend ( FAST MSG_Q_ID msgQId, /* message queue on which to send */ char * buffer, /* message to send */ FAST UINT nBytes, /* length of message */ int timeout, /* ticks to wait */ int priority /* MSG_PRI_NORMAL or MSG_PRI_URGENT */ ) { FAST MSG_NODE * pMsg; if (ID_IS_SHARED (msgQId)) /* message Q is shared? */ { if (ID_IS_DISTRIBUTED (msgQId)) /* message queue is distributed? */ { if (msgQDistSendRtn == NULL) { errno = S_distLib_NOT_INITIALIZED; return (ERROR); } return ((*msgQDistSendRtn) (msgQId, buffer, nBytes, timeout, WAIT_FOREVER, priority)); } if (msgQSmSendRtn == NULL) { errno = S_smObjLib_NOT_INITIALIZED; return (ERROR); } return ((*msgQSmSendRtn) (SM_OBJ_ID_TO_ADRS (msgQId), buffer, nBytes, timeout, priority)); } /* message queue is local */ if (!INT_CONTEXT ()) TASK_LOCK (); else { if (timeout != 0) { errnoSet (S_msgQLib_NON_ZERO_TIMEOUT_AT_INT_LEVEL); return (ERROR); } }restart: if (OBJ_VERIFY (msgQId, msgQClassId) != OK) { if (!INT_CONTEXT ()) TASK_UNLOCK (); return (ERROR); }#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging routine */ EVT_OBJ_5 (OBJ, msgQId, msgQClassId, EVENT_MSGQSEND, msgQId, buffer, nBytes, timeout, priority);#endif if (nBytes > msgQId->maxMsgLength) { if (!INT_CONTEXT ()) TASK_UNLOCK (); errnoSet (S_msgQLib_INVALID_MSG_LENGTH); return (ERROR); } pMsg = (MSG_NODE *) qJobGet (msgQId, &msgQId->freeQ, timeout); if (pMsg == (MSG_NODE *) NONE) { timeout = SIG_TIMEOUT_RECALC(timeout); goto restart; } if (pMsg == NULL) {#if FALSE msgQId->sendTimeouts++;#else /* * The timeout stat should only be updated if a timeout has occured. * An OBJ_VERIFY needs to be performed to catch the case where a * timeout indeed occured, but the message queue is subsequently * deleted before the current task is rescheduled. */ if (errnoGet() == S_objLib_OBJ_TIMEOUT) { if (OBJ_VERIFY (msgQId, msgQClassId) == OK) msgQId->sendTimeouts++; else errnoSet(S_objLib_OBJ_DELETED); }#endif /* FALSE */ if (!INT_CONTEXT ()) TASK_UNLOCK (); return (ERROR); } pMsg->msgLength = nBytes; bcopy (buffer, MSG_NODE_DATA (pMsg), (int) nBytes); if (qJobPut (msgQId, &msgQId->msgQ, &pMsg->node, priority) != OK) { if (!INT_CONTEXT ()) TASK_UNLOCK (); return (ERROR); /* errno set by qJobPut() */ } if (!INT_CONTEXT ()) TASK_UNLOCK (); return (OK); }/********************************************************************************* msgQReceive - receive a message from a message queue** This routine receives a message from the message queue <msgQId>.* The received message is copied into the specified <buffer>, which is* <maxNBytes> in length. If the message is longer than <maxNBytes>,* the remainder of the message is discarded (no error indication* is returned).** The <timeout> parameter specifies the number of ticks to wait for * a message to be sent to the queue, if no message is available when* msgQReceive() is called. The <timeout> parameter can also have * the following special values: * .iP "NO_WAIT (0)" 8* return immediately, whether a message has been received or not. * .iP "WAIT_FOREVER (-1)"* never time out.* .LP** WARNING: This routine must not be called by interrupt service routines.** RETURNS:* The number of bytes copied to <buffer>, or ERROR.** ERRNO: S_distLib_NOT_INITIALIZED, S_smObjLib_NOT_INITIALIZED,* S_objLib_OBJ_ID_ERROR, S_objLib_OBJ_DELETED,* S_objLib_OBJ_UNAVAILABLE, S_objLib_OBJ_TIMEOUT,* S_msgQLib_INVALID_MSG_LENGTH, S_intLib_NOT_ISR_CALLABLE** SEE ALSO: msgQSmLib*/int msgQReceive ( FAST MSG_Q_ID msgQId, /* message queue from which to receive */ char * buffer, /* buffer to receive message */ UINT maxNBytes, /* length of buffer */ int timeout /* ticks to wait */ ) { FAST MSG_NODE * pMsg; FAST int bytesReturned; if (INT_RESTRICT() != OK) /* errno set by INT_RESTRICT() */ return ERROR; if (ID_IS_SHARED (msgQId)) /* message Q is shared? */ { if (ID_IS_DISTRIBUTED (msgQId)) /* message queue is distributed? */ { if (msgQDistReceiveRtn == NULL) { errno = S_distLib_NOT_INITIALIZED; return (ERROR); } return ((*msgQDistReceiveRtn) (msgQId, buffer, maxNBytes, timeout, WAIT_FOREVER)); } if (msgQSmReceiveRtn == NULL) { errno = S_smObjLib_NOT_INITIALIZED; return (ERROR); } return ((*msgQSmReceiveRtn) (SM_OBJ_ID_TO_ADRS (msgQId), buffer, maxNBytes, timeout)); } /* message queue is local */ /* even though maxNBytes is unsigned, check for < 0 to catch possible * caller errors */ if ((int) maxNBytes < 0) { errnoSet (S_msgQLib_INVALID_MSG_LENGTH); return (ERROR); } TASK_LOCK ();restart: if (OBJ_VERIFY (msgQId, msgQClassId) != OK) { TASK_UNLOCK (); return (ERROR); }#ifdef WV_INSTRUMENTATION /* windview - level 1 event logging routine */ EVT_OBJ_4 (OBJ, msgQId, msgQClassId, EVENT_MSGQRECEIVE, msgQId, buffer, maxNBytes, timeout);#endif pMsg = (MSG_NODE *) qJobGet (msgQId, &msgQId->msgQ, timeout); if (pMsg == (MSG_NODE *) NONE) { timeout = SIG_TIMEOUT_RECALC(timeout); goto restart; } if (pMsg == NULL) {#if FALSE msgQId->recvTimeouts++;#else /* * The timeout stat should only be updated if a timeout has occured. * An OBJ_VERIFY needs to be performed to catch the case where a * timeout indeed occured, but the message queue is subsequently * deleted before the current task is rescheduled. */ if (errnoGet() == S_objLib_OBJ_TIMEOUT) { if (OBJ_VERIFY (msgQId, msgQClassId) == OK) msgQId->sendTimeouts++; else errnoSet(S_objLib_OBJ_DELETED); }#endif /* FALSE */ TASK_UNLOCK (); return (ERROR); } bytesReturned = min (pMsg->msgLength, maxNBytes); bcopy (MSG_NODE_DATA (pMsg), buffer, bytesReturned); qJobPut (msgQId, &msgQId->freeQ, &pMsg->node, Q_JOB_PRI_DONT_CARE); TASK_UNLOCK (); return (bytesReturned); }/********************************************************************************* msgQNumMsgs - get the number of messages queued to a message queue** This routine returns the number of messages currently queued to a specified* message queue.** RETURNS:* The number of messages queued, or ERROR.** ERRNO: S_distLib_NOT_INITIALIZED, S_smObjLib_NOT_INITIALIZED,* S_objLib_OBJ_ID_ERROR** SEE ALSO: msgQSmLib*/int msgQNumMsgs ( FAST MSG_Q_ID msgQId /* message queue to examine */ ) { if (ID_IS_SHARED (msgQId)) /* message Q is shared? */ { if (ID_IS_DISTRIBUTED (msgQId)) /* message queue is distributed? */ { if (msgQDistNumMsgsRtn == NULL) { errno = S_distLib_NOT_INITIALIZED; return (ERROR); } return ((*msgQDistNumMsgsRtn) (msgQId, WAIT_FOREVER)); } if (msgQSmNumMsgsRtn == NULL) { errno = S_smObjLib_NOT_INITIALIZED; return (ERROR); } return ((*msgQSmNumMsgsRtn) (SM_OBJ_ID_TO_ADRS (msgQId))); } /* message queue is local */ if (OBJ_VERIFY (msgQId, msgQClassId) != OK) return (ERROR); return (msgQId->msgQ.count); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -