From f7b58e9dfd1e55392cca93486e0d7440b4f9ea7c Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 21 Mar 2016 14:08:31 -0600 Subject: [PATCH] sched/: Move location (and form) of context switch instrumentation. --- include/nuttx/sched.h | 5 +- include/nuttx/sched_note.h | 54 +++++------- sched/Kconfig | 3 +- sched/sched/Make.defs | 4 + sched/sched/sched_addreadytorun.c | 10 --- sched/sched/sched_mergepending.c | 7 -- sched/sched/sched_note.c | 124 ++++++++++++++++++--------- sched/sched/sched_removereadytorun.c | 8 -- sched/sched/sched_resumescheduler.c | 13 ++- sched/sched/sched_suspendscheduler.c | 17 +++- 10 files changed, 140 insertions(+), 105 deletions(-) diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index b4f3d055fa..724be425ca 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -815,7 +815,8 @@ void task_vforkabort(FAR struct task_tcb_s *child, int errcode); * ********************************************************************************/ -#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC) +#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC) || \ + defined(CONFIG_SCHED_INSTRUMENTATION) void sched_resume_scheduler(FAR struct tcb_s *tcb); #else # define sched_resume_scheduler(tcb) @@ -837,7 +838,7 @@ void sched_resume_scheduler(FAR struct tcb_s *tcb); * ********************************************************************************/ -#ifdef CONFIG_SCHED_SPORADIC +#if defined(CONFIG_SCHED_SPORADIC) || defined(CONFIG_SCHED_INSTRUMENTATION) void sched_suspend_scheduler(FAR struct tcb_s *tcb); #else # define sched_suspend_scheduler(tcb) diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h index 39096228b5..7a20e57284 100644 --- a/include/nuttx/sched_note.h +++ b/include/nuttx/sched_note.h @@ -62,7 +62,8 @@ enum note_type_e { NOTE_START = 0, NOTE_STOP, - NOTE_SWITCH + NOTE_SUSPEND, + NOTE_RESUME #ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION , NOTE_PREEMPT_LOCK, @@ -79,21 +80,23 @@ enum note_type_e struct note_common_s { - uint8_t nc_length; /* Length of the note */ - uint8_t nc_type; /* See enum note_type_e */ - uint8_t nc_systime[4]; /* Time when note buffered */ + uint8_t nc_length; /* Length of the note */ + uint8_t nc_type; /* See enum note_type_e */ + uint8_t nc_priority; /* Thread/task priority */ +#ifdef CONFIG_SMP + uint8_t nc_cpu; /* CPU thread/task running on */ +#endif + uint8_t nc_pid[2]; /* ID of the thread/task */ + uint8_t nc_systime[4]; /* Time when note buffered */ }; /* This is the specific form of the NOTE_START note */ struct note_start_s { - uint8_t nst_length; /* Length of the note */ - uint8_t nst_type; /* Must be NOTE_START */ - uint8_t nst_systime[4]; /* Time when note buffered */ - uint8_t nst_pid[2]; /* ID of the new thread/task */ + struct note_common_s nst_cmn; /* Common note parameters */ #if CONFIG_TASK_NAME_SIZE > 0 - char nst_name[1]; /* Start of the name of the thread/task */ + char nst_name[1]; /* Start of the name of the thread/task */ #endif }; @@ -101,21 +104,14 @@ struct note_start_s struct note_stop_s { - uint8_t nsp_length; /* Length of the note */ - uint8_t nsp_type; /* Must be NOTE_STOP */ - uint8_t nsp_systime[4]; /* Time when note buffered */ - uint8_t nsp_pid[2]; /* ID of the thread/task that stopped */ + struct note_common_s nsp_cmn; /* Common note parameters */ }; -/* This is the specific form of the NOTE_SWITCH note */ +/* This is the specific form of the NOTE_SUSPEND/NOTE_RESUME note */ struct note_switch_s { - uint8_t nsw_length; /* Length of the note */ - uint8_t nsw_type; /* Must be NOTE_SWITCH */ - uint8_t nsw_systime[4]; /* Time when note buffered */ - uint8_t nsw_pidout[2]; /* ID of the thread/task that was blocked */ - uint8_t nsw_pidin[2]; /* ID of the thread/task that was started */ + struct note_common_s nsw_cmn; /* Common note parameters */ }; #ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION @@ -123,11 +119,8 @@ struct note_switch_s struct note_preempt_s { - uint8_t npr_length; /* Length of the note */ - uint8_t npr_type; /* Must be NOTE_PREEMPT_LOCK or _UNLOCK */ - uint8_t npr_systime[4]; /* Time when note buffered */ - uint8_t npr_pid[2]; /* ID of the thread/task that change pre-emption */ - uint8_t npr_count[2]; /* Count of nested locks */ + struct note_common_s npr_cmn; /* Common note parameters */ + uint8_t npr_count[2]; /* Count of nested locks */ }; #endif /* CONFIG_SCHED_INSTRUMENTATION_PREEMPTION */ @@ -136,12 +129,9 @@ struct note_preempt_s struct note_csection_s { - uint8_t ncs_length; /* Length of the note */ - uint8_t ncs_type; /* Must be NOTE_CSECTION_ENTER or _LEAVE */ - uint8_t ncs_systime[4]; /* Time when note buffered */ - uint8_t ncs_pid[2]; /* ID of the thread/task that changed critical section */ + struct note_common_s ncs_cmn; /* Common note parameters */ #ifdef CONFIG_SMP - uint8_t ncs_count[2]; /* Count of nested csections */ + uint8_t ncs_count[2]; /* Count of nested csections */ #endif }; #endif /* CONFIG_SCHED_INSTRUMENTATION_CSECTION */ @@ -173,7 +163,8 @@ struct note_csection_s void sched_note_start(FAR struct tcb_s *tcb); void sched_note_stop(FAR struct tcb_s *tcb); -void sched_note_switch(FAR struct tcb_s *fromtcb, FAR struct tcb_s *totcb); +void sched_note_suspend(FAR struct tcb_s *tcb); +void sched_note_resume(FAR struct tcb_s *tcb); #ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION void sched_note_premption(FAR struct tcb_s *tcb, bool locked); @@ -249,7 +240,8 @@ int note_register(void); # define sched_note_start(t) # define sched_note_stop(t) -# define sched_note_switch(t1, t2) +# define sched_note_suspend(t) +# define sched_note_resume(t) # define sched_note_premption(t,l) # define sched_note_csection(t,e) diff --git a/sched/Kconfig b/sched/Kconfig index dc9d7d13d9..6dfbd2a954 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -603,7 +603,8 @@ config SCHED_INSTRUMENTATION void sched_note_start(FAR struct tcb_s *tcb); void sched_note_stop(FAR struct tcb_s *tcb); - void sched_note_switch(FAR struct tcb_s *pFromTcb, FAR struct tcb_s *pToTcb); + void sched_note_suspend(FAR struct tcb_s *tcb); + void sched_note_resume(FAR struct tcb_s *tcb); NOTE: These are internal OS interfaces and are called at at very critical locations in the OS. There is very little that can be diff --git a/sched/sched/Make.defs b/sched/sched/Make.defs index 74ffabe1f3..e97db5f244 100644 --- a/sched/sched/Make.defs +++ b/sched/sched/Make.defs @@ -64,12 +64,16 @@ endif ifeq ($(CONFIG_SCHED_SPORADIC),y) CSRCS += sched_sporadic.c sched_suspendscheduler.c +else ifeq ($(CONFIG_SCHED_INSTRUMENTATION),y) +CSRCS += sched_suspendscheduler.c endif ifneq ($(CONFIG_RR_INTERVAL),0) CSRCS += sched_resumescheduler.c else ifeq ($(CONFIG_SCHED_SPORADIC),y) CSRCS += sched_resumescheduler.c +else ifeq ($(CONFIG_SCHED_INSTRUMENTATION),y) +CSRCS += sched_resumescheduler.c endif ifeq ($(CONFIG_SCHED_CPULOAD),y) diff --git a/sched/sched/sched_addreadytorun.c b/sched/sched/sched_addreadytorun.c index 987c91d486..4299d05106 100644 --- a/sched/sched/sched_addreadytorun.c +++ b/sched/sched/sched_addreadytorun.c @@ -43,8 +43,6 @@ #include #include -#include - #include "irq/irq.h" #include "sched/sched.h" @@ -107,10 +105,6 @@ bool sched_addreadytorun(FAR struct tcb_s *btcb) else if (sched_addprioritized(btcb, (FAR dq_queue_t *)&g_readytorun)) { - /* Inform the instrumentation logic that we are switching tasks */ - - sched_note_switch(rtcb, btcb); - /* The new btcb was added at the head of the ready-to-run list. It * is now the new active task! */ @@ -286,12 +280,8 @@ bool sched_addreadytorun(FAR struct tcb_s *btcb) /* The new btcb was added at the head of the ready-to-run list. It * is now the new active task! - * - * Inform the instrumentation logic that we are switching tasks. */ - sched_note_switch(rtcb, btcb); - /* Assign the CPU and set the running state */ DEBUGASSERT(task_state == TSTATE_TASK_RUNNING); diff --git a/sched/sched/sched_mergepending.c b/sched/sched/sched_mergepending.c index e314e31d69..58b3f071c1 100644 --- a/sched/sched/sched_mergepending.c +++ b/sched/sched/sched_mergepending.c @@ -44,8 +44,6 @@ #include #include -#include - #include "sched/sched.h" /**************************************************************************** @@ -123,11 +121,6 @@ bool sched_mergepending(void) if (!rprev) { /* Special case: Inserting ptcb at the head of the list */ - /* Inform the instrumentation layer that we are switching tasks */ - - sched_note_switch(rtcb, ptcb); - - /* Then insert at the head of the list */ ptcb->flink = rtcb; ptcb->blink = NULL; diff --git a/sched/sched/sched_note.c b/sched/sched/sched_note.c index 83f14a6376..b59e75d713 100644 --- a/sched/sched/sched_note.c +++ b/sched/sched/sched_note.c @@ -67,12 +67,9 @@ struct note_info_s struct note_startalloc_s { - uint8_t nsa_length; - uint8_t nsa_type; - uint8_t nsa_systime[4]; - uint8_t nsa_pid[2]; + struct note_common_s nsa_cmn; /* Common note parameters */ #if CONFIG_TASK_NAME_SIZE > 0 - char nsa_name[CONFIG_TASK_NAME_SIZE + 1]; + char nsa_name[CONFIG_TASK_NAME_SIZE + 1]; #endif }; @@ -266,6 +263,45 @@ static void note_add(FAR const uint8_t *note, uint8_t notelen) g_note_info.ni_head = head; } +/**************************************************************************** + * Name: sched_note_switch + * + * Description: + * Perform core logic for both sched_note_suspend and sched_note_resume + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + * Assumptions: + * We are within a critical section. + * + ****************************************************************************/ + +static void sched_note_switch(FAR struct tcb_s *tcb, uint8_t type) +{ + struct note_switch_s note; + + /* Format the note */ + + note.nsw_cmn.nc_length = sizeof(struct note_switch_s); + note.nsw_cmn.nc_type = type; + note.nsw_cmn.nc_priority = tcb->sched_priority; +#ifdef CONFIG_SMP + note.nsw_cmn.nc_cpu = tcb->cpu; +#endif + note.nsw_cmn.nc_pid[0] = (uint8_t)(tcb->pid & 0xff); + note.nsw_cmn.nc_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); + + note_systime((FAR struct note_common_s *)¬e); + + /* Add the note to circular buffer */ + + note_add((FAR const uint8_t *)¬e, sizeof(struct note_switch_s)); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -312,10 +348,14 @@ void sched_note_start(FAR struct tcb_s *tcb) /* Finish formatting the note */ - note.nsa_length = length; - note.nsa_type = NOTE_START; - note.nsa_pid[0] = (uint8_t)(tcb->pid & 0xff); - note.nsa_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); + note.nsa_cmn.nc_length = length; + note.nsa_cmn.nc_type = NOTE_START; + note.nsa_cmn.nc_priority = tcb->sched_priority; +#ifdef CONFIG_SMP + note.nsa_cmn.nc_cpu = tcb->cpu; +#endif + note.nsa_cmn.nc_pid[0] = (uint8_t)(tcb->pid & 0xff); + note.nsa_cmn.nc_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); note_systime((FAR struct note_common_s *)¬e); @@ -330,10 +370,14 @@ void sched_note_stop(FAR struct tcb_s *tcb) /* Format the note */ - note.nsp_length = sizeof(struct note_stop_s); - note.nsp_type = NOTE_STOP; - note.nsp_pid[0] = (uint8_t)(tcb->pid & 0xff); - note.nsp_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); + note.nsp_cmn.nc_length = sizeof(struct note_stop_s); + note.nsp_cmn.nc_type = NOTE_STOP; + note.nsp_cmn.nc_priority = tcb->sched_priority; +#ifdef CONFIG_SMP + note.nsp_cmn.nc_cpu = tcb->cpu; +#endif + note.nsp_cmn.nc_pid[0] = (uint8_t)(tcb->pid & 0xff); + note.nsp_cmn.nc_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); note_systime((FAR struct note_common_s *)¬e); @@ -342,24 +386,14 @@ void sched_note_stop(FAR struct tcb_s *tcb) note_add((FAR const uint8_t *)¬e, sizeof(struct note_stop_s)); } -void sched_note_switch(FAR struct tcb_s *fromtcb, FAR struct tcb_s *totcb) +void sched_note_suspend(FAR struct tcb_s *tcb) { - struct note_switch_s note; + sched_note_switch(tcb, NOTE_SUSPEND); +} - /* Format the note */ - - note.nsw_length = sizeof(struct note_switch_s); - note.nsw_type = NOTE_SWITCH; - note.nsw_pidout[0] = (uint8_t)(fromtcb->pid & 0xff); - note.nsw_pidout[1] = (uint8_t)((fromtcb->pid >> 8) & 0xff); - note.nsw_pidin[0] = (uint8_t)(totcb->pid & 0xff); - note.nsw_pidin[1] = (uint8_t)((totcb->pid >> 8) & 0xff); - - note_systime((FAR struct note_common_s *)¬e); - - /* Add the note to circular buffer */ - - note_add((FAR const uint8_t *)¬e, sizeof(struct note_switch_s)); +void sched_note_resume(FAR struct tcb_s *tcb) +{ + sched_note_switch(tcb, NOTE_RESUME); } #ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION @@ -369,12 +403,16 @@ void sched_note_premption(FAR struct tcb_s *tcb, bool locked) /* Format the note */ - note.npr_length = sizeof(struct note_preempt_s); - note.npr_type = locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK; - note.npr_pid[0] = (uint8_t)(tcb->pid & 0xff); - note.npr_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); - note.npr_count[0] = (uint8_t)(tcb->lockcount & 0xff); - note.npr_count[1] = (uint8_t)((tcb->lockcount >> 8) & 0xff); + note.npr_cmn.nc_length = sizeof(struct note_preempt_s); + note.npr_cmn.nc_type = locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK; + note.npr_cmn.nc_priority = tcb->sched_priority; +#ifdef CONFIG_SMP + note.npr_cmn.nc_cpu = tcb->cpu; +#endif + note.npr_cmn.nc_pid[0] = (uint8_t)(tcb->pid & 0xff); + note.npr_cmn.nc_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); + note.npr_count[0] = (uint8_t)(tcb->lockcount & 0xff); + note.npr_count[1] = (uint8_t)((tcb->lockcount >> 8) & 0xff); note_systime((FAR struct note_common_s *)¬e); @@ -391,13 +429,17 @@ void sched_note_csection(FAR struct tcb_s *tcb, bool enter) /* Format the note */ - note.ncs_length = sizeof(struct note_preempt_s); - note.ncs_type = enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE; - note.ncs_pid[0] = (uint8_t)(tcb->pid & 0xff); - note.ncs_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); + note.ncs_cmn.nc_length = sizeof(struct note_preempt_s); + note.ncs_cmn.nc_type = enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE; + note.ncs_cmn.nc_priority = tcb->sched_priority; #ifdef CONFIG_SMP - note.ncs_count[0] = (uint8_t)(tcb->irqcount & 0xff); - note.ncs_count[1] = (uint8_t)((tcb->irqcount >> 8) & 0xff); + note.ncs_cmn.nc_cpu = tcb->cpu; +#endif + note.ncs_cmn.nc_pid[0] = (uint8_t)(tcb->pid & 0xff); + note.ncs_cmn.nc_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff); +#ifdef CONFIG_SMP + note.ncs_count[0] = (uint8_t)(tcb->irqcount & 0xff); + note.ncs_count[1] = (uint8_t)((tcb->irqcount >> 8) & 0xff); #endif note_systime((FAR struct note_common_s *)¬e); diff --git a/sched/sched/sched_removereadytorun.c b/sched/sched/sched_removereadytorun.c index 84d3b25c11..78d1c6b6a1 100644 --- a/sched/sched/sched_removereadytorun.c +++ b/sched/sched/sched_removereadytorun.c @@ -43,8 +43,6 @@ #include #include -#include - #include "irq/irq.h" #include "sched/sched.h" @@ -94,9 +92,6 @@ bool sched_removereadytorun(FAR struct tcb_s *rtcb) FAR struct tcb_s *ntcb = (FAR struct tcb_s *)rtcb->flink; DEBUGASSERT(ntcb != NULL); - /* Inform the instrumentation layer that we are switching tasks */ - - sched_note_switch(rtcb, ntcb); ntcb->task_state = TSTATE_TASK_RUNNING; doswitch = true; } @@ -224,9 +219,6 @@ bool sched_removereadytorun(FAR struct tcb_s *rtcb) &g_cpu_irqlock); } - /* Inform the instrumentation layer that we are switching tasks */ - - sched_note_switch(rtcb, ntcb); ntcb->task_state = TSTATE_TASK_RUNNING; /* The task is running but the CPU that it was running on has been diff --git a/sched/sched/sched_resumescheduler.c b/sched/sched/sched_resumescheduler.c index 80856dd283..0c451e1577 100644 --- a/sched/sched/sched_resumescheduler.c +++ b/sched/sched/sched_resumescheduler.c @@ -43,10 +43,12 @@ #include #include +#include #include "sched/sched.h" -#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC) +#if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC) || \ + defined(CONFIG_SCHED_INSTRUMENTATION) /**************************************************************************** * Public Functions @@ -92,6 +94,13 @@ void sched_resume_scheduler(FAR struct tcb_s *tcb) DEBUGVERIFY(sched_sporadic_resume(tcb)); } #endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Inidicate the the task has been resumed */ + + sched_note_resume(tcb); +#endif + } -#endif /* CONFIG_RR_INTERVAL > 0 || CONFIG_SCHED_SPORADIC */ +#endif /* CONFIG_RR_INTERVAL > 0 || CONFIG_SCHED_SPORADIC || CONFIG_SCHED_INSTRUMENTATION */ diff --git a/sched/sched/sched_suspendscheduler.c b/sched/sched/sched_suspendscheduler.c index 16df6affb8..f938a82e01 100644 --- a/sched/sched/sched_suspendscheduler.c +++ b/sched/sched/sched_suspendscheduler.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sched/sched_suspendscheduler.c * - * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -45,11 +45,12 @@ #include #include #include +#include #include "clock/clock.h" #include "sched/sched.h" -#ifdef CONFIG_SCHED_SPORADIC +#if defined(CONFIG_SCHED_SPORADIC) || defined(CONFIG_SCHED_INSTRUMENTATION) /**************************************************************************** * Public Functions @@ -73,10 +74,20 @@ void sched_suspend_scheduler(FAR struct tcb_s *tcb) { +#ifdef CONFIG_SCHED_SPORADIC + /* Perform sporadic schedule operations */ + if ((tcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC) { DEBUGVERIFY(sched_sporadic_suspend(tcb)); } +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION + /* Inidicate the the task has been suspended */ + + sched_note_suspend(tcb); +#endif } -#endif /* CONFIG_SCHED_SPORADIC */ +#endif /* CONFIG_SCHED_SPORADIC || CONFIG_SCHED_INSTRUMENTATION */