mirror of
https://github.com/apache/nuttx.git
synced 2025-12-17 10:16:49 +08:00
sched/mqueue: replace inline linklist to improve performance
Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user