📄 mqpxlib.c
字号:
if (INT_CONTEXT ()) { intUnlock (level); /* UNLOCK INTERRUPTS */ error = EAGAIN; /* what should errno be??? */ goto bad; } while (pMq->msgq_free_list == NULL) { kernelState = TRUE; /* ENTER KERNEL */ intUnlock (level); /* UNLOCK INTERRUPTS */ /* windview - level 2 instrumentation */ EVT_TASK_1 (EVENT_OBJ_MSGSEND, pMq); if (windPendQPut (&pMq->msgq_cond_read, WAIT_FOREVER) != OK) { windExit (); /* EXIT KERNEL */ error = EBADF; /* what should errno be??? */ goto bad; } if ((status = windExit ()) != 0) /* EXIT KERNEL */ { error = (status == RESTART) ? EINTR : EAGAIN; goto bad; } level = intLock (); /* LOCK INTERRUPTS */ } } pNode = sll_head (&pMq->msgq_free_list); intUnlock (level); /* UNLOCK INTERRUPTS */ bcopy (pMsg, (void *) (pNode + 1), msgLen); pNode->sll_size = msgLen; level = intLock (); /* LOCK INTERRUPTS */ sll_ins (pNode, &pMq->msgq_data_list[msgPrio]); flag = pMq->msgq_attr.mq_curmsgs++; pMq->msgq_bmap |= 1 << (msgPrio); if (kernelState) { intUnlock (level); /* UNLOCK INTERRUPTS */ workQAdd2 ((FUNCPTR)mq_work, (int) pMq, flag); } else { if (Q_FIRST (&pMq->msgq_cond_data) != 0) { kernelState = TRUE; /* ENTER KERNEL */ intUnlock (level); /* UNLOCK INTERRUPTS */ /* windview - level 2 instrumentation */ EVT_TASK_1 (EVENT_OBJ_MSGSEND, pMq); windPendQGet (&pMq->msgq_cond_data); windExit (); /* EXIT KERNEL */ } else { intUnlock (level); /* UNLOCK INTERRUPTS */ if ((flag == 0) && (pMq->msgq_sigTask != -1)) { sigTaskSave = pMq->msgq_sigTask; pMq->msgq_sigTask = -1; sigPendKill (sigTaskSave, &pMq->msgq_sigPend); } } }bad: if (!INT_CONTEXT ()) TASK_UNLOCK (); /* TASK UNLOCK */ /* Link into pthreads support code */ if (_func_pthread_setcanceltype != NULL) { _func_pthread_setcanceltype(savtype, NULL); } if (error) { errno = error; return (-1); } return (0); }/********************************************************************************* mq_close - close a message queue (POSIX)** This routine is used to indicate that the calling task is finished* with the specified message queue <mqdes>. * The mq_close() call deallocates any system resources allocated * by the system for use by this task for its message queue.* The behavior of a task that is blocked on either a mq_send() or* mq_receive() is undefined when mq_close() is called.* The <mqdes> parameter will no longer be a valid message queue ID.** RETURNS: 0 (OK) if the message queue is closed successfully,* otherwise -1 (ERROR).** ERRNO: EBADF** SEE ALSO: mq_open()*/int mq_close ( mqd_t mqdes /* message queue descriptor */ ) { if (INT_RESTRICT () != OK) /* restrict ISR from calling */ return (-1); TASK_SAFE (); /* TASK SAFE */ TASK_LOCK (); /* LOCK PREEMPTION */ /* * validate message queue */ if (OBJ_VERIFY (mqdes, mqClassId) != OK) { TASK_UNLOCK (); /* TASK UNLOCK */ TASK_UNSAFE (); /* TASK UNSAFE */ errno = EBADF; return (-1); /* invalid object */ } /* * invalidate message queue descriptor */ objCoreTerminate (&mqdes->f_objCore); TASK_UNLOCK (); /* TASK UNLOCK */ semTake (&mqNameTbl->symMutex, WAIT_FOREVER); /* * No effect unless the name has been unlinked from name table */ if ((--mqdes->f_data->msgq_links == 0) && (mqdes->f_data->msgq_sym.name == NULL)) mq_terminate(mqdes->f_data); semGive (&mqNameTbl->symMutex); /* * free message queue descriptor */ objFree (mqClassId, (char *) mqdes); TASK_UNSAFE (); /* TASK UNSAFE */ return (0); }/********************************************************************************* mq_unlink - remove a message queue (POSIX)** This routine removes the message queue named by the pathname <mqName>.* After a successful call to mq_unlink(), a call to mq_open() on the same* message queue will fail if the flag O_CREAT is not set. If one or more* tasks have the message queue open when mq_unlink() is called, removal of* the message queue is postponed until all references to the message queue* have been closed.** RETURNS: 0 (OK) if the message queue is unlinked successfully,* otherwise -1 (ERROR).** ERRNO: ENOENT** SEE ALSO: mq_close(), mq_open()**/int mq_unlink ( const char * mqName /* name of message queue */ ) { struct msg_que *pMq; SYM_TYPE dummy; /* dummy var for symFindByName */ /* * The following semTake is used to insure that mq_open cannot * attach a task to the message queue between finding the message queue * name in the table and unlinking it from the table. */ semTake (&mqNameTbl->symMutex, WAIT_FOREVER); if (symFindByName (mqNameTbl, (char *) mqName, (char **) &pMq, &dummy) == ERROR) { semGive (&mqNameTbl->symMutex); errno = ENOENT; return (-1); } /* * Remove name from table */ symTblRemove (mqNameTbl, &pMq->msgq_sym); pMq->msgq_sym.name = 0; if (pMq->msgq_links == 0) mq_terminate (pMq); semGive (&mqNameTbl->symMutex); return (0); }/********************************************************************************* mq_notify - notify a task that a message is available on a queue (POSIX)** If <pNotification> is not NULL, this routine attaches the specified* <pNotification> request by the calling task to the specified message queue* <mqdes> associated with the calling task. The real-time signal specified* by <pNotification> will be sent to the task when the message queue changes* from empty to non-empty. If a task has already attached a notification* request to the message queue, all subsequent attempts to attach a* notification to the message queue will fail. A task is able to attach a* single notification to each <mqdes> it has unless another task has already* attached one.** If <pNotification> is NULL and the task has previously attached a* notification request to the message queue, the attached notification* request is detached and the queue is available for another task to attach* a notification request.** If a notification request is attached to a message queue and any task* is blocked in mq_receive() waiting to receive a message when a message* arrives at the queue, then the appropriate mq_receive() will be completed* and the notification request remains pending.** RETURNS: 0 (OK) if successful, otherwise -1 (ERROR).** ERRNO: EBADF, EBUSY, EINVAL** SEE ALSO: mq_open(), mq_send()**/int mq_notify ( mqd_t mqdes, /* message queue descriptor */ const struct sigevent * pNotification /* real-time signal */ ) { struct siginfo * sigInfoP; int error = 0; if (INT_RESTRICT () != OK) /* restrict ISR from calling */ return (-1); TASK_LOCK (); /* TASK LOCK */ if (OBJ_VERIFY (mqdes, mqClassId) != OK) { error = EBADF; goto done; /* invalid object */ } /* * free realtime signal */ if (pNotification == NULL) { if (taskIdSelf () == mqdes->f_data->msgq_sigTask) { mqdes->f_data->msgq_sigTask = -1; sigPendDestroy (&mqdes->f_data->msgq_sigPend); } else error = EINVAL; goto done; } /* * already in use */ if (mqdes->f_data->msgq_sigTask != -1) { error = EBUSY; goto done; } mqdes->f_data->msgq_sigTask = taskIdSelf (); sigInfoP = &mqdes->f_data->msgq_sigPend.sigp_info; sigInfoP->si_signo = pNotification->sigev_signo; /* signal number */ sigInfoP->si_code = SI_MESGQ; /* signal code */ sigInfoP->si_value = pNotification->sigev_value; /* signal value */ /* initialize signal */ sigPendInit (&mqdes->f_data->msgq_sigPend);done: TASK_UNLOCK (); /* TASK UNLOCK */ if (error != 0) { errno = error; return (-1); } return (0); }/********************************************************************************* mq_setattr - set message queue attributes (POSIX)** This routine sets attributes associated with the specified message* queue <mqdes>.** The message queue attributes corresponding to the following members* defined in the `mq_attr' structure are set to the specified values upon* successful completion of the call:* .iP `mq_flags'* The value the O_NONBLOCK flag.* .LP** If <pOldMqStat> is non-NULL, mq_setattr() will store, in the* location referenced by <pOldMqStat>, the previous message queue attributes* and the current queue status. These values are the same as would be returned* by a call to mq_getattr() at that point.** RETURNS: 0 (OK) if attributes are set successfully, otherwise -1 (ERROR).** ERRNO: EBADF** SEE ALSO: mq_open(), mq_send(), mq_getattr()*/int mq_setattr ( mqd_t mqdes, /* message queue descriptor */ const struct mq_attr * pMqStat, /* new attributes */ struct mq_attr * pOldMqStat /* old attributes */ ) { if (INT_RESTRICT () != OK) /* restrict ISR from calling */ return (-1); TASK_LOCK (); /* TASK LOCK */ if (OBJ_VERIFY (mqdes, mqClassId) != OK) { TASK_UNLOCK (); /* TASK UNLOCK */ errno = EBADF; return (-1); /* invalid object */ } if (pOldMqStat) { *pOldMqStat = mqdes->f_data->msgq_attr; pOldMqStat->mq_flags = mqdes->f_flag; } if (pMqStat) { mqdes->f_flag &= ~O_NONBLOCK; mqdes->f_flag |= (pMqStat->mq_flags & O_NONBLOCK); } TASK_UNLOCK (); /* TASK UNLOCK */ return (0); }/********************************************************************************* mq_getattr - get message queue attributes (POSIX)** This routine gets status information and attributes associated with a* specified message queue <mqdes>. Upon return, the following members of* the `mq_attr' structure referenced by <pMqStat> will contain the values* set when the message queue was created but with modifications made by* subsequent calls to mq_setattr():* .iP `mq_flags'* May be modified by mq_setattr().* .LP** The following were set at message queue creation:* .iP `mq_maxmsg'* Maximum number of messages.* .iP `mq_msgsize'* Maximum message size.* .LP** .iP `mq_curmsgs'* The number of messages currently in the queue.* .LP** RETURNS: 0 (OK) if message attributes can be determined, otherwise -1 (ERROR).** ERRNO: EBADF** SEE ALSO: mq_open(), mq_send(), mq_setattr()**/int mq_getattr ( mqd_t mqdes, /* message queue descriptor */ struct mq_attr * pMqStat /* buffer in which to return attributes */ ) { return (mq_setattr (mqdes, NULL, pMqStat)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -