diff --git a/components/libc/posix/ipc/mqueue.c b/components/libc/posix/ipc/mqueue.c index 4ab471c446..684891731e 100644 --- a/components/libc/posix/ipc/mqueue.c +++ b/components/libc/posix/ipc/mqueue.c @@ -13,9 +13,10 @@ #include #include #include +#include #include "mqueue.h" -static mqd_t posix_mq_list = RT_NULL; +static mqdes_t posix_mq_list = RT_NULL; static struct rt_semaphore posix_mq_lock; /* initialize posix mqueue */ @@ -26,15 +27,19 @@ static int posix_mq_system_init(void) } INIT_COMPONENT_EXPORT(posix_mq_system_init); -rt_inline void posix_mq_insert(mqd_t pmq) +rt_inline void posix_mq_insert(mqdes_t pmq) { + if (posix_mq_list == RT_NULL) + pmq->mq_id = 1; + else + pmq->mq_id = posix_mq_list->mq_id + 1; pmq->next = posix_mq_list; posix_mq_list = pmq; } -static void posix_mq_delete(mqd_t pmq) +static void posix_mq_delete(mqdes_t pmq) { - mqd_t iter; + mqdes_t iter; if (posix_mq_list == pmq) { posix_mq_list = pmq->next; @@ -63,9 +68,9 @@ static void posix_mq_delete(mqd_t pmq) } } -static mqd_t posix_mq_find(const char* name) +static mqdes_t posix_mq_find(const char *name) { - mqd_t iter; + mqdes_t iter; rt_object_t object; for (iter = posix_mq_list; iter != RT_NULL; iter = iter->next) @@ -81,12 +86,20 @@ static mqd_t posix_mq_find(const char* name) return RT_NULL; } -int mq_setattr(mqd_t mqdes, +static mqdes_t posix_mq_id_find(mqd_t id) +{ + for (mqdes_t iter = posix_mq_list; iter != RT_NULL; iter = iter->next) + if (iter->mq_id == id) + return iter; + return RT_NULL; +} + +int mq_setattr(mqd_t id, const struct mq_attr *mqstat, struct mq_attr *omqstat) { if (mqstat == RT_NULL) - return mq_getattr(mqdes, omqstat); + return mq_getattr(id, omqstat); else rt_set_errno(-RT_ERROR); @@ -94,9 +107,11 @@ int mq_setattr(mqd_t mqdes, } RTM_EXPORT(mq_setattr); -int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat) +int mq_getattr(mqd_t id, struct mq_attr *mqstat) { - mqdes = (mqd_t)((uintptr_t)mqdes << 1); + rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); + mqdes_t mqdes = posix_mq_id_find(id); + rt_sem_release(&posix_mq_lock); if ((mqdes == RT_NULL) || mqstat == RT_NULL) { rt_set_errno(EBADF); @@ -115,20 +130,30 @@ RTM_EXPORT(mq_getattr); mqd_t mq_open(const char *name, int oflag, ...) { - mqd_t mqdes; va_list arg; mode_t mode; + mqdes_t mqdes = RT_NULL; struct mq_attr *attr = RT_NULL; /* lock posix mqueue list */ rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); + int len = rt_strlen(name); + if (len > PATH_MAX || len > NAME_MAX) + { + rt_set_errno(ENAMETOOLONG); + goto __return; + } - mqdes = RT_NULL; - /* find mqueue */ mqdes = posix_mq_find(name); if (mqdes != RT_NULL) { - mqdes->refcount ++; /* increase reference count */ + if (oflag & O_CREAT && oflag & O_EXCL) + { + rt_set_errno(EEXIST); + rt_sem_release(&posix_mq_lock); + return (mqd_t)(-1); + } + mqdes->refcount++; /* increase reference count */ } else if (oflag & O_CREAT) { @@ -139,15 +164,13 @@ mqd_t mq_open(const char *name, int oflag, ...) attr = attr; va_end(arg); - if (oflag & O_EXCL) + if (attr->mq_maxmsg <= 0) { - if (posix_mq_find(name) != RT_NULL) - { - rt_set_errno(EEXIST); - goto __return; - } + rt_set_errno(EINVAL); + goto __return; } - mqdes = (mqd_t) rt_malloc (sizeof(struct mqdes)); + + mqdes = (mqdes_t) rt_malloc (sizeof(struct mqdes)); if (mqdes == RT_NULL) { rt_set_errno(ENFILE); @@ -175,7 +198,7 @@ mqd_t mq_open(const char *name, int oflag, ...) } rt_sem_release(&posix_mq_lock); - return (mqd_t)((uintptr_t)mqdes >> 1); + return (mqd_t)(mqdes->mq_id); __return: /* release lock */ @@ -191,13 +214,15 @@ __return: } rt_free(mqdes); } - return RT_NULL; + return (mqd_t)(-1); } RTM_EXPORT(mq_open); -ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio) +ssize_t mq_receive(mqd_t id, char *msg_ptr, size_t msg_len, unsigned *msg_prio) { - mqdes = (mqd_t)((uintptr_t)mqdes << 1); + rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); + mqdes_t mqdes = posix_mq_id_find(id); + rt_sem_release(&posix_mq_lock); rt_err_t result; if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) @@ -209,16 +234,18 @@ ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_pri result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, RT_WAITING_FOREVER); if (result == RT_EOK) - return msg_len; + return rt_strlen(msg_ptr); rt_set_errno(EBADF); return -1; } RTM_EXPORT(mq_receive); -int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio) +int mq_send(mqd_t id, const char *msg_ptr, size_t msg_len, unsigned msg_prio) { - mqdes = (mqd_t)((uintptr_t)mqdes << 1); + rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); + mqdes_t mqdes = posix_mq_id_find(id); + rt_sem_release(&posix_mq_lock); rt_err_t result; if ((mqdes == RT_NULL) || (msg_ptr == RT_NULL)) @@ -238,13 +265,15 @@ int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio) } RTM_EXPORT(mq_send); -ssize_t mq_timedreceive(mqd_t mqdes, +ssize_t mq_timedreceive(mqd_t id, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout) { - mqdes = (mqd_t)((uintptr_t)mqdes << 1); + rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); + mqdes_t mqdes = posix_mq_id_find(id); + rt_sem_release(&posix_mq_lock); int tick = 0; rt_err_t result; @@ -260,10 +289,12 @@ ssize_t mq_timedreceive(mqd_t mqdes, result = rt_mq_recv(mqdes->mq, msg_ptr, msg_len, tick); if (result == RT_EOK) - return msg_len; + return rt_strlen(msg_ptr); if (result == -RT_ETIMEOUT) rt_set_errno(ETIMEDOUT); + else if (result == -RT_ERROR) + rt_set_errno(EMSGSIZE); else rt_set_errno(EBADMSG); @@ -271,33 +302,41 @@ ssize_t mq_timedreceive(mqd_t mqdes, } RTM_EXPORT(mq_timedreceive); -int mq_timedsend(mqd_t mqdes, +int mq_timedsend(mqd_t id, const char *msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec *abs_timeout) { /* RT-Thread does not support timed send */ - return mq_send(mqdes, msg_ptr, msg_len, msg_prio); + return mq_send(id, msg_ptr, msg_len, msg_prio); } RTM_EXPORT(mq_timedsend); -int mq_notify(mqd_t mqdes, const struct sigevent *notification) +int mq_notify(mqd_t id, const struct sigevent *notification) { - mqdes = (mqd_t)((uintptr_t)mqdes << 1); + rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); + mqdes_t mqdes = posix_mq_id_find(id); + rt_sem_release(&posix_mq_lock); + if (mqdes == RT_NULL || mqdes->refcount == 0) + { + rt_set_errno(EBADF); + return -1; + } rt_set_errno(-RT_ERROR); return -1; } RTM_EXPORT(mq_notify); -int mq_close(mqd_t mqdes) +int mq_close(mqd_t id) { - mqdes = (mqd_t)((uintptr_t)mqdes << 1); + rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); + mqdes_t mqdes = posix_mq_id_find(id); + rt_sem_release(&posix_mq_lock); if (mqdes == RT_NULL) { - rt_set_errno(EINVAL); - + rt_set_errno(EBADF); return -1; } @@ -318,7 +357,7 @@ RTM_EXPORT(mq_close); int mq_unlink(const char *name) { - mqd_t pmq; + mqdes_t pmq; /* lock posix mqueue list */ rt_sem_take(&posix_mq_lock, RT_WAITING_FOREVER); diff --git a/components/libc/posix/ipc/mqueue.h b/components/libc/posix/ipc/mqueue.h index 4872dc238d..665ebb20e7 100644 --- a/components/libc/posix/ipc/mqueue.h +++ b/components/libc/posix/ipc/mqueue.h @@ -22,10 +22,14 @@ struct mqdes /* RT-Thread message queue */ rt_mq_t mq; + + int mq_id; /* next posix mqueue */ struct mqdes* next; }; -typedef struct mqdes* mqd_t; +typedef struct mqdes* mqdes_t; + +typedef int mqd_t; struct mq_attr { diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 373a36b779..f4295b4b55 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -4378,10 +4378,22 @@ mqd_t sys_mq_open(const char *name, int flags, mode_t mode, struct mq_attr *attr if (!kname) return (mqd_t)-ENOMEM; - lwp_get_from_user(&attr_k, (void *)attr, sizeof(struct mq_attr)); + if (attr == NULL) + { + attr_k.mq_maxmsg = 10; + attr_k.mq_msgsize = 8192; + attr_k.mq_flags = 0; + attr = &attr_k; + } + else + { + if (!lwp_get_from_user(&attr_k, (void *)attr, sizeof(struct mq_attr))) + return -EINVAL; + } + lwp_get_from_user(kname, (void *)name, len + 1); mqdes = mq_open(kname, flags, mode, &attr_k); - if (mqdes == RT_NULL) + if (mqdes == -1) { ret = GET_ERRNO(); } @@ -4390,7 +4402,7 @@ mqd_t sys_mq_open(const char *name, int flags, mode_t mode, struct mq_attr *attr #else mqdes = mq_open(name, flags, mode, attr); #endif - if (mqdes == RT_NULL) + if (mqdes == -1) return (mqd_t)ret; else return mqdes; @@ -4476,9 +4488,18 @@ sysret_t sys_mq_timedreceive(mqd_t mqd, char *restrict msg, size_t len, unsigned if (!kmsg) return -ENOMEM; - lwp_get_from_user(&at_k, (void *)at, sizeof(struct timespec)); lwp_get_from_user(kmsg, (void *)msg, len + 1); - ret = mq_timedreceive(mqd, kmsg, len, prio, &at_k); + if (at == RT_NULL) + { + ret = mq_timedreceive(mqd, kmsg, len, prio, RT_NULL); + } + else + { + if (!lwp_get_from_user(&at_k, (void *)at, sizeof(struct timespec))) + return -EINVAL; + ret = mq_timedreceive(mqd, kmsg, len, prio, &at_k); + } + if (ret > 0) lwp_put_to_user(msg, kmsg, len + 1);