Scheduler instrumentation: Fix some associated with monitoring critical sections
This commit is contained in:
parent
adf3c73219
commit
d20db82fcb
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/irq.h
|
||||
*
|
||||
* Copyright (C) 2007-2011, 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2011, 2013, 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -113,7 +113,7 @@ int irq_attach(int irq, xcpt_t isr);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_INSTRUMENTATION_CSECTION)
|
||||
irqstate_t enter_critical_section(void);
|
||||
#else
|
||||
# define enter_critical_section(f) up_irq_save(f)
|
||||
@ -131,7 +131,7 @@ irqstate_t enter_critical_section(void);
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_INSTRUMENTATION_CSECTION)
|
||||
void leave_critical_section(irqstate_t flags);
|
||||
#else
|
||||
# define leave_critical_section(f) up_irq_restore(f)
|
||||
@ -144,4 +144,3 @@ void leave_critical_section(irqstate_t flags);
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_IRQ_H */
|
||||
|
||||
|
@ -627,7 +627,7 @@ config SCHED_INSTRUMENTATION_PREEMPTION
|
||||
config SCHED_INSTRUMENTATION_CSECTION
|
||||
bool "Critical section monitor hooks"
|
||||
default n
|
||||
depends on SMP
|
||||
depends on EXPERIMENTAL
|
||||
---help---
|
||||
Enables additional hooks for entry and exit from critical sections.
|
||||
Interrupts are disabled while within a critical section. Board-
|
||||
@ -635,6 +635,13 @@ config SCHED_INSTRUMENTATION_CSECTION
|
||||
|
||||
void sched_note_csection(FAR struct tcb_s *tcb, bool state);
|
||||
|
||||
NOTE: This option is marked EXPERIMENTAL because there is a logical
|
||||
error in the design. That error is that sched_note_get() calls
|
||||
enter/leave_critical_section. When the buffer note buffer has been
|
||||
filled, each of these calls causes an entry to be removed from the
|
||||
note buffer to make more space. The end result is that every other
|
||||
note is lost when dumping the note buffer. Not very useful!
|
||||
|
||||
config SCHED_INSTRUMENTATION_BUFFER
|
||||
bool "Buffer instrumentation data in memory"
|
||||
default n
|
||||
|
@ -37,6 +37,8 @@ CSRCS += irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c
|
||||
|
||||
ifeq ($(CONFIG_SMP),y)
|
||||
CSRCS += irq_csection.c
|
||||
else ifeq ($(CONFIG_SCHED_INSTRUMENTATION_CSECTION),y)
|
||||
CSRCS += irq_csection.c
|
||||
endif
|
||||
|
||||
# Include irq build support
|
||||
|
@ -48,11 +48,13 @@
|
||||
#include "sched/sched.h"
|
||||
#include "irq/irq.h"
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_INSTRUMENTATION_CSECTION)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* This is the spinlock that enforces critical sections when interrupts are
|
||||
* disabled.
|
||||
*/
|
||||
@ -63,6 +65,7 @@ volatile spinlock_t g_cpu_irqlock = SP_UNLOCKED;
|
||||
|
||||
volatile spinlock_t g_cpu_irqsetlock;
|
||||
volatile cpu_set_t g_cpu_irqset;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -78,6 +81,7 @@ volatile cpu_set_t g_cpu_irqset;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
irqstate_t enter_critical_section(void)
|
||||
{
|
||||
FAR struct tcb_s *rtcb;
|
||||
@ -96,6 +100,8 @@ irqstate_t enter_critical_section(void)
|
||||
/* Do we already have interrupts disabled? */
|
||||
|
||||
rtcb = this_task();
|
||||
DEBUGASSERT(rtcb != NULL);
|
||||
|
||||
if (rtcb->irqcount > 0)
|
||||
{
|
||||
/* Yes... make sure that the spinlock is set and increment the IRQ
|
||||
@ -136,6 +142,26 @@ irqstate_t enter_critical_section(void)
|
||||
|
||||
return up_irq_save();
|
||||
}
|
||||
#else /* defined(CONFIG_SCHED_INSTRUMENTATION_CSECTION) */
|
||||
irqstate_t enter_critical_section(void)
|
||||
{
|
||||
/* Check if we were called from an interrupt handler */
|
||||
|
||||
if (!up_interrupt_context())
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
DEBUGASSERT(rtcb != NULL);
|
||||
|
||||
/* No.. note that we have entered the critical section */
|
||||
|
||||
sched_note_csection(rtcb, true);
|
||||
}
|
||||
|
||||
/* And disable interrupts */
|
||||
|
||||
return up_irq_save();
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: leave_critical_section
|
||||
@ -146,6 +172,7 @@ irqstate_t enter_critical_section(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void leave_critical_section(irqstate_t flags)
|
||||
{
|
||||
/* Do nothing if called from an interrupt handler */
|
||||
@ -153,8 +180,7 @@ void leave_critical_section(irqstate_t flags)
|
||||
if (!up_interrupt_context())
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
|
||||
DEBUGASSERT(rtcb->irqcount > 0);
|
||||
DEBUGASSERT(rtcb != 0 && rtcb->irqcount > 0);
|
||||
|
||||
/* Will we still have interrupts disabled after decrementing the
|
||||
* count?
|
||||
@ -211,5 +237,25 @@ void leave_critical_section(irqstate_t flags)
|
||||
up_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
#else /* defined(CONFIG_SCHED_INSTRUMENTATION_CSECTION) */
|
||||
void leave_critical_section(irqstate_t flags)
|
||||
{
|
||||
/* Check if we were called from an interrupt handler */
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
if (!up_interrupt_context())
|
||||
{
|
||||
FAR struct tcb_s *rtcb = this_task();
|
||||
DEBUGASSERT(rtcb != NULL);
|
||||
|
||||
/* Note that we have left the critical section */
|
||||
|
||||
sched_note_csection(rtcb, false);
|
||||
}
|
||||
|
||||
/* Restore the previous interrupt state. */
|
||||
|
||||
up_irq_restore(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_SMP || CONFIG_SCHED_INSTRUMENTATION_CSECTION*/
|
||||
|
@ -401,8 +401,6 @@ void sched_note_csection(FAR struct tcb_s *tcb, bool enter)
|
||||
note.ncs_count[1] = (uint8_t)((tcb->irqcount >> 8) & 0xff);
|
||||
#endif
|
||||
|
||||
note_systime((FAR struct note_common_s *)¬e);
|
||||
|
||||
/* Add the note to circular buffer */
|
||||
|
||||
note_add((FAR const uint8_t *)¬e, sizeof(struct note_csection_s));
|
||||
@ -450,7 +448,7 @@ ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen)
|
||||
|
||||
/* Get the index to the tail of the circular buffer */
|
||||
|
||||
tail = g_note_info.ni_tail;
|
||||
tail = g_note_info.ni_tail;
|
||||
DEBUGASSERT(tail < CONFIG_SCHED_NOTE_BUFSIZE);
|
||||
|
||||
/* Get the length of the note at the tail index */
|
||||
@ -467,7 +465,7 @@ ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen)
|
||||
|
||||
note_remove();
|
||||
|
||||
/* and return and error */
|
||||
/* and return an error */
|
||||
|
||||
notelen = -EFBIG;
|
||||
goto errout_with_csection;
|
||||
|
Loading…
Reference in New Issue
Block a user