📄 msgqsmlib.c
字号:
** This routine sends the message in <buffer> of length <nBytes> to the* shared memory message queue <smMsgQId>. 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.** The <timeout> parameter specifies the number of ticks to wait for free* space if the message queue is full. <timeout> can have the special value* NO_WAIT that indicates msgQSend() will return immediately even if the* message has not been sent. Another value for <timeout> is WAIT_FOREVER* that indicates that msgQSend() will never timeout.** The <priority> parameter specifies the priority of the message being sent.* Normal priority messages (MSG_PRI_NORMAL) are added to the tail* of the list of queued messages. Urgent priority messages* (MSG_PRI_URGENT) are added to the head of the list.** This routine is normally called by the generic msgQSend() system call. * The lower bit of the identifier passed to msgQSend() is used to * differentiate local and shared memory message queues.** This routine not callable at interrupt level.** RETURNS: OK or ERROR.** ERRNO: S_objLib_OBJ_ID_ERROR, S_objLib_OBJ_UNAVAILABLE,* S_objLib_OBJ_TIMEOUT, S_msgQLib_INVALID_MSG_LENGTH,* S_smObjLib_LOCK_TIMEOUT** NOMANUAL*/STATUS msgQSmSend ( SM_MSG_Q_ID smMsgQId, /* message queue on which to send */ char * buffer, /* message to send */ UINT nBytes, /* length of message */ int timeout, /* ticks to wait */ int priority /* MSG_PRI_NORMAL or MSG_PRI_URGENT */ ) { SM_MSG_NODE volatile * pMsg; SM_DL_NODE * prevNode; int level; SM_MSG_Q_ID volatile smMsgQIdv = (SM_MSG_Q_ID volatile) smMsgQId; int temp; /* temp storage */ if (INT_RESTRICT () != OK) /* not ISR callable */ { return (ERROR); } CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = smMsgQIdv->verify; /* PCI bridge bug [SPR 68844]*/ if (SM_OBJ_VERIFY (smMsgQIdv) != OK) { return (ERROR); } if (nBytes > ntohl (smMsgQId->maxMsgLength)) { errno = S_msgQLib_INVALID_MSG_LENGTH; return (ERROR); } TASK_LOCK (); /* windview level 2 event logging, uses the OSE logging routine */ EVT_OBJ_SM_MSGQ (EVENT_MSGQSEND, smMsgQId, buffer, nBytes, timeout, priority,5); /* get a free message by taking free msg Q shared counting semaphore */ if (semSmTake (&smMsgQId->freeQSem, timeout) != OK) { smMsgQId->sendTimeouts = htonl (ntohl (smMsgQId->sendTimeouts) + 1); TASK_UNLOCK (); return (ERROR); } /* a free message was available before timeout, get it */ if (SM_OBJ_LOCK_TAKE (&smMsgQId->freeQLock, &level) != OK) { smObjTimeoutLogMsg ("msgQSend", (char *) &smMsgQId->freeQLock); TASK_UNLOCK (); return (ERROR); /* can't take lock */ } pMsg = (SM_MSG_NODE volatile *) smDllGet (&smMsgQId->freeQ); SM_OBJ_LOCK_GIVE (&smMsgQId->freeQLock, level);/* release lock */ pMsg->msgLength = htonl (nBytes); bcopy (buffer, SM_MSG_NODE_DATA (pMsg), (int) nBytes); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pMsg->msgLength; /* BRIDGE FLUSH [SPR 68334] */ /* now send message */ if (SM_OBJ_LOCK_TAKE (&smMsgQId->msgQLock, &level) != OK) { smObjTimeoutLogMsg ("msgQSend", (char *) &smMsgQId->msgQLock); TASK_UNLOCK (); return (ERROR); /* can't take lock */ } /* insert message in message list according to its priority */ if (priority == MSG_PRI_NORMAL) { prevNode = (SM_DL_NODE *) SM_DL_LAST (&smMsgQId->msgQ); } else prevNode = NULL; smDllInsert (&smMsgQId->msgQ, prevNode, (SM_DL_NODE *) pMsg); SM_OBJ_LOCK_GIVE (&smMsgQId->msgQLock, level);/* release lock */ /* * If another CPU is currently doing a msgQ send * we can have a case where the other CPU has put a message and * is delayed by an interrupt before Giving the shared * semaphore. In that case, this CPU can put its message and Give * the shared semaphore, the receiver will be unblocked by * the Give done by this CPU but the message obtained will * be the one put by the other CPU (FIFO order of messages will be kept). */ /* unblock receiver */ if (semSmGive (&smMsgQId->msgQSem) != OK) { TASK_UNLOCK (); return (ERROR); } TASK_UNLOCK (); return (OK); }/******************************************************************************* msgQSmReceive - receive a message from a shared memory message queue** This routine receives a message from the shared memory message queue* <smMsgQId>. 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* msgQSmReceive() is called. <timeout> can have the special value NO_WAIT* that indicates msgQSmReceive() will return immediately even if a message* is available. Another value for <timeout> is WAIT_FOREVER that indicates* that msgQSmReceive() will never timeout.** This routine is normally called by the generic msgQReceive() system call. * The lower bit of the identifier passed to msgQReceive() is used to * differentiate local and shared memory message queues.** This routine cannot be called by interrupt service routines.** RETURNS:* The number of bytes copied to <buffer>, or ERROR.** ERRNO: S_smObjLib_OBJ_ID_ERROR, S_objLib_OBJ_UNAVAILABLE,* S_objLib_OBJ_TIMEOUT, S_msgQLib_INVALID_MSG_LENGTH,* S_smObjLib_LOCK_TIMEOUT** NOMANUAL*/int msgQSmReceive ( SM_MSG_Q_ID smMsgQId, /* message queue from which to receive*/ char * buffer, /* buffer to receive message */ UINT maxNBytes, /* length of buffer */ int timeout /* ticks to wait */ ) { SM_MSG_NODE volatile * pMsg; int bytesReturned; int level; SM_MSG_Q_ID volatile smMsgQIdv = (SM_MSG_Q_ID volatile) smMsgQId; int temp; /* temp storage */ /* * even though maxNBytes is unsigned, check for < 0 to catch * possible caller errors */ if ((int) maxNBytes < 0) { errno = S_msgQLib_INVALID_MSG_LENGTH; return (ERROR); } TASK_LOCK (); /* windview level 2 event logging, uses the OSE logging routine */ EVT_OBJ_SM_MSGQ (EVENT_MSGQRECEIVE, smMsgQId, buffer, maxNBytes, timeout, 0,4); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = smMsgQIdv->verify; /* PCI bridge bug [SPR 68844]*/ if (SM_OBJ_VERIFY (smMsgQIdv) != OK) { TASK_UNLOCK (); return (ERROR); } /* block until a message is available */ if (semSmTake (&smMsgQId->msgQSem, timeout) != OK) { smMsgQId->recvTimeouts = htonl (ntohl (smMsgQId->recvTimeouts) + 1); TASK_UNLOCK (); return (ERROR); } /* a message was available before timeout, get it */ if (SM_OBJ_LOCK_TAKE (&smMsgQId->msgQLock, &level) != OK) { smObjTimeoutLogMsg ("msgQReceive", (char *) &smMsgQId->msgQLock); TASK_UNLOCK (); return (ERROR); /* can't take lock */ } pMsg = (SM_MSG_NODE volatile *) smDllGet (&smMsgQId->msgQ); SM_OBJ_LOCK_GIVE (&smMsgQId->msgQLock, level);/* release lock */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pMsg->msgLength; /* PCI bridge bug [SPR 68844]*/ bytesReturned = min (ntohl (pMsg->msgLength), maxNBytes); bcopy (SM_MSG_NODE_DATA (pMsg), buffer, bytesReturned); /* now give back message to free queue */ if (SM_OBJ_LOCK_TAKE (&smMsgQId->freeQLock, &level) != OK) { smObjTimeoutLogMsg ("msgQReceive", (char *) &smMsgQId->freeQLock); TASK_UNLOCK (); return (ERROR); /* can't take lock */ } smDllAdd (&smMsgQId->freeQ, (SM_DL_NODE *) pMsg); SM_OBJ_LOCK_GIVE (&smMsgQId->freeQLock, level);/* release lock */ /* now give free queue semaphore */ if (semSmGive (&smMsgQId->freeQSem) != OK) { TASK_UNLOCK (); return (ERROR); } TASK_UNLOCK (); return (bytesReturned); }/******************************************************************************* msgQSmNumMsgs - get number of messages queued to shared memory message queue** This routine returns the number of messages currently queued to a specified* message queue <smMsgQId>.** This routine is normally called by the generic msgQNumMsgs() system call. * The lower bit of the identifier passed to msgQNumMsgs() is used to * differentiate local and shared memory message queues.** RETURNS:* The number of messages queued, or ERROR.** ERRNO: S_objLib_OBJ_ID_ERROR** NOMANUAL*/int msgQSmNumMsgs ( SM_MSG_Q_ID smMsgQId /* message queue to examine */ ) { SM_MSG_Q_ID volatile smMsgQIdv = (SM_MSG_Q_ID volatile) smMsgQId; int temp; /* temp storage */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = smMsgQIdv->verify; /* PCI bridge bug [SPR 68844]*/ if (SM_OBJ_VERIFY (smMsgQIdv) != OK) { return (ERROR); } temp = smMsgQIdv->msgQSem.state.count; /* PCI bridge bug [SPR 68844]*/ temp = smMsgQIdv->msgQSem.state.count; return (ntohl (temp)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -