⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mqpxlib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    struct mq_attr *	pAttr;		/* pointer to attr passed in */    void *		pQMem;		/* memory queue will be placed in */    mode_t		mode;		/* not used by vxWorks */    int			nMsgs;		/* number of messages in queue */    int			msgSize;	/* size of each message in queue */    int			nBytes;		/* amount of mem needed for queue */    SYM_TYPE		dummy;		/* dummy var for symFindByName */    if (INT_RESTRICT () != OK)	/* restrict ISR from calling */	return ((mqd_t) -1);    if ((!mqLibInstalled) && (mqPxLibInit (0) != OK))	return ((mqd_t) -1);	/* package init problem */    if ((oflags & 3) == 3)	{	errno = EINVAL;	return ((mqd_t) -1);	}    semTake (&mqNameTbl->symMutex, WAIT_FOREVER);    if (symFindByName (mqNameTbl, (char *) mqName, (char **)&pQMem,                        &dummy) == OK)	{	/*	 * Found a mq, see if we should use it	 */	if (O_EXCL & oflags)	    {	    semGive (&mqNameTbl->symMutex);	    errno = EEXIST;	    return ((mqd_t) -1);	    }	if ((pMqDesc = (mqd_t) objAlloc (mqClassId)) == NULL)	    {	    semGive (&mqNameTbl->symMutex);	    errno = ENOSPC;	    return ((mqd_t) -1);	    }	}    else	{	/*	 * There was no mq, create one if asked	 */	if (!(O_CREAT & oflags))	    {	    semGive (&mqNameTbl->symMutex);	    errno = ENOENT;	    return ((mqd_t) -1);		/* queue does not exist */	    }	va_start (vaList, oflags);	mode = va_arg (vaList, mode_t);	pAttr = va_arg (vaList, struct mq_attr *);	va_end (vaList);	if (pAttr != NULL)	    {	    nMsgs = pAttr->mq_maxmsg;	    msgSize = pAttr->mq_msgsize;	    if ((nMsgs <= 0) || (msgSize <= 0))		{	    	semGive (&mqNameTbl->symMutex);	    	errno = EINVAL;	    	return ((mqd_t) -1);		/* invalid size specified */	    	}	    oflags |= (pAttr->mq_flags & O_NONBLOCK);	    }	else	    {	    nMsgs =   MQ_NUM_MSGS_DEFAULT;	    msgSize = MQ_MSG_SIZE_DEFAULT;	    }	nBytes = MEM_ROUND_UP (sizeof(struct msg_que)) + 		 nMsgs * MEM_ROUND_UP (msgSize + sizeof (struct sll_node));	pQMem = malloc (nBytes + strlen (mqName) + 1);	if (pQMem == 0)	    {	    semGive (&mqNameTbl->symMutex);	    errno = ENOSPC;	    return ((mqd_t) -1);	    }	mq_init (pQMem, nMsgs, msgSize);	((struct msg_que *) pQMem)->msgq_sym.name = (char *) pQMem + nBytes;	((struct msg_que *) pQMem)->msgq_sym.value = (char *) pQMem;	strcpy ((char *)pQMem + nBytes, mqName);	if ((pMqDesc = (mqd_t) objAlloc (mqClassId)) == NULL)	    {	    free (pQMem);	    semGive (&mqNameTbl->symMutex);	    errno = ENOSPC;	    return ((mqd_t) -1);	    }	symTblAdd (mqNameTbl, &((struct msg_que *) pQMem)->msgq_sym);	}    /*     * (oflags & 3) + 1 is magic for transposing O_RDONLY, O_RDWR or     * O_WRONLY into the bit field flags FREAD and FWRITE     */    pMqDesc->f_flag = (oflags & O_NONBLOCK) | ((oflags & 3) + 1);    pMqDesc->f_data = pQMem;    pMqDesc->f_data->msgq_links++;    objCoreInit (&pMqDesc->f_objCore, mqClassId);	/* valid file obj */    semGive (&mqNameTbl->symMutex);    return (pMqDesc);    }/********************************************************************************* mq_receive - receive a message from a message queue (POSIX)** This routine receives the oldest of the highest priority message from* the message queue specified by <mqdes>.  If the size of the buffer in* bytes, specified by the <msgLen> argument, is less than the `mq_msgsize'* attribute of the message queue, mq_receive() will fail and return an* error.  Otherwise, the selected message is removed from the queue and* copied to <pMsg>.** If <pMsgPrio> is not NULL, the priority of the selected message* will be stored in <pMsgPrio>.** If the message queue is empty and O_NONBLOCK is not set in the message* queue's description, mq_receive() will block until a message is added to* the message queue, or until it is interrupted by a signal.  If more than* one task is waiting to receive a message when a message arrives at an* empty queue, the task of highest priority that has been waiting the* longest will be selected to receive the message.  If the specified message* queue is empty and O_NONBLOCK is set in the message queue's description,* no message is removed from the queue, and mq_receive() returns an error.** RETURNS: The length of the selected message in bytes, otherwise -1 (ERROR). ** ERRNO: EAGAIN, EBADF, EMSGSIZE, EINTR** SEE ALSO: mq_send()*/ssize_t mq_receive    (    mqd_t	mqdes,		/* message queue descriptor */    void	*pMsg,		/* buffer to receive message */    size_t	msgLen,		/* size of buffer, in bytes */    int		*pMsgPrio	/* if not NULL, priority of message */    )    {    struct sll_node *pNode;    struct msg_que *pMq;    int status;    int level;    int prio;    int error = 0;    int savtype;    if (INT_RESTRICT () != OK)		/* restrict ISR from calling */	return (-1);    TASK_LOCK ();			/* TASK LOCK */    if ((OBJ_VERIFY (mqdes, mqClassId) != OK) ||	((mqdes->f_flag & FREAD) == 0))	{	error = EBADF;	goto bad;	}    pMq = mqdes->f_data;    /* Link into pthreads support code */    if (_func_pthread_setcanceltype != NULL)        {        _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype);        }    if (msgLen < pMq->msgq_attr.mq_msgsize)	{	error = EMSGSIZE;	goto bad;	}    level = intLock ();			/* LOCK INTERRUPTS */    if (pMq->msgq_bmap == 0)	{	if (mqdes->f_flag & O_NONBLOCK)	    {	    intUnlock (level);		/* UNLOCK INTERRUPTS */	    error = EAGAIN;	    goto bad;	    }	/*	 * This needs to be in a loop, the reason is that someone	 * can wake us up but we may not run.  During that time someone	 * else can come in and steal our message.	 */	while (pMq->msgq_bmap == 0)	    {	    kernelState = TRUE;		/* ENTER KERNEL */	    intUnlock (level);		/* UNLOCK INTERRUPTS */	    /* windview - level 2 instrumentation */            EVT_TASK_1 (EVENT_OBJ_MSGRECEIVE, pMq);	    if (windPendQPut (&pMq->msgq_cond_data, WAIT_FOREVER) != OK)		{		windExit ();			/* EXIT KERNEL */		error = EBADF;			/* what should ernno be??? */		goto bad;		}	    status = windExit ();		/* EXIT KERNEL */	    if (status != 0)		{		error = (status == RESTART) ? EINTR : EAGAIN;		goto bad;		}	    level = intLock ();		/* LOCK INTERRUPTS */	    }	}    prio = ffsMsb (pMq->msgq_bmap) - 1;    pNode = sll_head (&pMq->msgq_data_list[prio]);    --pMq->msgq_attr.mq_curmsgs;    if (pMq->msgq_data_list[prio] == NULL)	pMq->msgq_bmap &= ~(1 << prio);    intUnlock (level);			/* UNLOCK INTERRUPTS */    msgLen = pNode->sll_size;    bcopy ((void *) (pNode + 1), pMsg, msgLen);    if (pMsgPrio != 0)	*pMsgPrio = prio;    level = intLock ();			/* LOCK INTERRUPTS */    sll_ins (pNode, &pMq->msgq_free_list);    if (Q_FIRST (&pMq->msgq_cond_read) != 0)	{	kernelState = TRUE;		/* ENTER KERNEL */	intUnlock (level);		/* UNLOCK INTERRUPTS */	/* windview - level 2 instrumentation */        EVT_TASK_1 (EVENT_OBJ_MSGRECEIVE, pMq);	windPendQGet (&pMq->msgq_cond_read);	windExit ();			/* EXIT KERNEL */	}    else	intUnlock (level);		/* UNLOCK INTERRUPTS */bad:    TASK_UNLOCK();			/* TASK UNLOCK */    /* Link into pthreads support code */    if (_func_pthread_setcanceltype != NULL)        {        _func_pthread_setcanceltype(savtype, NULL);        }    if (error != 0)	{	errno = error;	return (-1);	}    return (msgLen);    }/********************************************************************************* mq_work - handle mq work** The routine is always done as work. It is needed because windPendQGet* does not check it the queue is empty.*/LOCAL void mq_work    (    struct msg_que *pMq,    int flag    )    {    if (Q_FIRST (&pMq->msgq_cond_data) != NULL)	{	/* windview - level 2 instrumentation */        EVT_TASK_1 (EVENT_OBJ_MSGSEND, pMq);	windPendQGet (&pMq->msgq_cond_data);	}    else if ((flag == 0) && (pMq->msgq_sigTask != -1))	{        /* SPR #32033         * An interrupt context is faked while executing sigPendKill().           * Since the work queue is drained with kernelState set to TRUE,         * sigPendKill() will perform an excJobAdd() of itself.  Without         * faking an interrupt context, the ensuing msgQSend() will perform         * taskLock/taskUnlock to protect it's critical section.  The          * taskUnlock() would then re-enter the kernel via windExit().         * The kernel cannot be re-entered while in the process of draining         * the work queue.         */   	++intCnt;     /* no need to lock interrupts around increment */	sigPendKill (pMq->msgq_sigTask, &pMq->msgq_sigPend);	--intCnt;     /* no need to lock interrupts around decrement */	pMq->msgq_sigTask = -1;	}    }/********************************************************************************* mq_send - send a message to a message queue (POSIX)** This routine adds the message <pMsg> to the message queue* <mqdes>.  The <msgLen> parameter specifies the length of the message in* bytes pointed to by <pMsg>.  The value of <pMsg> must be less than or* equal to the `mq_msgsize' attribute of the message queue, or mq_send()* will fail.** If the message queue is not full, mq_send() will behave as if the message* is inserted into the message queue at the position indicated by the * <msgPrio> argument.  A message with a higher numeric value for <msgPrio>* is inserted before messages with a lower value.  The value* of <msgPrio> must be less than or equal to 31.** If the specified message queue is full and O_NONBLOCK is not set in the* message queue's, mq_send() will block until space becomes available to* queue the message, or until it is interrupted by a signal.  The priority* scheduling option is supported in the event that there is more than one* task waiting on space becoming available.  If the message queue is full* and O_NONBLOCK is set in the message queue's description, the message is* not queued, and mq_send() returns an error.** 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.  If mq_send()* is called from an interrupt service routine, it will behave as if* the O_NONBLOCK flag were set.** RETURNS: 0 (OK), otherwise -1 (ERROR).** ERRNO: EAGAIN, EBADF, EINTR, EINVAL, EMSGSIZE** SEE ALSO: mq_receive()*/int mq_send    (    mqd_t	mqdes,		/* message queue descriptor */    const void	*pMsg,		/* message to send */    size_t	msgLen,		/* size of message, in bytes */    int		msgPrio		/* priority of message */    )    {    struct sll_node *pNode;    struct msg_que *pMq;    int status;    int level;    int flag;    int sigTaskSave;		/* saved task id */    int error = 0;    int savtype;		/* saved cancellation type */    if (msgPrio > MQ_PRIORITY_MAX)	{	errno = EINVAL;	return (-1);	}    /* Link into pthreads support code */        if (_func_pthread_setcanceltype != NULL)        {        _func_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &savtype);        }     if (!INT_CONTEXT ())	TASK_LOCK ();			/* TASK LOCK */    if ((OBJ_VERIFY (mqdes, mqClassId) != OK) ||	((mqdes->f_flag & FWRITE) == 0))	{	error = EBADF;	goto bad;	}    pMq = mqdes->f_data;    if (msgLen > pMq->msgq_attr.mq_msgsize)	{	error = EMSGSIZE;	goto bad;	}    level = intLock ();			/* LOCK INTERRUPTS */    if (pMq->msgq_free_list == NULL)	{	if (mqdes->f_flag & O_NONBLOCK)	    {	    intUnlock (level);		/* UNLOCK INTERRUPTS */	    error = EAGAIN;	    goto bad;	    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -