wireless/bluetooth: Soften use of enter_critical_sectino() which is a performance hog in SMP configurations. Replace with spin_lock_irqsave() in most cases. That is the same for single core CPUs, but much more efficient in SMP configurations. And better, repace with sched_lock() if there is really no necessity to disable interrupts too.

This commit is contained in:
Gregory Nutt
2018-04-14 17:55:30 -06:00
parent f45ec5c695
commit 91ff7cc785
3 changed files with 20 additions and 17 deletions
+8 -8
View File
@@ -242,7 +242,7 @@ FAR struct bt_buf_s *bt_buf_alloc(enum bt_buf_type_e type,
* then try the list of messages reserved for interrupt handlers * then try the list of messages reserved for interrupt handlers
*/ */
flags = enter_critical_section(); /* Always necessary in SMP mode */ flags = spin_lock_irqsave(); /* Always necessary in SMP mode */
if (up_interrupt_context()) if (up_interrupt_context())
{ {
#if CONFIG_BLUETOOTH_BUFFER_PREALLOC > CONFIG_BLUETOOTH_BUFFER_IRQRESERVE #if CONFIG_BLUETOOTH_BUFFER_PREALLOC > CONFIG_BLUETOOTH_BUFFER_IRQRESERVE
@@ -253,7 +253,7 @@ FAR struct bt_buf_s *bt_buf_alloc(enum bt_buf_type_e type,
buf = g_buf_free; buf = g_buf_free;
g_buf_free = buf->flink; g_buf_free = buf->flink;
leave_critical_section(flags); spin_unlock_irqrestore(flags);
pool = POOL_BUFFER_GENERAL; pool = POOL_BUFFER_GENERAL;
} }
else else
@@ -266,13 +266,13 @@ FAR struct bt_buf_s *bt_buf_alloc(enum bt_buf_type_e type,
buf = g_buf_free_irq; buf = g_buf_free_irq;
g_buf_free_irq = buf->flink; g_buf_free_irq = buf->flink;
leave_critical_section(flags); spin_unlock_irqrestore(flags);
pool = POOL_BUFFER_IRQ; pool = POOL_BUFFER_IRQ;
} }
else else
#endif #endif
{ {
leave_critical_section(flags); spin_unlock_irqrestore(flags);
return NULL; return NULL;
} }
} }
@@ -422,10 +422,10 @@ void bt_buf_release(FAR struct bt_buf_s *buf)
* list from interrupt handlers. * list from interrupt handlers.
*/ */
flags = enter_critical_section(); flags = spin_lock_irqsave();
buf->flink = g_buf_free; buf->flink = g_buf_free;
g_buf_free = buf; g_buf_free = buf;
leave_critical_section(flags); spin_unlock_irqrestore(flags);
} }
else else
#endif #endif
@@ -441,10 +441,10 @@ void bt_buf_release(FAR struct bt_buf_s *buf)
* list from interrupt handlers. * list from interrupt handlers.
*/ */
flags = enter_critical_section(); flags = spin_lock_irqsave();
buf->flink = g_buf_free_irq; buf->flink = g_buf_free_irq;
g_buf_free_irq = buf; g_buf_free_irq = buf;
leave_critical_section(flags); spin_unlock_irqrestore(flags);
} }
else else
#endif #endif
+10 -7
View File
@@ -50,10 +50,10 @@
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <time.h> #include <time.h>
#include <sched.h>
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/clock.h> #include <nuttx/clock.h>
#include <nuttx/kthread.h> #include <nuttx/kthread.h>
#include <nuttx/semaphore.h> #include <nuttx/semaphore.h>
@@ -1518,20 +1518,23 @@ int bt_hci_cmd_send_sync(uint16_t opcode, FAR struct bt_buf_s *buf,
else else
{ {
struct timespec abstime; struct timespec abstime;
irqstate_t flags;
/* Wait for the response to the command. An I/O error will be /* Wait for the response to the command. An I/O error will be
* declared if the response does not occur within the timeout * declared if the response does not occur within the timeout
* interval. * interval.
* *
* Get the current time. Not that we must be in critical section here * REVISIT: The cause of the timeout could be a failure to receive a
* so that we can be assured that there will be no context switches * response to a sent frame or, perhaps, a failure to send the frame.
* Should there also be logic to flush any unsent Tx packets?
*
* Get the current time. Not that we lock the scheduler here so that
* we can be assured that there will be no context switches will occur
* between the time that we calculate the delay time and until we get * between the time that we calculate the delay time and until we get
* to the wait. * to the wait.
*/ */
flags = enter_critical_section(); sched_lock();
ret = clock_gettime(CLOCK_REALTIME, &abstime); ret = clock_gettime(CLOCK_REALTIME, &abstime);
if (ret >= 0) if (ret >= 0)
{ {
/* Add the offset to the time in the future */ /* Add the offset to the time in the future */
@@ -1560,7 +1563,7 @@ int bt_hci_cmd_send_sync(uint16_t opcode, FAR struct bt_buf_s *buf,
while (ret == -EINTR); while (ret == -EINTR);
} }
leave_critical_section(flags); sched_unlock();
} }
/* Indicate failure if we failed to get the response */ /* Indicate failure if we failed to get the response */
+2 -2
View File
@@ -662,7 +662,7 @@ static int btnet_ifdown(FAR struct net_driver_s *netdev)
/* Disable interruption */ /* Disable interruption */
flags = enter_critical_section(); flags = spin_lock_irqsave();
/* Cancel the TX poll timer and TX timeout timers */ /* Cancel the TX poll timer and TX timeout timers */
@@ -676,7 +676,7 @@ static int btnet_ifdown(FAR struct net_driver_s *netdev)
/* Mark the device "down" */ /* Mark the device "down" */
priv->bd_bifup = false; priv->bd_bifup = false;
leave_critical_section(flags); spin_unlock_irqrestore(flags);
return OK; return OK;
} }