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

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
*/
flags = enter_critical_section(); /* Always necessary in SMP mode */
flags = spin_lock_irqsave(); /* Always necessary in SMP mode */
if (up_interrupt_context())
{
#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;
g_buf_free = buf->flink;
leave_critical_section(flags);
spin_unlock_irqrestore(flags);
pool = POOL_BUFFER_GENERAL;
}
else
@ -266,13 +266,13 @@ FAR struct bt_buf_s *bt_buf_alloc(enum bt_buf_type_e type,
buf = g_buf_free_irq;
g_buf_free_irq = buf->flink;
leave_critical_section(flags);
spin_unlock_irqrestore(flags);
pool = POOL_BUFFER_IRQ;
}
else
#endif
{
leave_critical_section(flags);
spin_unlock_irqrestore(flags);
return NULL;
}
}
@ -422,10 +422,10 @@ void bt_buf_release(FAR struct bt_buf_s *buf)
* list from interrupt handlers.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave();
buf->flink = g_buf_free;
g_buf_free = buf;
leave_critical_section(flags);
spin_unlock_irqrestore(flags);
}
else
#endif
@ -441,10 +441,10 @@ void bt_buf_release(FAR struct bt_buf_s *buf)
* list from interrupt handlers.
*/
flags = enter_critical_section();
flags = spin_lock_irqsave();
buf->flink = g_buf_free_irq;
g_buf_free_irq = buf;
leave_critical_section(flags);
spin_unlock_irqrestore(flags);
}
else
#endif

View File

@ -50,10 +50,10 @@
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <sched.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/clock.h>
#include <nuttx/kthread.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
{
struct timespec abstime;
irqstate_t flags;
/* Wait for the response to the command. An I/O error will be
* declared if the response does not occur within the timeout
* interval.
*
* Get the current time. Not that we must be in critical section here
* so that we can be assured that there will be no context switches
* REVISIT: The cause of the timeout could be a failure to receive a
* 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
* to the wait.
*/
flags = enter_critical_section();
ret = clock_gettime(CLOCK_REALTIME, &abstime);
sched_lock();
ret = clock_gettime(CLOCK_REALTIME, &abstime);
if (ret >= 0)
{
/* 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);
}
leave_critical_section(flags);
sched_unlock();
}
/* Indicate failure if we failed to get the response */

View File

@ -662,7 +662,7 @@ static int btnet_ifdown(FAR struct net_driver_s *netdev)
/* Disable interruption */
flags = enter_critical_section();
flags = spin_lock_irqsave();
/* 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" */
priv->bd_bifup = false;
leave_critical_section(flags);
spin_unlock_irqrestore(flags);
return OK;
}