sched_note: Add spinlock instrumentation; In SMP configurations, select to log only notes from certain CPUs
This commit is contained in:
parent
d65be718c2
commit
00215fbc98
@ -50,6 +50,22 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
#ifdef CONFIG_SCHED_INSTRUMENTATION
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Provide defaults for some configuration settings (could be undefined with
|
||||||
|
* old configuration files)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_CPUSET
|
||||||
|
# define CONFIG_SCHED_INSTRUMENTATION_CPUSET 0xffff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_NOTE_BUFSIZE
|
||||||
|
# define CONFIG_SCHED_NOTE_BUFSIZE 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -81,6 +97,13 @@ enum note_type_e
|
|||||||
NOTE_CSECTION_ENTER,
|
NOTE_CSECTION_ENTER,
|
||||||
NOTE_CSECTION_LEAVE
|
NOTE_CSECTION_LEAVE
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
,
|
||||||
|
NOTE_SPINLOCK_LOCK,
|
||||||
|
NOTE_SPINLOCK_LOCKED,
|
||||||
|
NOTE_SPINLOCK_UNLOCK,
|
||||||
|
NOTE_SPINLOCK_ABORT
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure provides the common header of each note */
|
/* This structure provides the common header of each note */
|
||||||
@ -182,6 +205,17 @@ struct note_csection_s
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_SCHED_INSTRUMENTATION_CSECTION */
|
#endif /* CONFIG_SCHED_INSTRUMENTATION_CSECTION */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* This is the specific form of the NOTE_SPINLOCK_LOCK/LOCKED/UNLOCK/ABORT note */
|
||||||
|
|
||||||
|
struct note_spinlock_s
|
||||||
|
{
|
||||||
|
struct note_common_s nsp_cmn; /* Common note parameters */
|
||||||
|
FAR void *nsp_spinlock; /* Address of spinlock */
|
||||||
|
uint8_t nsp_value; /* Value of spinlock */
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS */
|
||||||
#endif /* CONFIG_SCHED_INSTRUMENTATION_BUFFER */
|
#endif /* CONFIG_SCHED_INSTRUMENTATION_BUFFER */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -237,6 +271,18 @@ void sched_note_csection(FAR struct tcb_s *tcb, bool enter);
|
|||||||
# define sched_note_csection(t,e)
|
# define sched_note_csection(t,e)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
void sched_note_spinlock(FAR struct tcb_s *tcb, FAR volatile void *spinlock);
|
||||||
|
void sched_note_spinlocked(FAR struct tcb_s *tcb, FAR volatile void *spinlock);
|
||||||
|
void sched_note_spinunlock(FAR struct tcb_s *tcb, FAR volatile void *spinlock);
|
||||||
|
void sched_note_spinabort(FAR struct tcb_s *tcb, FAR volatile void *spinlock);
|
||||||
|
#else
|
||||||
|
# define sched_note_spinlock(t,s)
|
||||||
|
# define sched_note_spinlocked(t,s)
|
||||||
|
# define sched_note_spinunlock(t,s)
|
||||||
|
# define sched_note_spinabort(t,s)
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: sched_note_get
|
* Name: sched_note_get
|
||||||
*
|
*
|
||||||
@ -311,6 +357,10 @@ int note_register(void);
|
|||||||
# define sched_note_cpu_resumed(t)
|
# define sched_note_cpu_resumed(t)
|
||||||
# define sched_note_premption(t,l)
|
# define sched_note_premption(t,l)
|
||||||
# define sched_note_csection(t,e)
|
# define sched_note_csection(t,e)
|
||||||
|
# define sched_note_spinlock(t,s)
|
||||||
|
# define sched_note_spinlocked(t,s)
|
||||||
|
# define sched_note_spinunlock(t,s)
|
||||||
|
# define sched_note_spinabort(t,s)
|
||||||
|
|
||||||
#endif /* CONFIG_SCHED_INSTRUMENTATION */
|
#endif /* CONFIG_SCHED_INSTRUMENTATION */
|
||||||
#endif /* __INCLUDE_NUTTX_SCHED_NOTE_H */
|
#endif /* __INCLUDE_NUTTX_SCHED_NOTE_H */
|
||||||
|
@ -80,6 +80,10 @@
|
|||||||
# define SP_DSB()
|
# define SP_DSB()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS) && !defined(__SP_UNLOCK_FUNCTION)
|
||||||
|
# define __SP_UNLOCK_FUNCTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If the target CPU supports a data cache then it may be necessary to
|
/* If the target CPU supports a data cache then it may be necessary to
|
||||||
* manage spinlocks in a special way, perhaps linking them all into a
|
* manage spinlocks in a special way, perhaps linking them all into a
|
||||||
* special non-cacheable memory region.
|
* special non-cacheable memory region.
|
||||||
|
@ -678,6 +678,13 @@ config SCHED_INSTRUMENTATION
|
|||||||
|
|
||||||
if SCHED_INSTRUMENTATION
|
if SCHED_INSTRUMENTATION
|
||||||
|
|
||||||
|
config SCHED_INSTRUMENTATION_CPUSET
|
||||||
|
hex "CPU bit set"
|
||||||
|
default 0xffff
|
||||||
|
depends on SMP
|
||||||
|
---help---
|
||||||
|
Monitor only CPUs in the bitset. Bit 0=CPU0, Bit1=CPU1, etc.
|
||||||
|
|
||||||
config SCHED_INSTRUMENTATION_PREEMPTION
|
config SCHED_INSTRUMENTATION_PREEMPTION
|
||||||
bool "Preemption monitor hooks"
|
bool "Preemption monitor hooks"
|
||||||
default n
|
default n
|
||||||
@ -687,10 +694,15 @@ config SCHED_INSTRUMENTATION_PREEMPTION
|
|||||||
|
|
||||||
void sched_note_premption(FAR struct tcb_s *tcb, bool state);
|
void sched_note_premption(FAR struct tcb_s *tcb, bool state);
|
||||||
|
|
||||||
|
config SCHED_INSTRUMENTATION_FAUXPAS
|
||||||
|
bool
|
||||||
|
default y if !EXPERIMENTAL && SCHED_INSTRUMENTATION_BUFFER
|
||||||
|
default n if EXPERIMENTAL || !SCHED_INSTRUMENTATION_BUFFER
|
||||||
|
|
||||||
config SCHED_INSTRUMENTATION_CSECTION
|
config SCHED_INSTRUMENTATION_CSECTION
|
||||||
bool "Critical section monitor hooks"
|
bool "Critical section monitor hooks"
|
||||||
default n
|
default n
|
||||||
depends on EXPERIMENTAL || !SCHED_INSTRUMENTATION_BUFFER
|
depends on !SCHED_INSTRUMENTATION_FAUXPAS
|
||||||
---help---
|
---help---
|
||||||
Enables additional hooks for entry and exit from critical sections.
|
Enables additional hooks for entry and exit from critical sections.
|
||||||
Interrupts are disabled while within a critical section. Board-
|
Interrupts are disabled while within a critical section. Board-
|
||||||
@ -706,6 +718,27 @@ config SCHED_INSTRUMENTATION_CSECTION
|
|||||||
added from the note buffer in order to remove one entry. Not
|
added from the note buffer in order to remove one entry. Not
|
||||||
very useful in its current state!
|
very useful in its current state!
|
||||||
|
|
||||||
|
config SCHED_INSTRUMENTATION_SPINLOCK
|
||||||
|
bool "Spinlock monitor hooks"
|
||||||
|
default n
|
||||||
|
depends on SPINLOCK && (!SMP || !SCHED_INSTRUMENTATION_FAUXPAS)
|
||||||
|
---help---
|
||||||
|
Enables additional hooks for spinlock state. Board-specific logic
|
||||||
|
must provide this additional logic.
|
||||||
|
|
||||||
|
void sched_note_spinlock(FAR struct tcb_s *tcb, bool state);
|
||||||
|
void sched_note_spinlocked(FAR struct tcb_s *tcb, bool state);
|
||||||
|
void sched_note_spinunlock(FAR struct tcb_s *tcb, bool state);
|
||||||
|
void sched_note_spinabort(FAR struct tcb_s *tcb, bool state);
|
||||||
|
|
||||||
|
NOTE: This option is marked EXPERIMENTAL because there is a logical
|
||||||
|
error in the design when this feature is used with
|
||||||
|
CONFIG_SCHED_INSTRUMENTATION_BUFFER. That error is that
|
||||||
|
sched_note_get() calls enter_ and leave_critical_section which use
|
||||||
|
spinlocks in SMP mode. That means that each call to sched_note_get()
|
||||||
|
causes several additional entries to be added from the note buffer in
|
||||||
|
order to remove one entry. Not very useful in its current state!
|
||||||
|
|
||||||
config SCHED_INSTRUMENTATION_BUFFER
|
config SCHED_INSTRUMENTATION_BUFFER
|
||||||
bool "Buffer instrumentation data in memory"
|
bool "Buffer instrumentation data in memory"
|
||||||
default n
|
default n
|
||||||
|
@ -128,6 +128,14 @@ static uint8_t g_cpu_nestcount[CONFIG_SMP_NCPUS];
|
|||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static inline bool irq_waitlock(int cpu)
|
static inline bool irq_waitlock(int cpu)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
FAR struct tcb_s *tcb = this_task();
|
||||||
|
|
||||||
|
/* Notify that we are waiting for a spinlock */
|
||||||
|
|
||||||
|
sched_note_spinlock(tcb, &g_cpu_irqlock);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Duplicate the spin_lock() logic from spinlock.c, but adding the check
|
/* Duplicate the spin_lock() logic from spinlock.c, but adding the check
|
||||||
* for the deadlock condition.
|
* for the deadlock condition.
|
||||||
*/
|
*/
|
||||||
@ -142,6 +150,12 @@ static inline bool irq_waitlock(int cpu)
|
|||||||
* Abort the wait and return false.
|
* Abort the wait and return false.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we are waiting for a spinlock */
|
||||||
|
|
||||||
|
sched_note_spinabort(tcb, &g_cpu_irqlock);
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +164,12 @@ static inline bool irq_waitlock(int cpu)
|
|||||||
|
|
||||||
/* We have g_cpu_irqlock! */
|
/* We have g_cpu_irqlock! */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we have the spinlock */
|
||||||
|
|
||||||
|
sched_note_spinlocked(tcb, &g_cpu_irqlock);
|
||||||
|
#endif
|
||||||
|
|
||||||
SP_DMB();
|
SP_DMB();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,11 @@
|
|||||||
|
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
#include <nuttx/clock.h>
|
#include <nuttx/clock.h>
|
||||||
|
#include <nuttx/spinlock.h>
|
||||||
#include <nuttx/sched_note.h>
|
#include <nuttx/sched_note.h>
|
||||||
|
|
||||||
|
#include "sched/sched.h"
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_INSTRUMENTATION_BUFFER
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_BUFFER
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -122,8 +125,10 @@ static inline unsigned int note_next(unsigned int ndx, unsigned int offset)
|
|||||||
* Fill in some of the common fields in the note structure.
|
* Fill in some of the common fields in the note structure.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* tcb - The TCB containing the information
|
* tcb - The TCB containing the information
|
||||||
* note - The common note structure to use
|
* note - The common note structure to use
|
||||||
|
* length - The total lengthof the note structure
|
||||||
|
* type - The type of the note
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None
|
* None
|
||||||
@ -154,6 +159,39 @@ static void note_common(FAR struct tcb_s *tcb, FAR struct note_common_s *note,
|
|||||||
note->nc_systime[3] = (uint8_t)((systime >> 24) & 0xff);
|
note->nc_systime[3] = (uint8_t)((systime >> 24) & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: note_spincommon
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Common logic for NOTE_SPINLOCK, NOTE_SPINLOCKED, and NOTE_SPINUNLOCK
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* tcb - The TCB containing the information
|
||||||
|
* note - The common note structure to use
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
void note_spincommon(FAR struct tcb_s *tcb, FAR volatile spinlock_t *spinlock,
|
||||||
|
int type)
|
||||||
|
{
|
||||||
|
struct note_spinlock_s note;
|
||||||
|
|
||||||
|
/* Format the note */
|
||||||
|
|
||||||
|
note_common(tcb, ¬e.nsp_cmn, sizeof(struct note_spinlock_s), type);
|
||||||
|
note.nsp_spinlock = (FAR void *)spinlock;
|
||||||
|
note.nsp_value = (uint8_t)*spinlock;
|
||||||
|
|
||||||
|
/* Add the note to circular buffer */
|
||||||
|
|
||||||
|
note_add((FAR const uint8_t *)¬e, sizeof(struct note_spinlock_s));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: note_length
|
* Name: note_length
|
||||||
*
|
*
|
||||||
@ -244,6 +282,17 @@ static void note_add(FAR const uint8_t *note, uint8_t notelen)
|
|||||||
unsigned int head;
|
unsigned int head;
|
||||||
unsigned int next;
|
unsigned int next;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
/* Ignore notes that are not in the set of monitored CPUs */
|
||||||
|
|
||||||
|
if ((CONFIG_SCHED_INSTRUMENTATION_CPUSET & (1 << this_cpu())) == 0)
|
||||||
|
{
|
||||||
|
/* Not in the set of monitored CPUs. Do not log the note. */
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Get the index to the head of the circular buffer */
|
/* Get the index to the head of the circular buffer */
|
||||||
|
|
||||||
DEBUGASSERT(note != NULL && notelen < CONFIG_SCHED_NOTE_BUFSIZE);
|
DEBUGASSERT(note != NULL && notelen < CONFIG_SCHED_NOTE_BUFSIZE);
|
||||||
@ -463,6 +512,27 @@ void sched_note_csection(FAR struct tcb_s *tcb, bool enter)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
void sched_note_spinlock(FAR struct tcb_s *tcb, FAR volatile void *spinlock)
|
||||||
|
{
|
||||||
|
note_spincommon(tcb, spinlock, NOTE_SPINLOCK_LOCK)
|
||||||
|
}
|
||||||
|
|
||||||
|
void sched_note_spinlocked(FAR struct tcb_s *tcb, FAR volatile void *spinlock);
|
||||||
|
{
|
||||||
|
note_spincommon(tcb, spinlock, NOTE_SPINLOCK_LOCKED)
|
||||||
|
}
|
||||||
|
|
||||||
|
void sched_note_spinunlock(FAR struct tcb_s *tcb, FAR volatile void *spinlock);
|
||||||
|
{
|
||||||
|
note_spincommon(tcb, spinlock, NOTE_SPINLOCK_UNLOCK)
|
||||||
|
}
|
||||||
|
void sched_note_spinabort(FAR struct tcb_s *tcb, FAR volatile void *spinlock);
|
||||||
|
{
|
||||||
|
note_spincommon(tcb, spinlock, NOTE_SPINLOCK_ABORT)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: sched_note_get
|
* Name: sched_note_get
|
||||||
*
|
*
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <nuttx/spinlock.h>
|
#include <nuttx/spinlock.h>
|
||||||
|
#include <nuttx/sched_note.h>
|
||||||
#include <arch/irq.h>
|
#include <arch/irq.h>
|
||||||
|
|
||||||
#include "sched/sched.h"
|
#include "sched/sched.h"
|
||||||
@ -119,11 +120,22 @@ void spin_initializer(FAR struct spinlock_s *lock)
|
|||||||
|
|
||||||
void spin_lock(FAR volatile spinlock_t *lock)
|
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);
|
||||||
|
#endif
|
||||||
|
|
||||||
while (up_testset(lock) == SP_LOCKED)
|
while (up_testset(lock) == SP_LOCKED)
|
||||||
{
|
{
|
||||||
SP_DSB();
|
SP_DSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we have the spinlock */
|
||||||
|
|
||||||
|
sched_note_spinlocked(this_task(), lock);
|
||||||
|
#endif
|
||||||
SP_DMB();
|
SP_DMB();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +159,12 @@ void spin_lock(FAR volatile spinlock_t *lock)
|
|||||||
#ifdef __SP_UNLOCK_FUNCTION
|
#ifdef __SP_UNLOCK_FUNCTION
|
||||||
void spin_unlock(FAR volatile spinlock_t *lock)
|
void spin_unlock(FAR volatile spinlock_t *lock)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we are unlocking the spinlock */
|
||||||
|
|
||||||
|
sched_note_spinunlock(this_task(), lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
*lock = SP_UNLOCKED;
|
*lock = SP_UNLOCKED;
|
||||||
SP_DMB();
|
SP_DMB();
|
||||||
}
|
}
|
||||||
@ -208,6 +226,13 @@ void spin_lockr(FAR struct spinlock_s *lock)
|
|||||||
|
|
||||||
# warning Missing logic
|
# warning Missing logic
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we are waiting for a spinlock */
|
||||||
|
|
||||||
|
sched_note_spinlock(this_task(), &lock->sp_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Take the lock. REVISIT: We should set an indication in the TCB
|
/* Take the lock. REVISIT: We should set an indication in the TCB
|
||||||
* that the thread is spinning. This might be useful in determining
|
* that the thread is spinning. This might be useful in determining
|
||||||
* some scheduling actions?
|
* some scheduling actions?
|
||||||
@ -221,6 +246,12 @@ void spin_lockr(FAR struct spinlock_s *lock)
|
|||||||
SP_DSB();
|
SP_DSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we have thespinlock */
|
||||||
|
|
||||||
|
sched_note_spinlocked(this_task(), &lock->sp_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
SP_DMB();
|
SP_DMB();
|
||||||
|
|
||||||
/* Take one count on the lock */
|
/* Take one count on the lock */
|
||||||
@ -233,6 +264,12 @@ void spin_lockr(FAR struct spinlock_s *lock)
|
|||||||
|
|
||||||
#else /* CONFIG_SMP */
|
#else /* CONFIG_SMP */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we are waiting for a spinlock */
|
||||||
|
|
||||||
|
sched_note_spinlock(this_task(), &lock->sp_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Take the lock. REVISIT: We should set an indication in the TCB that
|
/* Take the lock. REVISIT: We should set an indication in the TCB that
|
||||||
* the thread is spinning. This might be useful in determining some
|
* the thread is spinning. This might be useful in determining some
|
||||||
* scheduling actions?
|
* scheduling actions?
|
||||||
@ -244,6 +281,12 @@ void spin_lockr(FAR struct spinlock_s *lock)
|
|||||||
SP_DSB()
|
SP_DSB()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we have thespinlock */
|
||||||
|
|
||||||
|
sched_note_spinlocked(this_task(), &lock->sp_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
SP_DMB();
|
SP_DMB();
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
}
|
}
|
||||||
@ -303,6 +346,11 @@ void spin_unlockr(FAR struct spinlock_s *lock)
|
|||||||
|
|
||||||
if (lock->sp_count <= 1)
|
if (lock->sp_count <= 1)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we are unlocking the spinlock */
|
||||||
|
|
||||||
|
sched_note_spinunlock(this_task(), &lock->sp_lock);
|
||||||
|
#endif
|
||||||
/* The count must decremented to zero */
|
/* The count must decremented to zero */
|
||||||
|
|
||||||
lock->sp_count = 0;
|
lock->sp_count = 0;
|
||||||
@ -318,6 +366,13 @@ void spin_unlockr(FAR struct spinlock_s *lock)
|
|||||||
up_irq_restore(flags);
|
up_irq_restore(flags);
|
||||||
|
|
||||||
#else /* CONFIG_SMP */
|
#else /* CONFIG_SMP */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
/* Notify that we are unlocking the spinlock */
|
||||||
|
|
||||||
|
sched_note_spinunlock(this_task(), &lock->sp_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Just mark the spinlock unlocked */
|
/* Just mark the spinlock unlocked */
|
||||||
|
|
||||||
DEBUGASSERT(lock != NULL && lock->sp_lock == SP_LOCKED);
|
DEBUGASSERT(lock != NULL && lock->sp_lock == SP_LOCKED);
|
||||||
@ -347,15 +402,31 @@ void spin_setbit(FAR volatile cpu_set_t *set, unsigned int cpu,
|
|||||||
FAR volatile spinlock_t *setlock,
|
FAR volatile spinlock_t *setlock,
|
||||||
FAR volatile spinlock_t *orlock)
|
FAR volatile spinlock_t *orlock)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
cpu_set_t prev;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* First, get the 'setlock' spinlock */
|
/* First, get the 'setlock' spinlock */
|
||||||
|
|
||||||
spin_lock(setlock);
|
spin_lock(setlock);
|
||||||
|
|
||||||
/* Then set the bit and mark the 'orlock' as locked */
|
/* Then set the bit and mark the 'orlock' as locked */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
prev = *set;
|
||||||
|
#endif
|
||||||
*set |= (1 << cpu);
|
*set |= (1 << cpu);
|
||||||
*orlock = SP_LOCKED;
|
*orlock = SP_LOCKED;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
if (prev == 0)
|
||||||
|
{
|
||||||
|
/* Notify that we have locked the spinlock */
|
||||||
|
|
||||||
|
sched_note_spinlocked(this_task(), orlock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Release the 'setlock' */
|
/* Release the 'setlock' */
|
||||||
|
|
||||||
spin_unlock(setlock);
|
spin_unlock(setlock);
|
||||||
@ -382,6 +453,10 @@ void spin_clrbit(FAR volatile cpu_set_t *set, unsigned int cpu,
|
|||||||
FAR volatile spinlock_t *setlock,
|
FAR volatile spinlock_t *setlock,
|
||||||
FAR volatile spinlock_t *orlock)
|
FAR volatile spinlock_t *orlock)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
cpu_set_t prev;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* First, get the 'setlock' spinlock */
|
/* First, get the 'setlock' spinlock */
|
||||||
|
|
||||||
spin_lock(setlock);
|
spin_lock(setlock);
|
||||||
@ -390,9 +465,21 @@ void spin_clrbit(FAR volatile cpu_set_t *set, unsigned int cpu,
|
|||||||
* upon the resulting state of the CPU set.
|
* upon the resulting state of the CPU set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
prev = *set;
|
||||||
|
#endif
|
||||||
*set &= ~(1 << cpu);
|
*set &= ~(1 << cpu);
|
||||||
*orlock = (*set != 0) ? SP_LOCKED : SP_UNLOCKED;
|
*orlock = (*set != 0) ? SP_LOCKED : SP_UNLOCKED;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
|
||||||
|
if (prev != 0 && *set == 0)
|
||||||
|
{
|
||||||
|
/* Notify that we have unlocked the spinlock */
|
||||||
|
|
||||||
|
sched_note_spinunlock(this_task(), orlock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Release the 'setlock' */
|
/* Release the 'setlock' */
|
||||||
|
|
||||||
spin_unlock(setlock);
|
spin_unlock(setlock);
|
||||||
|
Loading…
Reference in New Issue
Block a user