spin_lock: inline spin_lock
test: We can use qemu for testing. compiling make distclean -j20; ./tools/configure.sh -l qemu-armv8a:nsh_smp ;make -j20 running qemu-system-aarch64 -cpu cortex-a53 -smp 4 -nographic -machine virt,virtualization=on,gic-version=3 -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel ./nuttx
This commit is contained in:
parent
ae8ce535f3
commit
a4fece3450
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
# include <termios.h>
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
# include <termios.h>
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "sam_gpio.h"
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "sam_pio.h"
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
# include <termios.h>
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "hardware/tms570_sci.h"
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/tioctl.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "bl602_lowputc.h"
|
||||
#include "bl602_gpio.h"
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "riscv_internal.h"
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_TERMIOS
|
||||
# include <termios.h>
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <arch/arch.h>
|
||||
#include <arch/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "init/init.h"
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "xtensa.h"
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/analog/dac.h>
|
||||
#include <debug.h>
|
||||
#include "esp32_dac.h"
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "xtensa.h"
|
||||
#include "esp32s2_clockconfig.h"
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/board.h>
|
||||
#include <nuttx/power/pm.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "xtensa.h"
|
||||
#include "esp32s3_pm.h"
|
||||
|
@ -1170,6 +1170,27 @@ void sched_note_spinlock(FAR struct tcb_s *tcb,
|
||||
note_add(*driver, ¬e, sizeof(struct note_spinlock_s));
|
||||
}
|
||||
}
|
||||
|
||||
void sched_note_spinlock_lock(FAR volatile spinlock_t *spinlock)
|
||||
{
|
||||
sched_note_spinlock(this_task(), spinlock, NOTE_SPINLOCK_LOCK);
|
||||
}
|
||||
|
||||
void sched_note_spinlock_locked(FAR volatile spinlock_t *spinlock)
|
||||
{
|
||||
sched_note_spinlock(this_task(), spinlock, NOTE_SPINLOCK_LOCKED);
|
||||
}
|
||||
|
||||
void sched_note_spinlock_abort(FAR volatile spinlock_t *spinlock)
|
||||
{
|
||||
sched_note_spinlock(this_task(), spinlock, NOTE_SPINLOCK_ABORT);
|
||||
}
|
||||
|
||||
void sched_note_spinlock_unlock(FAR volatile spinlock_t *spinlock)
|
||||
{
|
||||
sched_note_spinlock(this_task(), spinlock, NOTE_SPINLOCK_UNLOCK);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <nuttx/serial/serial.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
#include <nuttx/serial/uart_16550.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/spawn.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_FDSAN
|
||||
# include <android/fdsan.h>
|
||||
@ -66,11 +67,11 @@ static FAR struct file *files_fget_by_index(FAR struct filelist *list,
|
||||
FAR struct file *filep;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = spin_lock_irqsave(&list->fl_lock);
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
|
||||
filep = &list->fl_files[l1][l2];
|
||||
|
||||
spin_unlock_irqrestore(&list->fl_lock, flags);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
|
||||
return filep;
|
||||
}
|
||||
@ -125,7 +126,7 @@ static int files_extend(FAR struct filelist *list, size_t row)
|
||||
}
|
||||
while (++i < row);
|
||||
|
||||
flags = spin_lock_irqsave(&list->fl_lock);
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
|
||||
/* To avoid race condition, if the file list is updated by other threads
|
||||
* and list rows is greater or equal than temp list,
|
||||
@ -134,7 +135,7 @@ static int files_extend(FAR struct filelist *list, size_t row)
|
||||
|
||||
if (orig_rows != list->fl_rows && list->fl_rows >= row)
|
||||
{
|
||||
spin_unlock_irqrestore(&list->fl_lock, flags);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
|
||||
for (j = orig_rows; j < i; j++)
|
||||
{
|
||||
@ -156,7 +157,7 @@ static int files_extend(FAR struct filelist *list, size_t row)
|
||||
list->fl_files = files;
|
||||
list->fl_rows = row;
|
||||
|
||||
spin_unlock_irqrestore(&list->fl_lock, flags);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
|
||||
if (tmp != NULL && tmp != &list->fl_prefile)
|
||||
{
|
||||
@ -484,13 +485,13 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode,
|
||||
|
||||
/* Find free file */
|
||||
|
||||
flags = spin_lock_irqsave(&list->fl_lock);
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
|
||||
for (; ; i++, j = 0)
|
||||
{
|
||||
if (i >= list->fl_rows)
|
||||
{
|
||||
spin_unlock_irqrestore(&list->fl_lock, flags);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
|
||||
ret = files_extend(list, i + 1);
|
||||
if (ret < 0)
|
||||
@ -498,7 +499,7 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode,
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = spin_lock_irqsave(&list->fl_lock);
|
||||
flags = spin_lock_irqsave(NULL);
|
||||
}
|
||||
|
||||
do
|
||||
@ -518,7 +519,7 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode,
|
||||
}
|
||||
|
||||
found:
|
||||
spin_unlock_irqrestore(&list->fl_lock, flags);
|
||||
spin_unlock_irqrestore(NULL, flags);
|
||||
|
||||
if (addref)
|
||||
{
|
||||
|
@ -37,10 +37,10 @@
|
||||
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/mm/map.h>
|
||||
#include <nuttx/spawn.h>
|
||||
#include <nuttx/queue.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@ -490,7 +490,6 @@ struct file
|
||||
|
||||
struct filelist
|
||||
{
|
||||
spinlock_t fl_lock; /* Manage access to the file list */
|
||||
uint8_t fl_rows; /* The number of rows of fl_files array */
|
||||
FAR struct file **fl_files; /* The pointer of two layer file descriptors array */
|
||||
|
||||
|
@ -28,8 +28,30 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(CONFIG_TICKET_SPINLOCK) || defined(CONFIG_RW_SPINLOCK)
|
||||
# if !defined(__cplusplus)
|
||||
# include <stdatomic.h>
|
||||
# define CONFIG_HAVE_INLINE_SPINLOCK
|
||||
# elif defined(__has_include) && __has_include(<atomic>)
|
||||
extern "C++"
|
||||
{
|
||||
# include <atomic>
|
||||
# define CONFIG_HAVE_INLINE_SPINLOCK
|
||||
using std::atomic_int;
|
||||
using std::atomic_load;
|
||||
using std::atomic_fetch_add;
|
||||
using std::atomic_fetch_sub;
|
||||
using std::atomic_compare_exchange_strong;
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
# define CONFIG_HAVE_INLINE_SPINLOCK
|
||||
#endif
|
||||
|
||||
#include <nuttx/compiler.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#undef EXTERN
|
||||
@ -123,6 +145,18 @@ typedef union spinlock_u spinlock_t;
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
void sched_note_spinlock_lock(FAR volatile spinlock_t *spinlock);
|
||||
void sched_note_spinlock_locked(FAR volatile spinlock_t *spinlock);
|
||||
void sched_note_spinlock_abort(FAR volatile spinlock_t *spinlock);
|
||||
void sched_note_spinlock_unlock(FAR volatile spinlock_t *spinlock);
|
||||
#else
|
||||
# define sched_note_spinlock_lock(spinlock)
|
||||
# define sched_note_spinlock_locked(spinlock)
|
||||
# define sched_note_spinlock_abort(spinlock)
|
||||
# define sched_note_spinlock_unlocked(spinlock)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_testset
|
||||
*
|
||||
@ -184,6 +218,8 @@ static inline spinlock_t up_testset(FAR volatile spinlock_t *lock)
|
||||
/* void spin_lock_init(FAR spinlock_t *lock); */
|
||||
#define spin_lock_init(l) do { *(l) = SP_UNLOCKED; } while (0)
|
||||
|
||||
#ifdef CONFIG_HAVE_INLINE_SPINLOCK
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_lock
|
||||
*
|
||||
@ -207,7 +243,34 @@ static inline spinlock_t up_testset(FAR volatile spinlock_t *lock)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void spin_lock(FAR volatile spinlock_t *lock);
|
||||
static inline_function void spin_lock(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
|
||||
/* Notify that we are waiting for a spinlock */
|
||||
|
||||
sched_note_spinlock_lock(lock);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
unsigned short ticket =
|
||||
atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.next, 1);
|
||||
while (atomic_load((FAR atomic_ushort *)&lock->tickets.owner) != ticket)
|
||||
#else /* CONFIG_SPINLOCK */
|
||||
while (up_testset(lock) == SP_LOCKED)
|
||||
#endif
|
||||
{
|
||||
SP_DSB();
|
||||
SP_WFE();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we have the spinlock */
|
||||
|
||||
sched_note_spinlock_locked(lock);
|
||||
#endif
|
||||
SP_DMB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_lock_wo_note
|
||||
@ -231,7 +294,22 @@ void spin_lock(FAR volatile spinlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void spin_lock_wo_note(FAR volatile spinlock_t *lock);
|
||||
static inline_function void spin_lock_wo_note(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
unsigned short ticket =
|
||||
atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.next, 1);
|
||||
while (atomic_load((FAR atomic_ushort *)&lock->tickets.owner) != ticket)
|
||||
#else /* CONFIG_TICKET_SPINLOCK */
|
||||
while (up_testset(lock) == SP_LOCKED)
|
||||
#endif
|
||||
{
|
||||
SP_DSB();
|
||||
SP_WFE();
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_trylock
|
||||
@ -252,7 +330,56 @@ void spin_lock_wo_note(FAR volatile spinlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool spin_trylock(FAR volatile spinlock_t *lock);
|
||||
static inline_function bool spin_trylock(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
|
||||
/* Notify that we are waiting for a spinlock */
|
||||
|
||||
sched_note_spinlock_lock(lock);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
unsigned short ticket =
|
||||
atomic_load((FAR atomic_ushort *)&lock->tickets.next);
|
||||
|
||||
spinlock_t old =
|
||||
{
|
||||
{
|
||||
ticket, ticket
|
||||
}
|
||||
};
|
||||
|
||||
spinlock_t new =
|
||||
{
|
||||
{
|
||||
ticket, ticket + 1
|
||||
}
|
||||
};
|
||||
|
||||
if (!atomic_compare_exchange_strong((FAR atomic_uint *)&lock->value,
|
||||
&old.value, new.value))
|
||||
#else /* CONFIG_TICKET_SPINLOCK */
|
||||
if (up_testset(lock) == SP_LOCKED)
|
||||
#endif /* CONFIG_TICKET_SPINLOCK */
|
||||
{
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we abort for a spinlock */
|
||||
|
||||
sched_note_spinlock_abort(lock);
|
||||
#endif
|
||||
SP_DSB();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we have the spinlock */
|
||||
|
||||
sched_note_spinlock_locked(lock);
|
||||
#endif
|
||||
SP_DMB();
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_trylock_wo_note
|
||||
@ -276,7 +403,40 @@ bool spin_trylock(FAR volatile spinlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool spin_trylock_wo_note(FAR volatile spinlock_t *lock);
|
||||
static inline_function bool
|
||||
spin_trylock_wo_note(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
unsigned short ticket =
|
||||
atomic_load((FAR atomic_ushort *)&lock->tickets.next);
|
||||
|
||||
spinlock_t old =
|
||||
{
|
||||
{
|
||||
ticket, ticket
|
||||
}
|
||||
};
|
||||
|
||||
spinlock_t new =
|
||||
{
|
||||
{
|
||||
ticket, ticket + 1
|
||||
}
|
||||
};
|
||||
|
||||
if (!atomic_compare_exchange_strong((FAR atomic_uint *)&lock->value,
|
||||
&old.value, new.value))
|
||||
#else /* CONFIG_TICKET_SPINLOCK */
|
||||
if (up_testset(lock) == SP_LOCKED)
|
||||
#endif /* CONFIG_TICKET_SPINLOCK */
|
||||
{
|
||||
SP_DSB();
|
||||
return false;
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_unlock
|
||||
@ -296,7 +456,23 @@ bool spin_trylock_wo_note(FAR volatile spinlock_t *lock);
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __SP_UNLOCK_FUNCTION
|
||||
void spin_unlock(FAR volatile spinlock_t *lock);
|
||||
static inline_function void spin_unlock(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
# ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we are unlocking the spinlock */
|
||||
|
||||
sched_note_spinlock_unlock(lock);
|
||||
# endif
|
||||
|
||||
SP_DMB();
|
||||
# ifdef CONFIG_TICKET_SPINLOCK
|
||||
atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.owner, 1);
|
||||
# else
|
||||
*lock = SP_UNLOCKED;
|
||||
# endif
|
||||
SP_DSB();
|
||||
SP_SEV();
|
||||
}
|
||||
#else
|
||||
# define spin_unlock(l) do { *(l) = SP_UNLOCKED; } while (0)
|
||||
#endif
|
||||
@ -321,7 +497,18 @@ void spin_unlock(FAR volatile spinlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void spin_unlock_wo_note(FAR volatile spinlock_t *lock);
|
||||
static inline_function void
|
||||
spin_unlock_wo_note(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
SP_DMB();
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.owner, 1);
|
||||
#else
|
||||
*lock = SP_UNLOCKED;
|
||||
#endif
|
||||
SP_DSB();
|
||||
SP_SEV();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_is_locked
|
||||
@ -502,7 +689,26 @@ void spin_unlock_irqrestore_wo_note(FAR spinlock_t *lock, irqstate_t flags);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void read_lock(FAR volatile rwlock_t *lock);
|
||||
static inline_function void read_lock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int old = atomic_load((FAR atomic_int *)lock);
|
||||
if (old <= RW_SP_WRITE_LOCKED)
|
||||
{
|
||||
DEBUGASSERT(old == RW_SP_WRITE_LOCKED);
|
||||
SP_DSB();
|
||||
SP_WFE();
|
||||
}
|
||||
else if(atomic_compare_exchange_strong((FAR atomic_int *)lock,
|
||||
&old, old + 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: read_trylock
|
||||
@ -528,7 +734,26 @@ void read_lock(FAR volatile rwlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool read_trylock(FAR volatile rwlock_t *lock);
|
||||
static inline_function bool read_trylock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int old = atomic_load((FAR atomic_int *)lock);
|
||||
if (old <= RW_SP_WRITE_LOCKED)
|
||||
{
|
||||
DEBUGASSERT(old == RW_SP_WRITE_LOCKED);
|
||||
return false;
|
||||
}
|
||||
else if (atomic_compare_exchange_strong((FAR atomic_int *)lock,
|
||||
&old, old + 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: read_unlock
|
||||
@ -547,7 +772,15 @@ bool read_trylock(FAR volatile rwlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void read_unlock(FAR volatile rwlock_t *lock);
|
||||
static inline_function void read_unlock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
DEBUGASSERT(atomic_load((FAR atomic_int *)lock) >= RW_SP_READ_LOCKED);
|
||||
|
||||
SP_DMB();
|
||||
atomic_fetch_sub((FAR atomic_int *)lock, 1);
|
||||
SP_DSB();
|
||||
SP_SEV();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: write_lock
|
||||
@ -574,7 +807,19 @@ void read_unlock(FAR volatile rwlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void write_lock(FAR volatile rwlock_t *lock);
|
||||
static inline_function void write_lock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
int zero = RW_SP_UNLOCKED;
|
||||
|
||||
while (!atomic_compare_exchange_strong((FAR atomic_int *)lock,
|
||||
&zero, RW_SP_WRITE_LOCKED))
|
||||
{
|
||||
SP_DSB();
|
||||
SP_WFE();
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: write_trylock
|
||||
@ -601,7 +846,20 @@ void write_lock(FAR volatile rwlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool write_trylock(FAR volatile rwlock_t *lock);
|
||||
static inline_function bool write_trylock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
int zero = RW_SP_UNLOCKED;
|
||||
|
||||
if (atomic_compare_exchange_strong((FAR atomic_int *)lock,
|
||||
&zero, RW_SP_WRITE_LOCKED))
|
||||
{
|
||||
SP_DMB();
|
||||
return true;
|
||||
}
|
||||
|
||||
SP_DSB();
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: write_unlock
|
||||
@ -620,7 +878,17 @@ bool write_trylock(FAR volatile rwlock_t *lock);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void write_unlock(FAR volatile rwlock_t *lock);
|
||||
static inline_function void write_unlock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
/* Ensure this cpu already get write lock */
|
||||
|
||||
DEBUGASSERT(atomic_load((FAR atomic_int *)lock) == RW_SP_WRITE_LOCKED);
|
||||
|
||||
SP_DMB();
|
||||
atomic_store((FAR atomic_int *)lock, RW_SP_UNLOCKED);
|
||||
SP_DSB();
|
||||
SP_SEV();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: read_lock_irqsave
|
||||
@ -767,6 +1035,7 @@ void write_unlock_irqrestore(FAR rwlock_t *lock, irqstate_t flags);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_RW_SPINLOCK */
|
||||
#endif /* CONFIG_HAVE_INLINE_SPINLOCK */
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/sched.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_BINFMT_LOADABLE
|
||||
# include <nuttx/binfmt/binfmt.h>
|
||||
|
@ -117,7 +117,7 @@ volatile uint8_t g_cpu_nestcount[CONFIG_SMP_NCPUS];
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static bool irq_waitlock(int cpu)
|
||||
static inline_function bool irq_waitlock(int cpu)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
FAR struct tcb_s *tcb = current_task(cpu);
|
||||
|
@ -36,12 +36,4 @@ if(CONFIG_PRIORITY_INHERITANCE)
|
||||
list(APPEND CSRCS sem_initialize.c sem_holder.c sem_setprotocol.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SPINLOCK)
|
||||
list(APPEND CSRCS spinlock.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_TICKET_SPINLOCK)
|
||||
list(APPEND CSRCS spinlock.c)
|
||||
endif()
|
||||
|
||||
target_sources(sched PRIVATE ${CSRCS})
|
||||
|
@ -28,10 +28,6 @@ ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
|
||||
CSRCS += sem_initialize.c sem_holder.c sem_setprotocol.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SPINLOCK),y)
|
||||
CSRCS += spinlock.c
|
||||
endif
|
||||
|
||||
# Include semaphore build support
|
||||
|
||||
DEPPATH += --dep-path semaphore
|
||||
|
@ -1,560 +0,0 @@
|
||||
/****************************************************************************
|
||||
* sched/semaphore/spinlock.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdatomic.h>
|
||||
#include <sched.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/sched_note.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
#if defined(CONFIG_TICKET_SPINLOCK) || defined(CONFIG_RW_SPINLOCK)
|
||||
# include <stdatomic.h>
|
||||
#endif
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
||||
#if defined(CONFIG_SPINLOCK) || defined(CONFIG_TICKET_SPINLOCK)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_lock
|
||||
*
|
||||
* Description:
|
||||
* If this CPU does not already hold the spinlock, then loop until the
|
||||
* spinlock is successfully locked.
|
||||
*
|
||||
* This implementation is non-reentrant and is prone to deadlocks in
|
||||
* the case that any logic on the same CPU attempts to take the lock
|
||||
* more than once.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to lock.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. When the function returns, the spinlock was successfully locked
|
||||
* by this CPU.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void spin_lock(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we are waiting for a spinlock */
|
||||
|
||||
sched_note_spinlock(this_task(), lock, NOTE_SPINLOCK_LOCK);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
unsigned short ticket =
|
||||
atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.next, 1);
|
||||
while (atomic_load((FAR atomic_ushort *)&lock->tickets.owner) != ticket)
|
||||
#else /* CONFIG_SPINLOCK */
|
||||
while (up_testset(lock) == SP_LOCKED)
|
||||
#endif
|
||||
{
|
||||
SP_DSB();
|
||||
SP_WFE();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we have the spinlock */
|
||||
|
||||
sched_note_spinlock(this_task(), lock, NOTE_SPINLOCK_LOCKED);
|
||||
#endif
|
||||
SP_DMB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_lock_wo_note
|
||||
*
|
||||
* Description:
|
||||
* If this CPU does not already hold the spinlock, then loop until the
|
||||
* spinlock is successfully locked.
|
||||
*
|
||||
* This implementation is the same as the above spin_lock() except that
|
||||
* it does not perform instrumentation logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to lock.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. When the function returns, the spinlock was successfully locked
|
||||
* by this CPU.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void spin_lock_wo_note(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
unsigned short ticket =
|
||||
atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.next, 1);
|
||||
while (atomic_load((FAR atomic_ushort *)&lock->tickets.owner) != ticket)
|
||||
#else /* CONFIG_TICKET_SPINLOCK */
|
||||
while (up_testset(lock) == SP_LOCKED)
|
||||
#endif
|
||||
{
|
||||
SP_DSB();
|
||||
SP_WFE();
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_trylock
|
||||
*
|
||||
* Description:
|
||||
* Try once to lock the spinlock. Do not wait if the spinlock is already
|
||||
* locked.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to lock.
|
||||
*
|
||||
* Returned Value:
|
||||
* false - Failure, the spinlock was already locked
|
||||
* true - Success, the spinlock was successfully locked
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool spin_trylock(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we are waiting for a spinlock */
|
||||
|
||||
sched_note_spinlock(this_task(), lock, NOTE_SPINLOCK_LOCK);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
unsigned short ticket =
|
||||
atomic_load((FAR atomic_ushort *)&lock->tickets.next);
|
||||
|
||||
spinlock_t old =
|
||||
{
|
||||
{
|
||||
ticket, ticket
|
||||
}
|
||||
};
|
||||
|
||||
spinlock_t new =
|
||||
{
|
||||
{
|
||||
ticket, ticket + 1
|
||||
}
|
||||
};
|
||||
|
||||
if (!atomic_compare_exchange_strong((FAR atomic_uint *)&lock->value,
|
||||
&old.value, new.value))
|
||||
#else /* CONFIG_TICKET_SPINLOCK */
|
||||
if (up_testset(lock) == SP_LOCKED)
|
||||
#endif /* CONFIG_TICKET_SPINLOCK */
|
||||
{
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we abort for a spinlock */
|
||||
|
||||
sched_note_spinlock(this_task(), lock, NOTE_SPINLOCK_ABORT);
|
||||
#endif
|
||||
SP_DSB();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we have the spinlock */
|
||||
|
||||
sched_note_spinlock(this_task(), lock, NOTE_SPINLOCK_LOCKED);
|
||||
#endif
|
||||
SP_DMB();
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_trylock_wo_note
|
||||
*
|
||||
* Description:
|
||||
* Try once to lock the spinlock. Do not wait if the spinlock is already
|
||||
* locked.
|
||||
*
|
||||
* This implementation is the same as the above spin_trylock() except that
|
||||
* it does not perform instrumentation logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to lock.
|
||||
*
|
||||
* Returned Value:
|
||||
* false - Failure, the spinlock was already locked
|
||||
* true - Success, the spinlock was successfully locked
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool spin_trylock_wo_note(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
unsigned short ticket =
|
||||
atomic_load((FAR atomic_ushort *)&lock->tickets.next);
|
||||
|
||||
spinlock_t old =
|
||||
{
|
||||
{
|
||||
ticket, ticket
|
||||
}
|
||||
};
|
||||
|
||||
spinlock_t new =
|
||||
{
|
||||
{
|
||||
ticket, ticket + 1
|
||||
}
|
||||
};
|
||||
|
||||
if (!atomic_compare_exchange_strong((FAR atomic_uint *)&lock->value,
|
||||
&old.value, new.value))
|
||||
#else /* CONFIG_TICKET_SPINLOCK */
|
||||
if (up_testset(lock) == SP_LOCKED)
|
||||
#endif /* CONFIG_TICKET_SPINLOCK */
|
||||
{
|
||||
SP_DSB();
|
||||
return false;
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_unlock
|
||||
*
|
||||
* Description:
|
||||
* Release one count on a non-reentrant spinlock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to unlock.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __SP_UNLOCK_FUNCTION
|
||||
void spin_unlock(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||
/* Notify that we are unlocking the spinlock */
|
||||
|
||||
sched_note_spinlock(this_task(), lock, NOTE_SPINLOCK_UNLOCK);
|
||||
#endif
|
||||
|
||||
SP_DMB();
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.owner, 1);
|
||||
#else
|
||||
*lock = SP_UNLOCKED;
|
||||
#endif
|
||||
SP_DSB();
|
||||
SP_SEV();
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: spin_unlock_wo_note
|
||||
*
|
||||
* Description:
|
||||
* Release one count on a non-reentrant spinlock.
|
||||
*
|
||||
* This implementation is the same as the above spin_unlock() except that
|
||||
* it does not perform instrumentation logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to unlock.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void spin_unlock_wo_note(FAR volatile spinlock_t *lock)
|
||||
{
|
||||
SP_DMB();
|
||||
#ifdef CONFIG_TICKET_SPINLOCK
|
||||
atomic_fetch_add((FAR atomic_ushort *)&lock->tickets.owner, 1);
|
||||
#else
|
||||
*lock = SP_UNLOCKED;
|
||||
#endif
|
||||
SP_DSB();
|
||||
SP_SEV();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RW_SPINLOCK
|
||||
|
||||
/****************************************************************************
|
||||
* Name: read_lock
|
||||
*
|
||||
* Description:
|
||||
* If this task does not already hold the spinlock, then loop until the
|
||||
* spinlock is successfully locked.
|
||||
*
|
||||
* This implementation is non-reentrant and set a bit of lock.
|
||||
*
|
||||
* The priority of reader is higher than writter if a reader hold the
|
||||
* lock, a new reader can get its lock but writer can't get this lock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to lock.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. When the function returns, the spinlock was successfully locked
|
||||
* by this CPU.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void read_lock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int old = atomic_load((FAR atomic_int *)lock);
|
||||
if (old <= RW_SP_WRITE_LOCKED)
|
||||
{
|
||||
DEBUGASSERT(old == RW_SP_WRITE_LOCKED);
|
||||
SP_DSB();
|
||||
SP_WFE();
|
||||
}
|
||||
else if(atomic_compare_exchange_strong((FAR atomic_int *)lock,
|
||||
&old, old + 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: read_trylock
|
||||
*
|
||||
* Description:
|
||||
* If this task does not already hold the spinlock, then try to get the
|
||||
* lock.
|
||||
*
|
||||
* This implementation is non-reentrant and set a bit of lock.
|
||||
*
|
||||
* The priority of reader is higher than writter if a reader hold the
|
||||
* lock, a new reader can get its lock but writer can't get this lock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to lock.
|
||||
*
|
||||
* Returned Value:
|
||||
* false - Failure, the spinlock was already locked
|
||||
* true - Success, the spinlock was successfully locked
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool read_trylock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int old = atomic_load((FAR atomic_int *)lock);
|
||||
if (old <= RW_SP_WRITE_LOCKED)
|
||||
{
|
||||
DEBUGASSERT(old == RW_SP_WRITE_LOCKED);
|
||||
return false;
|
||||
}
|
||||
else if (atomic_compare_exchange_strong((FAR atomic_int *)lock,
|
||||
&old, old + 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: read_unlock
|
||||
*
|
||||
* Description:
|
||||
* Release a bit on a non-reentrant spinlock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to unlock.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void read_unlock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
DEBUGASSERT(atomic_load((FAR atomic_int *)lock) >= RW_SP_READ_LOCKED);
|
||||
|
||||
SP_DMB();
|
||||
atomic_fetch_sub((FAR atomic_int *)lock, 1);
|
||||
SP_DSB();
|
||||
SP_SEV();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: write_lock
|
||||
*
|
||||
* Description:
|
||||
* If this task does not already hold the spinlock, then loop until the
|
||||
* spinlock is successfully locked.
|
||||
*
|
||||
* This implementation is non-reentrant and set all bit on lock to avoid
|
||||
* readers and writers.
|
||||
*
|
||||
* The priority of reader is higher than writter if a reader hold the
|
||||
* lock, a new reader can get its lock but writer can't get this lock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to lock.
|
||||
*
|
||||
* Returned Value:
|
||||
* None. When the function returns, the spinlock was successfully locked
|
||||
* by this CPU.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void write_lock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
int zero = RW_SP_UNLOCKED;
|
||||
|
||||
while (!atomic_compare_exchange_strong((FAR atomic_int *)lock,
|
||||
&zero, RW_SP_WRITE_LOCKED))
|
||||
{
|
||||
SP_DSB();
|
||||
SP_WFE();
|
||||
}
|
||||
|
||||
SP_DMB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: write_trylock
|
||||
*
|
||||
* Description:
|
||||
* If this task does not already hold the spinlock, then loop until the
|
||||
* spinlock is successfully locked.
|
||||
*
|
||||
* This implementation is non-reentrant and set all bit on lock to avoid
|
||||
* readers and writers.
|
||||
*
|
||||
* The priority of reader is higher than writter if a reader hold the
|
||||
* lock, a new reader can get its lock but writer can't get this lock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to lock.
|
||||
*
|
||||
* Returned Value:
|
||||
* false - Failure, the spinlock was already locked
|
||||
* true - Success, the spinlock was successfully locked
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool write_trylock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
int zero = RW_SP_UNLOCKED;
|
||||
|
||||
if (atomic_compare_exchange_strong((FAR atomic_int *)lock,
|
||||
&zero, RW_SP_WRITE_LOCKED))
|
||||
{
|
||||
SP_DMB();
|
||||
return true;
|
||||
}
|
||||
|
||||
SP_DSB();
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: write_unlock
|
||||
*
|
||||
* Description:
|
||||
* Release write lock on a non-reentrant spinlock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lock - A reference to the spinlock object to unlock.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
* Assumptions:
|
||||
* Not running at the interrupt level.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void write_unlock(FAR volatile rwlock_t *lock)
|
||||
{
|
||||
/* Ensure this cpu already get write lock */
|
||||
|
||||
DEBUGASSERT(atomic_load((FAR atomic_int *)lock) == RW_SP_WRITE_LOCKED);
|
||||
|
||||
SP_DMB();
|
||||
atomic_store((FAR atomic_int *)lock, RW_SP_UNLOCKED);
|
||||
SP_DSB();
|
||||
SP_SEV();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RW_SPINLOCK */
|
||||
#endif /* CONFIG_SPINLOCK */
|
@ -23,6 +23,8 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/spinlock.h>
|
||||
#include "signal/signal.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user