anchao opened a new pull request, #16226:
URL: https://github.com/apache/nuttx/pull/16226

   
   ## Summary
   
   nuttx/msgq: add kernel message queue support
   
   Currently NuttX have 2 message queue implementations:
   
   1. Posix Message Queue    
(mq_close/mq_getattr/mq_getsetattr/mq_notify/mq_open/mq_overview/mq_receive/mq_send/mq_setattr/mq_timedreceive/mq_timedsend/mq_unlink)
   2. System V Message Queue 
(msgctl/msgget/msggrep/msginit/msgmerge/msgop/msgrcv/msgsnd)
   
   Posix/SysteV message queues meet the standard implementation, But there are 
various limitations for kernel developer:
   
   1. Depends on the file system, and message sending and receiving require 
file descriptors as handles, resulting in additional resource overhead and 
performance degradation
   2. Do not support static memory pool configuration, and use global shared 
memory pools, which will cause more uncertainty in some use case.
   3. Cannot support additional capabilities(such as "message peek")
   
   So in this PR, we are planing to introduce the "nxmsgq" implementation to 
simplify the development in kernel space:
   (Compare with of Zephyr and FreeRTOS interfaces)
   
   ```
   
------------------------------------------------------------------------------
   |      NuttX          |         Zephyr          |       FreeRTOS             
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_init       |       k_msgq_init       |      xQueueCreateStatic    
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_create     |    k_msgq_alloc_init    |      xQueueCreate          
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_destroy    |    k_msgq_cleanup       |      vQueueDelete          
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_used       |    k_msgq_num_used_get  |   uxQueueMessagesWaiting   
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_space      |    k_msgq_num_free_get  |   uxQueueSpacesAvailable   
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_purge      |     k_msgq_purge        |                            
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_ticksend   |     k_msgq_put          |       xQueueSend           
|
   |   nxmsgq_trysend    |                         |      xQueueSendFromISR     
|
   |   nxmsgq_send       |                         |       xQueueSend           
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_tickrecv   |     k_msgq_get          |      xQueueReceive         
|
   |   nxmsgq_tryrecv    |                         |    xQueueReceiveFromISR    
|
   |   nxmsgq_recv       |                         |       xQueueReceive        
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_tickpeek   |     k_msgq_peek         |       xQueuePeek           
|
   |   nxmsgq_trypeek    |                         |       xQueuePeekFromISR    
|
   |   nxmsgq_peek       |                         |       xQueuePeek           
|
   
|---------------------|-------------------------|----------------------------|
   |   nxmsgq_is_empty   |                         |                            
|
   |   nxmsgq_is_full    |                         |                            
|
   
------------------------------------------------------------------------------
   ```
   
   ```
   Posix  Open Test(mq)     : loop: 1001:spending 0.13305000s
   Kernel Open Test(nxmsgq) : loop: 1001:spending 0.6345000s (-52%)
   
   Posix  Recv Test(mq)     : loop: 1001:spending 0.7884000s
   Kernel Recv Test(nxmsgq) : loop: 1001:spending 0.6837000s (-13%)
   ```
   
   Signed-off-by: chao an <anchao.arc...@bytedance.com>
   
   
   ## Impact
   
   N/A
   
   ## Testing
   
   sim/nsh,  Cortex-M55, test code as below
   
   ```
   
   #include <nuttx/config.h>
   #include <stdio.h>
   
   #include <fcntl.h>   
   #include <sys/stat.h>
   #include <mqueue.h>
   #include <nuttx/msgq.h>
   #include <nuttx/irq.h>
   #include <errno.h>
   
   /****************************************************************************
    * Public Functions
    
****************************************************************************/
   
   /****************************************************************************
    * hello_main
    
****************************************************************************/
   
   static void timespec_sub(struct timespec *dest,                            
                            struct timespec *ts1,                             
                            struct timespec *ts2)                             
   {                                                                          
     dest->tv_sec = ts1->tv_sec - ts2->tv_sec;                                
     dest->tv_nsec = ts1->tv_nsec - ts2->tv_nsec;                             
                                                                              
     if (dest->tv_nsec < 0)                                                   
       {                                                                      
         dest->tv_nsec += 1000000000;                                         
         dest->tv_sec -= 1;                                                   
       }                                                                      
   }       
   
   void mq_open_test(void)
   {
     struct timespec result;                                                  
     struct timespec start;                                                   
     struct timespec end;     
     nxmsgq_t *msg;
     mqd_t mq;
   
     irqstate_t flags;
     int loop = 0;
     
   
     /* Posix Message Queue Test */
   
     flags = enter_critical_section();
     clock_gettime(CLOCK_MONOTONIC, &start);
     while (loop++ < 1000)
       {
         mq = mq_open("test", O_RDWR | O_CREAT, 0644, NULL);
         if (mq < 0) {
           printf("mq_open fail: %d\n", mq);
           break;
         }
   
         mq_close(mq);
       }
     clock_gettime(CLOCK_MONOTONIC, &end);
     leave_critical_section(flags);
   
     timespec_sub(&result, &end, &start);
     printf("Posix  Open Test : loop: %d:spending %lld.%lds\n", loop, 
result.tv_sec, result.tv_nsec);
   
     /* Kernel Message Queue Test */
   
     loop = 0;
   
     flags = enter_critical_section();
     clock_gettime(CLOCK_MONOTONIC, &start);
     while (loop++ < 1000)
       {
         msg = nxmsgq_create(64, 8);
         if (msg == NULL) {
           printf("nxmsgq_create fail: %p\n", msg);
           break;
         }
   
         nxmsgq_destroy(msg);
       }
     clock_gettime(CLOCK_MONOTONIC, &end);
     leave_critical_section(flags);
   
     timespec_sub(&result, &end, &start);
   
     printf("Kernel Open Test : loop: %d:spending %lld.%lds\n", loop, 
result.tv_sec, result.tv_nsec);
   }
   
   mqd_t     g_mq;
   nxmsgq_t *g_msg;
   
   void *message_thread(void *arg)
   {
     struct timespec result;                                                  
     struct timespec start;                                                   
     struct timespec end;     
     irqstate_t flags;
     char tmp[64];
     int loop = 0;
     int ret;
     unsigned int prio;
   
     /* Posix Message Queue Test */
   
     flags = enter_critical_section();
     clock_gettime(CLOCK_MONOTONIC, &start);
     while (loop++ < 1000)
       {
         ret = mq_receive(g_mq, tmp, 64, &prio);
         if (ret < 0)
           {
             printf("mq_receive fail: %d, loop: %d, errno: %d\n", ret, loop, 
errno);
             return NULL;
           }
       }
     clock_gettime(CLOCK_MONOTONIC, &end);
     leave_critical_section(flags);
   
     timespec_sub(&result, &end, &start);
     printf("Posix  Recv Test : loop: %d:spending %lld.%lds\n", loop, 
result.tv_sec, result.tv_nsec);
   
     /* Kernel Message Queue Test */
   
     loop = 0;
   
     flags = enter_critical_section();
     clock_gettime(CLOCK_MONOTONIC, &start);
     while (loop++ < 1000)
       {
         ret = nxmsgq_recv(g_msg, tmp);
         if (ret < 0)
           {
             printf("nxmsgq_recv fail: %d, loop: %d\n", ret, loop);
             return NULL;
           }
       }
     clock_gettime(CLOCK_MONOTONIC, &end);
     leave_critical_section(flags);
   
     timespec_sub(&result, &end, &start);
     printf("Kernel Recv Test : loop: %d:spending %lld.%lds\n", loop, 
result.tv_sec, result.tv_nsec);
   
     return NULL;
   }
   
   
   void mq_sendrecv_test(void)
   {
     struct sched_param sparam;
     pthread_attr_t tattr;
     pthread_t pid;
     char tmp[64];
     int loop = 0;
     int ret;
   
     g_mq = mq_open("test", O_RDWR | O_CREAT, 0644, NULL);
     if (g_mq < 0)
       {
         printf("mq_open fail: %d\n", g_mq);
         return;
       }
   
     g_msg = nxmsgq_create(64, 8);
     if (g_msg < 0)
       {
         printf("nxmsgq_create fail: %p\n", g_msg);
         return;
       }
   
     pthread_attr_init(&tattr);
     sparam.sched_priority = 200;
     pthread_attr_setschedparam(&tattr, &sparam);
   
     pthread_create(&pid, &tattr, message_thread, NULL);
   
     while (loop++ < 1000)
       {
         ret = mq_send(g_mq, tmp, 64, 0);
         if (ret < 0)
           {
             printf("mq_send fail: %d\n", ret);
             return;
           }
       }
   
     loop = 0;
     while (loop++ < 1000)
       {
         ret = nxmsgq_send(g_msg, tmp);
         if (ret < 0)
           {
             printf("nxmsgq_send fail: %d\n", ret);
             return;
           }
       }
   
   }
   
   int main(int argc, FAR char *argv[])
   {
     mq_open_test();
     mq_sendrecv_test();
     return 0;
   }
   ```
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to