Răsfoiți Sursa

[components][posix] 完善 posix 接口消息队列 (#7395)

zhkag 2 ani în urmă
părinte
comite
a6a9b0dfcb

+ 79 - 40
components/libc/posix/ipc/mqueue.c

@@ -13,9 +13,10 @@
 #include <sys/time.h>
 #include <sys/errno.h>
 #include <rtthread.h>
+#include <limits.h>
 #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);

+ 5 - 1
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
 {

+ 26 - 5
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);