mq.c

来自「xenomai 很好的linux实时补丁」· C语言 代码 · 共 879 行 · 第 1/2 页

C
879
字号
        if (direct & msg.used)            return 0;                    if (xnthread_test_flags(cur, XNRMID))            return EBADF;        if (xnthread_test_flags(cur, XNTIMEO))            return ETIMEDOUT;        if (xnthread_test_flags(cur, XNBREAK))            return EINTR;        }}/** * Try during a bounded time to send a message to a message queue. * * @see http://www.opengroup.org/onlinepubs/000095399/functions/mq_timedsend.html *  */int mq_timedsend(mqd_t fd,                 const char * buffer,                 size_t len,                 unsigned prio,                 const struct timespec *abs_timeout){    xnticks_t timeout;    int err;    spl_t s;    if((unsigned long) abs_timeout->tv_nsec >= ONE_BILLION)        {        thread_set_errno(EINVAL);        return -1;        }    timeout = ts2ticks_ceil(abs_timeout) + 1;    xnlock_get_irqsave(&nklock, s);    err = pse51_mq_timedsend_inner(fd, buffer, len, prio, timeout);    xnlock_put_irqrestore(&nklock, s);    if(err)        {        thread_set_errno(err);        return -1;        }    return 0;}/** * Send a message to a message queue. * * @see http://www.opengroup.org/onlinepubs/000095399/functions/mq_send.html *  */int mq_send(mqd_t fd, const char *buffer, size_t len, unsigned prio){    int err;    spl_t s;    xnlock_get_irqsave(&nklock, s);    err = pse51_mq_timedsend_inner(fd, buffer, len, prio, XN_INFINITE);    xnlock_put_irqrestore(&nklock, s);    if(err)        {        thread_set_errno(err);        return -1;        }    return 0;}/** * Register the current thread to be notified of message arrival at an empty * message queue. * * @see http://www.opengroup.org/onlinepubs/000095399/functions/mq_notify.html *  */int mq_notify(mqd_t fd, const struct sigevent *evp){    pthread_t thread = pse51_current_thread();    pse51_desc_t *desc;    pse51_mq_t *mq;    int err;    spl_t s;    if (evp && ((evp->sigev_notify != SIGEV_SIGNAL &&		 evp->sigev_notify != SIGEV_NONE) ||                (unsigned) (evp->sigev_signo - 1) > SIGRTMAX - 1))        {        err = EINVAL;        goto error;        }    if (xnpod_asynch_p() || !thread)        {        err = EPERM;        goto error;        }    xnlock_get_irqsave(&nklock, s);    err = pse51_desc_get(&desc, fd, PSE51_MQ_MAGIC);    if(err)        goto unlock_and_error;    mq = node2mq(pse51_desc_node(desc));    if (mq->target && mq->target != thread)        {        err = EBUSY;        goto unlock_and_error;        }    if (!evp || evp->sigev_notify == SIGEV_NONE)        /* Here, mq->target == pse51_current_thread() or NULL. */        mq->target = NULL;    else        {        mq->target = thread;        mq->si.info.si_signo = evp->sigev_signo;        mq->si.info.si_code = SI_MESGQ;        mq->si.info.si_value = evp->sigev_value;        }    xnlock_put_irqrestore(&nklock, s);    return 0;  unlock_and_error:    xnlock_put_irqrestore(&nklock, s);  error:    thread_set_errno(err);    return -1;}/** * Try during a bounded time to receive a message from a message queue. * * @see http://www.opengroup.org/onlinepubs/000095399/functions/mq_timedreceive.html *  */ssize_t mq_timedreceive(mqd_t fd,                        char *__restrict__ buffer,                        size_t len,                        unsigned *__restrict__ priop,                        const struct timespec *__restrict__ abs_timeout){    xnticks_t timeout;    int err;    spl_t s;    if((unsigned long) abs_timeout->tv_nsec >= ONE_BILLION)        {        thread_set_errno(EINVAL);        return -1;        }    timeout = ts2ticks_ceil(abs_timeout) + 1;    xnlock_get_irqsave(&nklock, s);    err = pse51_mq_timedrcv_inner(fd, buffer, &len, priop, timeout);    xnlock_put_irqrestore(&nklock, s);    if(err)        {        thread_set_errno(err);        return -1;        }    return len;    }/** * Receive a message from a message queue. * * @see http://www.opengroup.org/onlinepubs/000095399/functions/mq_receive.html *  */ssize_t mq_receive(mqd_t fd, char *buffer, size_t len, unsigned *priop){    int err;    spl_t s;    xnlock_get_irqsave(&nklock, s);    err = pse51_mq_timedrcv_inner(fd, buffer, &len, priop, XN_INFINITE);    xnlock_put_irqrestore(&nklock, s);    if(err)        {        thread_set_errno(err);        return -1;        }    return len;    }/** * Open a message queue. * * @see http://www.opengroup.org/onlinepubs/000095399/functions/mq_open.html *  */mqd_t mq_open(const char *name, int oflags, ...){    struct mq_attr *attr;    xnsynch_t done_synch;    pse51_node_t *node;    pse51_desc_t *desc;    spl_t s, ignored;    pse51_mq_t *mq;    mode_t mode;    va_list ap;    int err;        xnlock_get_irqsave(&nklock, s);    err = pse51_node_get(&node, name, PSE51_MQ_MAGIC, oflags);    if(err)        goto error;    if(node)        {        mq = node2mq(node);        goto got_mq;        }    /* Here, we know that we must create a message queue. */    mq = (pse51_mq_t *) xnmalloc(sizeof(*mq));        if(!mq)        {        err = ENOMEM;        goto error;        }    err = pse51_node_add_start(&mq->nodebase, name, PSE51_MQ_MAGIC, &done_synch);    if(err)        goto error;    xnlock_clear_irqon(&nklock);    /* Release the global lock while creating the message queue. */    va_start(ap, oflags);    mode = va_arg(ap, int); /* unused */    attr = va_arg(ap, struct mq_attr *);    va_end(ap);        err = pse51_mq_init(mq, attr);    xnlock_get_irqsave(&nklock, ignored);    pse51_node_add_finished(&mq->nodebase, err);    if(err)        {        xnlock_put_irqrestore(&nklock, s);        goto err_free_mq;        }    inith(&mq->link);    appendq(&pse51_mqq, &mq->link);    /* Whether found or created, here we have a valid message queue. */  got_mq:    err = pse51_desc_create(&desc, &mq->nodebase);    if(err)        goto err_put_mq;    pse51_desc_setflags(desc, oflags & (O_NONBLOCK | PSE51_PERMS_MASK));    xnlock_put_irqrestore(&nklock, s);    return (mqd_t) pse51_desc_fd(desc);  err_put_mq:    pse51_node_put(&mq->nodebase);    if(pse51_node_removed_p(&mq->nodebase))        {        /* mq is no longer referenced, we may destroy it. */        xnlock_put_irqrestore(&nklock, s);        pse51_mq_destroy(mq);  err_free_mq:        xnfree(mq);        }    else  error:        xnlock_put_irqrestore(&nklock, s);    thread_set_errno(err);    return (mqd_t) -1;}/** * Close a message queue. * * @see http://www.opengroup.org/onlinepubs/000095399/functions/mq_close.html *  */int mq_close(mqd_t fd){    pse51_desc_t *desc;    pse51_mq_t *mq;    spl_t s;    int err;    if (xnpod_asynch_p() || !xnpod_root_p())        {        err = EPERM;        goto error;        }    xnlock_get_irqsave(&nklock, s);    err = pse51_desc_get(&desc, fd, PSE51_MQ_MAGIC);    if(err)        goto err_unlock;    mq = node2mq(pse51_desc_node(desc));        err = pse51_desc_destroy(desc);    if(err)        goto err_unlock;    err = pse51_node_put(&mq->nodebase);    if(err)        goto err_unlock;        if(pse51_node_removed_p(&mq->nodebase))        {        xnlock_put_irqrestore(&nklock, s);        pse51_mq_destroy(mq);        xnfree(mq);        }    else        xnlock_put_irqrestore(&nklock, s);    return 0;  err_unlock:    xnlock_put_irqrestore(&nklock, s);  error:    thread_set_errno(err);    return -1;}/** * Unlink a message queue. * * @see http://www.opengroup.org/onlinepubs/000095399/functions/mq_unlink.html *  */int mq_unlink(const char *name){    pse51_node_t *node;    pse51_mq_t *mq;    spl_t s;    int err;    if (xnpod_asynch_p() || !xnpod_root_p())        {        err = EPERM;        goto error;        }    xnlock_get_irqsave(&nklock, s);    err = pse51_node_remove(&node, name, PSE51_MQ_MAGIC);    if(!err && pse51_node_removed_p(node))        {        xnlock_put_irqrestore(&nklock, s);        mq = node2mq(node);        pse51_mq_destroy(mq);        xnfree(mq);        }    else        xnlock_put_irqrestore(&nklock, s);    if(err)        {error:        thread_set_errno(err);        return -1;        }    return 0;}int pse51_mq_pkg_init(void){    initq(&pse51_mqq);    return 0;}void pse51_mq_pkg_cleanup(void){    xnholder_t *holder;    while ((holder = getheadq(&pse51_mqq)))        {        pse51_mq_t *mq = link2mq(holder);        pse51_node_t *node;#ifdef CONFIG_XENO_OPT_DEBUG        xnprintf("Posix message queue %s was not unlinked, unlinking now.\n",                 mq->nodebase.name);#endif /* CONFIG_XENO_OPT_DEBUG */        pse51_node_remove(&node, mq->nodebase.name, PSE51_MQ_MAGIC);        pse51_mq_destroy(mq);        xnfree(mq);        }}/*@}*/EXPORT_SYMBOL(mq_open);EXPORT_SYMBOL(mq_getattr);EXPORT_SYMBOL(mq_setattr);EXPORT_SYMBOL(mq_send);EXPORT_SYMBOL(mq_timedsend);EXPORT_SYMBOL(mq_receive);EXPORT_SYMBOL(mq_timedreceive);EXPORT_SYMBOL(mq_close);EXPORT_SYMBOL(mq_unlink);

⌨️ 快捷键说明

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