sched/mqueue: replace inline linklist to improve performance

Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
chao.an
2022-06-08 22:42:01 +08:00
committed by Xiang Xiao
parent d09dc08eab
commit 7c12e5281e
9 changed files with 71 additions and 101 deletions

View File

@@ -29,6 +29,7 @@
#include <nuttx/compiler.h>
#include <nuttx/fs/fs.h>
#include <nuttx/signal.h>
#include <nuttx/list.h>
#include <sys/types.h>
#include <stdint.h>
@@ -87,7 +88,7 @@
struct mqueue_inode_s
{
FAR struct inode *inode; /* Containing inode */
sq_queue_t msglist; /* Prioritized message list */
struct list_node msglist; /* Prioritized message list */
int16_t maxmsgs; /* Maximum number of messages in the queue */
int16_t nmsgs; /* Number of message in the queue */
int16_t nwaitnotfull; /* Number tasks waiting for not full */

View File

@@ -25,7 +25,6 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <queue.h>
#include <nuttx/kmalloc.h>
#include "mqueue/mqueue.h"
@@ -39,29 +38,13 @@
* item.
*/
sq_queue_t g_msgfree;
struct list_node g_msgfree = LIST_INITIAL_VALUE(g_msgfree);
/* The g_msgfreeInt is a list of messages that are reserved for use by
* interrupt handlers.
*/
sq_queue_t g_msgfreeirq;
/****************************************************************************
* Private Data
****************************************************************************/
/* g_msgalloc is a pointer to the start of the allocated block of
* messages.
*/
static struct mqueue_msg_s *g_msgalloc;
/* g_msgfreeirqalloc is a pointer to the start of the allocated block of
* messages.
*/
static struct mqueue_msg_s *g_msgfreeirqalloc;
struct list_node g_msgfreeirq = LIST_INITIAL_VALUE(g_msgfreeirq);
/****************************************************************************
* Private Functions
@@ -78,13 +61,13 @@ static struct mqueue_msg_s *g_msgfreeirqalloc;
*
****************************************************************************/
static struct mqueue_msg_s *
mq_msgblockalloc(FAR sq_queue_t *queue, uint16_t nmsgs,
static void
mq_msgblockalloc(FAR struct list_node *list, uint16_t nmsgs,
uint8_t alloc_type)
{
struct mqueue_msg_s *mqmsgblock;
FAR struct mqueue_msg_s *mqmsgblock;
/* The g_msgfree must be loaded at initialization time to hold the
/* The list must be loaded at initialization time to hold the
* configured number of messages.
*/
@@ -93,17 +76,14 @@ mq_msgblockalloc(FAR sq_queue_t *queue, uint16_t nmsgs,
if (mqmsgblock)
{
struct mqueue_msg_s *mqmsg = mqmsgblock;
int i;
int i;
for (i = 0; i < nmsgs; i++)
{
mqmsg->type = alloc_type;
sq_addlast((FAR sq_entry_t *)mqmsg++, queue);
mqmsgblock->type = alloc_type;
list_add_tail(list, &mqmsgblock->node);
mqmsgblock++;
}
}
return mqmsgblock;
}
/****************************************************************************
@@ -128,22 +108,15 @@ mq_msgblockalloc(FAR sq_queue_t *queue, uint16_t nmsgs,
void nxmq_initialize(void)
{
/* Initialize the message free lists */
sq_init(&g_msgfree);
sq_init(&g_msgfreeirq);
/* Allocate a block of messages for general use */
g_msgalloc =
mq_msgblockalloc(&g_msgfree, CONFIG_PREALLOC_MQ_MSGS,
MQ_ALLOC_FIXED);
mq_msgblockalloc(&g_msgfree, CONFIG_PREALLOC_MQ_MSGS,
MQ_ALLOC_FIXED);
/* Allocate a block of messages for use exclusively by
* interrupt handlers
*/
g_msgfreeirqalloc =
mq_msgblockalloc(&g_msgfreeirq, CONFIG_PREALLOC_MQ_IRQ_MSGS,
MQ_ALLOC_IRQ);
mq_msgblockalloc(&g_msgfreeirq, CONFIG_PREALLOC_MQ_IRQ_MSGS,
MQ_ALLOC_IRQ);
}

View File

@@ -25,7 +25,6 @@
#include <nuttx/config.h>
#include <assert.h>
#include <queue.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
@@ -65,7 +64,7 @@ void nxmq_free_msg(FAR struct mqueue_msg_s *mqmsg)
* list from interrupt handlers.
*/
sq_addlast((FAR sq_entry_t *)mqmsg, &g_msgfree);
list_add_tail(&g_msgfree, &mqmsg->node);
}
/* If this is a message pre-allocated for interrupts,
@@ -78,7 +77,7 @@ void nxmq_free_msg(FAR struct mqueue_msg_s *mqmsg)
* list from interrupt handlers.
*/
sq_addlast((FAR sq_entry_t *)mqmsg, &g_msgfreeirq);
list_add_tail(&g_msgfreeirq, &mqmsg->node);
}
/* Otherwise, deallocate it. Note: interrupt handlers

View File

@@ -86,7 +86,7 @@ int nxmq_alloc_msgq(FAR struct mq_attr *attr,
{
/* Initialize the new named message queue */
sq_init(&msgq->msglist);
list_initialize(&msgq->msglist);
if (attr)
{
msgq->maxmsgs = (int16_t)attr->mq_maxmsg;

View File

@@ -52,19 +52,18 @@
void nxmq_free_msgq(FAR struct mqueue_inode_s *msgq)
{
FAR struct mqueue_msg_s *curr;
FAR struct mqueue_msg_s *next;
FAR struct mqueue_msg_s *entry;
FAR struct mqueue_msg_s *tmp;
/* Deallocate any stranded messages in the message queue. */
curr = (FAR struct mqueue_msg_s *)msgq->msglist.head;
while (curr)
list_for_every_entry_safe(&msgq->msglist, entry,
tmp, struct mqueue_msg_s, node)
{
/* Deallocate the message structure. */
next = curr->next;
nxmq_free_msg(curr);
curr = next;
list_delete(&entry->node);
nxmq_free_msg(entry);
}
/* Then deallocate the message queue itself */

View File

@@ -155,8 +155,8 @@ int nxmq_wait_receive(FAR struct mqueue_inode_s *msgq,
/* Get the message from the head of the queue */
while ((newmsg = (FAR struct mqueue_msg_s *)sq_remfirst(&msgq->msglist))
== NULL)
while ((newmsg = (FAR struct mqueue_msg_s *)
list_remove_head(&msgq->msglist)) == NULL)
{
/* The queue is empty! Should we block until there the above condition
* has been satisfied?

View File

@@ -136,43 +136,34 @@ int nxmq_verify_send(FAR FAR struct file *mq, FAR const char *msg,
FAR struct mqueue_msg_s *nxmq_alloc_msg(void)
{
FAR struct mqueue_msg_s *mqmsg;
FAR struct list_node *mqmsg;
/* If we were called from an interrupt handler, then try to get the message
* from generally available list of messages. If this fails, then try the
* list of messages reserved for interrupt handlers
*/
/* Try to get the message from the generally available free list. */
if (up_interrupt_context())
mqmsg = list_remove_head(&g_msgfree);
if (mqmsg == NULL)
{
/* Try the general free list */
/* If we were called from an interrupt handler, then try to get the
* message from generally available list of messages. If this fails,
* then try the list of messages reserved for interrupt handlers
*/
mqmsg = (FAR struct mqueue_msg_s *)sq_remfirst(&g_msgfree);
if (mqmsg == NULL)
if (up_interrupt_context())
{
/* Try the free list reserved for interrupt handlers */
mqmsg = (FAR struct mqueue_msg_s *)sq_remfirst(&g_msgfreeirq);
mqmsg = list_remove_head(&g_msgfreeirq);
}
}
/* We were not called from an interrupt handler. */
/* We were not called from an interrupt handler. */
else
{
/* Try to get the message from the generally available free list.
* Disable interrupts -- we might be called from an interrupt handler.
*/
mqmsg = (FAR struct mqueue_msg_s *)sq_remfirst(&g_msgfree);
/* If we cannot a message from the free list, then we will have to
* allocate one.
*/
if (mqmsg == NULL)
else
{
mqmsg = (FAR struct mqueue_msg_s *)
/* If we cannot a message from the free list, then we will have to
* allocate one.
*/
mqmsg = (FAR struct list_node *)
kmm_malloc((sizeof (struct mqueue_msg_s)));
/* Check if we allocated the message */
@@ -183,12 +174,12 @@ FAR struct mqueue_msg_s *nxmq_alloc_msg(void)
* allocated.
*/
mqmsg->type = MQ_ALLOC_DYN;
((FAR struct mqueue_msg_s *)mqmsg)->type = MQ_ALLOC_DYN;
}
}
}
return mqmsg;
return (FAR struct mqueue_msg_s *)mqmsg;
}
/****************************************************************************
@@ -318,9 +309,9 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
FAR struct mqueue_msg_s *mqmsg,
FAR const char *msg, size_t msglen, unsigned int prio)
{
FAR struct tcb_s *btcb;
FAR struct mqueue_msg_s *prev = NULL;
FAR struct mqueue_msg_s *next;
FAR struct mqueue_msg_s *prev;
FAR struct tcb_s *btcb;
/* Construct the message header info */
@@ -336,20 +327,27 @@ int nxmq_do_send(FAR struct mqueue_inode_s *msgq,
* message. Each is list is maintained in ascending priority order.
*/
for (prev = NULL, next = (FAR struct mqueue_msg_s *)msgq->msglist.head;
next && prio <= next->priority;
prev = next, next = next->next);
list_for_every_entry(&msgq->msglist, next, struct mqueue_msg_s, node)
{
if (prio > next->priority)
{
break;
}
else
{
prev = next;
}
}
/* Add the message at the right place */
if (prev)
{
sq_addafter((FAR sq_entry_t *)prev, (FAR sq_entry_t *)mqmsg,
&msgq->msglist);
list_add_after(&prev->node, &mqmsg->node);
}
else
{
sq_addfirst((FAR sq_entry_t *)mqmsg, &msgq->msglist);
list_add_head(&msgq->msglist, &mqmsg->node);
}
/* Increment the count of messages in the queue */

View File

@@ -173,7 +173,7 @@ ssize_t file_mq_timedreceive(FAR struct file *mq, FAR char *msg,
* will not need to start timer.
*/
if (msgq->msglist.head == NULL)
if (list_is_empty(&msgq->msglist))
{
sclock_t ticks;

View File

@@ -62,15 +62,15 @@ enum mqalloc_e
struct mqueue_msg_s
{
FAR struct mqueue_msg_s *next; /* Forward link to next message */
uint8_t type; /* (Used to manage allocations) */
uint8_t priority; /* priority of message */
struct list_node node; /* Link node to message */
uint8_t type; /* (Used to manage allocations) */
uint8_t priority; /* Priority of message */
#if MQ_MAX_BYTES < 256
uint8_t msglen; /* Message data length */
uint8_t msglen; /* Message data length */
#else
uint16_t msglen; /* Message data length */
uint16_t msglen; /* Message data length */
#endif
char mail[MQ_MAX_BYTES]; /* Message data */
char mail[MQ_MAX_BYTES]; /* Message data */
};
/********************************************************************************
@@ -89,13 +89,13 @@ extern "C"
* The number of messages in this list is a system configuration item.
*/
EXTERN sq_queue_t g_msgfree;
EXTERN struct list_node g_msgfree;
/* The g_msgfreeInt is a list of messages that are reserved for use by
/* The g_msgfreeirq is a list of messages that are reserved for use by
* interrupt handlers.
*/
EXTERN sq_queue_t g_msgfreeirq;
EXTERN struct list_node g_msgfreeirq;
/********************************************************************************
* Public Function Prototypes