mqueue.c 7.5 KB
Newer Older
Y
yiyue.fang 已提交
1
/*
2
 * Copyright (c) 2006-2021, RT-Thread Development Team
Y
yiyue.fang 已提交
3
 *
4
 * SPDX-License-Identifier: Apache-2.0
Y
yiyue.fang 已提交
5 6 7 8 9
 *
 * Change Logs:
 * Date           Author       Notes
 */

B
Bernard Xiong 已提交
10
#include <string.h>
11
#include <fcntl.h>
12
#include <sys/signal.h>
13 14 15
#include <sys/time.h>
#include <sys/errno.h>
#include <rtthread.h>
M
Ming, Bai 已提交
16 17 18 19
#include "mqueue.h"

static mqd_t posix_mq_list = RT_NULL;
static struct rt_semaphore posix_mq_lock;
20 21 22

/* initialize posix mqueue */
static int posix_mq_system_init(void)
M
Ming, Bai 已提交
23
{
Y
yiyue.fang 已提交
24
    rt_sem_init(&posix_mq_lock, "pmq", 1, RT_IPC_FLAG_FIFO);
25
    return 0;
M
Ming, Bai 已提交
26
}
27
INIT_COMPONENT_EXPORT(posix_mq_system_init);
M
Ming, Bai 已提交
28 29 30

rt_inline void posix_mq_insert(mqd_t pmq)
{
Y
yiyue.fang 已提交
31 32
    pmq->next = posix_mq_list;
    posix_mq_list = pmq;
M
Ming, Bai 已提交
33 34 35 36
}

static void posix_mq_delete(mqd_t pmq)
{
Y
yiyue.fang 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
    mqd_t iter;
    if (posix_mq_list == pmq)
    {
        posix_mq_list = pmq->next;

        rt_mq_delete(pmq->mq);
        rt_free(pmq);

        return;
    }
    for (iter = posix_mq_list; iter->next != RT_NULL; iter = iter->next)
    {
        if (iter->next == pmq)
        {
            /* delete this mq */
            if (pmq->next != RT_NULL)
                iter->next = pmq->next;
            else
                iter->next = RT_NULL;

            /* delete RT-Thread mqueue */
            rt_mq_delete(pmq->mq);
            rt_free(pmq);

            return ;
        }
    }
M
Ming, Bai 已提交
64 65 66 67
}

static mqd_t posix_mq_find(const char* name)
{
Y
yiyue.fang 已提交
68 69
    mqd_t iter;
    rt_object_t object;
M
Ming, Bai 已提交
70

Y
yiyue.fang 已提交
71 72 73
    for (iter = posix_mq_list; iter != RT_NULL; iter = iter->next)
    {
        object = (rt_object_t)(iter->mq);
M
Ming, Bai 已提交
74

Y
yiyue.fang 已提交
75 76 77 78 79
        if (strncmp(object->name, name, RT_NAME_MAX) == 0)
        {
            return iter;
        }
    }
M
Ming, Bai 已提交
80

Y
yiyue.fang 已提交
81
    return RT_NULL;
M
Ming, Bai 已提交
82 83
}

Y
yiyue.fang 已提交
84 85 86
int mq_setattr(mqd_t                 mqdes,
               const struct mq_attr *mqstat,
               struct mq_attr       *omqstat)
M
Ming, Bai 已提交
87
{
Z
zhkag 已提交
88 89 90 91
    if (mqstat == RT_NULL)
        return mq_getattr(mqdes, omqstat);
    else
        rt_set_errno(-RT_ERROR);
Y
yiyue.fang 已提交
92 93

    return -1;
M
Ming, Bai 已提交
94 95 96 97 98
}
RTM_EXPORT(mq_setattr);

int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat)
{
Z
zhkag 已提交
99
    mqdes = (mqd_t)((uintptr_t)mqdes << 1);
Y
yiyue.fang 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112
    if ((mqdes == RT_NULL) || mqstat == RT_NULL)
    {
        rt_set_errno(EBADF);

        return -1;
    }

    mqstat->mq_maxmsg = mqdes->mq->max_msgs;
    mqstat->mq_msgsize = mqdes->mq->msg_size;
    mqstat->mq_curmsgs = 0;
    mqstat->mq_flags = 0;

    return 0;
M
Ming, Bai 已提交
113 114 115 116 117
}
RTM_EXPORT(mq_getattr);

mqd_t mq_open(const char *name, int oflag, ...)
{
Y
yiyue.fang 已提交
118 119
    mqd_t mqdes;
    va_list arg;
120
    mode_t mode;
Y
yiyue.fang 已提交
121
    struct mq_attr *attr = RT_NULL;
M
Ming, Bai 已提交
122 123 124 125 126

    /* lock posix mqueue list */
    rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER);

    mqdes = RT_NULL;
127 128 129 130 131 132 133
    /* find mqueue */
    mqdes = posix_mq_find(name);
    if (mqdes != RT_NULL)
    {
        mqdes->refcount ++; /* increase reference count */
    }
    else if (oflag & O_CREAT)
Y
yiyue.fang 已提交
134 135
    {
        va_start(arg, oflag);
136 137
        mode = (mode_t)va_arg(arg, unsigned int);
        mode = mode;
Y
yiyue.fang 已提交
138
        attr = (struct mq_attr *)va_arg(arg, struct mq_attr *);
Z
zhkag 已提交
139
        attr = attr;
Y
yiyue.fang 已提交
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
        va_end(arg);

        if (oflag & O_EXCL)
        {
            if (posix_mq_find(name) != RT_NULL)
            {
                rt_set_errno(EEXIST);
                goto __return;
            }
        }
        mqdes = (mqd_t) rt_malloc (sizeof(struct mqdes));
        if (mqdes == RT_NULL)
        {
            rt_set_errno(ENFILE);
            goto __return;
        }

        /* create RT-Thread message queue */
        mqdes->mq = rt_mq_create(name, attr->mq_msgsize, attr->mq_maxmsg, RT_IPC_FLAG_FIFO);
        if (mqdes->mq == RT_NULL) /* create failed */
        {
            rt_set_errno(ENFILE);
            goto __return;
        }
        /* initialize reference count */
        mqdes->refcount = 1;
        mqdes->unlinked = 0;

        /* insert mq to posix mq list */
        posix_mq_insert(mqdes);
    }
    else
    {
173 174
        rt_set_errno(ENOENT);
        goto __return;
Y
yiyue.fang 已提交
175 176 177
    }
    rt_sem_release(&posix_mq_lock);

Z
zhkag 已提交
178
    return (mqd_t)((uintptr_t)mqdes >> 1);
M
Ming, Bai 已提交
179 180

__return:
Y
yiyue.fang 已提交
181 182 183 184 185 186 187 188 189 190 191 192 193 194
    /* release lock */
    rt_sem_release(&posix_mq_lock);

    /* release allocated memory */
    if (mqdes != RT_NULL)
    {
        if (mqdes->mq != RT_NULL)
        {
            /* delete RT-Thread message queue */
            rt_mq_delete(mqdes->mq);
        }
        rt_free(mqdes);
    }
    return RT_NULL;
M
Ming, Bai 已提交
195 196 197 198 199
}
RTM_EXPORT(mq_open);

ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio)
{
Z
zhkag 已提交
200
    mqdes = (mqd_t)((uintptr_t)mqdes << 1);
Y
yiyue.fang 已提交
201
    rt_err_t result;
M
Ming, Bai 已提交
202

Y
yiyue.fang 已提交
203 204 205 206 207 208
    if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL))
    {
        rt_set_errno(EINVAL);

        return -1;
    }
M
Ming, Bai 已提交
209

Y
yiyue.fang 已提交
210 211 212
    result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, RT_WAITING_FOREVER);
    if (result == RT_EOK)
        return msg_len;
M
Ming, Bai 已提交
213

Y
yiyue.fang 已提交
214 215
    rt_set_errno(EBADF);
    return -1;
M
Ming, Bai 已提交
216 217 218 219 220
}
RTM_EXPORT(mq_receive);

int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio)
{
Z
zhkag 已提交
221
    mqdes = (mqd_t)((uintptr_t)mqdes << 1);
Y
yiyue.fang 已提交
222 223 224 225 226
    rt_err_t result;

    if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL))
    {
        rt_set_errno(EINVAL);
M
Ming, Bai 已提交
227

Y
yiyue.fang 已提交
228 229 230 231 232 233
        return -1;
    }

    result = rt_mq_send(mqdes->mq, (void*)msg_ptr, msg_len);
    if (result == RT_EOK)
        return 0;
M
Ming, Bai 已提交
234

Y
yiyue.fang 已提交
235
    rt_set_errno(EBADF);
M
Ming, Bai 已提交
236

Y
yiyue.fang 已提交
237
    return -1;
M
Ming, Bai 已提交
238 239 240
}
RTM_EXPORT(mq_send);

Y
yiyue.fang 已提交
241 242 243 244 245
ssize_t mq_timedreceive(mqd_t                  mqdes,
                        char                  *msg_ptr,
                        size_t                 msg_len,
                        unsigned              *msg_prio,
                        const struct timespec *abs_timeout)
M
Ming, Bai 已提交
246
{
Z
zhkag 已提交
247 248
    mqdes = (mqd_t)((uintptr_t)mqdes << 1);
    int tick = 0;
Y
yiyue.fang 已提交
249 250 251 252 253 254
    rt_err_t result;

    /* parameters check */
    if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL))
    {
        rt_set_errno(EINVAL);
M
Ming, Bai 已提交
255

Y
yiyue.fang 已提交
256 257
        return -1;
    }
258 259
    if (abs_timeout != RT_NULL)
        tick = rt_timespec_to_tick(abs_timeout);
M
Ming, Bai 已提交
260

Y
yiyue.fang 已提交
261 262 263
    result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, tick);
    if (result == RT_EOK)
        return msg_len;
M
Ming, Bai 已提交
264

Y
yiyue.fang 已提交
265 266 267 268
    if (result == -RT_ETIMEOUT)
        rt_set_errno(ETIMEDOUT);
    else
        rt_set_errno(EBADMSG);
M
Ming, Bai 已提交
269

Y
yiyue.fang 已提交
270
    return -1;
M
Ming, Bai 已提交
271 272 273
}
RTM_EXPORT(mq_timedreceive);

Y
yiyue.fang 已提交
274 275 276 277 278
int mq_timedsend(mqd_t                  mqdes,
                 const char            *msg_ptr,
                 size_t                 msg_len,
                 unsigned               msg_prio,
                 const struct timespec *abs_timeout)
M
Ming, Bai 已提交
279
{
Y
yiyue.fang 已提交
280 281
    /* RT-Thread does not support timed send */
    return mq_send(mqdes, msg_ptr, msg_len, msg_prio);
M
Ming, Bai 已提交
282 283 284 285 286
}
RTM_EXPORT(mq_timedsend);

int mq_notify(mqd_t mqdes, const struct sigevent *notification)
{
Z
zhkag 已提交
287
    mqdes = (mqd_t)((uintptr_t)mqdes << 1);
Y
yiyue.fang 已提交
288 289 290
    rt_set_errno(-RT_ERROR);

    return -1;
M
Ming, Bai 已提交
291 292 293 294 295
}
RTM_EXPORT(mq_notify);

int mq_close(mqd_t mqdes)
{
Z
zhkag 已提交
296
    mqdes = (mqd_t)((uintptr_t)mqdes << 1);
Y
yiyue.fang 已提交
297 298 299 300 301 302
    if (mqdes == RT_NULL)
    {
        rt_set_errno(EINVAL);

        return -1;
    }
M
Ming, Bai 已提交
303 304 305 306 307 308

    /* lock posix mqueue list */
    rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER);
    mqdes->refcount --;
    if (mqdes->refcount == 0)
    {
Y
yiyue.fang 已提交
309 310 311
        /* delete from posix mqueue list */
        if (mqdes->unlinked)
            posix_mq_delete(mqdes);
M
Ming, Bai 已提交
312 313 314 315 316 317 318 319 320
    }
    rt_sem_release(&posix_mq_lock);

    return 0;
}
RTM_EXPORT(mq_close);

int mq_unlink(const char *name)
{
Y
yiyue.fang 已提交
321
    mqd_t pmq;
M
Ming, Bai 已提交
322 323 324 325 326 327

    /* lock posix mqueue list */
    rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER);
    pmq = posix_mq_find(name);
    if (pmq != RT_NULL)
    {
Y
yiyue.fang 已提交
328 329 330 331 332 333
        pmq->unlinked = 1;
        if (pmq->refcount == 0)
        {
            /* remove this mqueue */
            posix_mq_delete(pmq);
        }
M
Ming, Bai 已提交
334
        rt_sem_release(&posix_mq_lock);
Y
yiyue.fang 已提交
335

M
Ming, Bai 已提交
336 337 338 339 340 341
        return 0;
    }
    rt_sem_release(&posix_mq_lock);

    /* no this entry */
    rt_set_errno(ENOENT);
Y
yiyue.fang 已提交
342

M
Ming, Bai 已提交
343 344 345
    return -1;
}
RTM_EXPORT(mq_unlink);