diff --git a/sched/sched/Make.defs b/sched/sched/Make.defs index 7bacba7b0f8..e8a67b961a6 100644 --- a/sched/sched/Make.defs +++ b/sched/sched/Make.defs @@ -100,8 +100,10 @@ endif ifeq ($(CONFIG_SMP),y) CSRCS += sched_tasklistlock.c +ifeq ($(CONFIG_ARCH_GLOBAL_IRQDISABLE),y) CSRCS += sched_thistask.c endif +endif # Include sched build support diff --git a/sched/sched/sched.h b/sched/sched/sched.h index cad10c8d943..b5ccb7b48bd 100644 --- a/sched/sched/sched.h +++ b/sched/sched/sched.h @@ -72,12 +72,19 @@ /* These are macros to access the current CPU and the current task on a CPU. * These macros are intended to support a future SMP implementation. - * NOTE: this_task() for SMP is implemented in sched_thistask.c + * NOTE: this_task() for SMP is implemented in sched_thistask.c if the CPU + * supports disabling of inter-processor interrupts. + * + * REVISIT: A mechanism to provide an atomic this_task() is still required + * for the case where where inter-processor interrupts cannot be disabled! */ #ifdef CONFIG_SMP # define current_task(cpu) ((FAR struct tcb_s *)g_assignedtasks[cpu].head) # define this_cpu() up_cpu_index() +# ifndef CONFIG_ARCH_GLOBAL_IRQDISABLE +# define this_task() (current_task(this_cpu())) +# endif #else # define current_task(cpu) ((FAR struct tcb_s *)g_readytorun.head) # define this_cpu() (0) @@ -428,7 +435,9 @@ void sched_sporadic_lowpriority(FAR struct tcb_s *tcb); #endif #ifdef CONFIG_SMP +#ifdef CONFIG_ARCH_GLOBAL_IRQDISABLE FAR struct tcb_s *this_task(void); +#endif int sched_cpu_select(cpu_set_t affinity); int sched_cpu_pause(FAR struct tcb_s *tcb); diff --git a/sched/sched/sched_thistask.c b/sched/sched/sched_thistask.c index 1c0584db067..d7d17cb9e8f 100644 --- a/sched/sched/sched_thistask.c +++ b/sched/sched/sched_thistask.c @@ -69,17 +69,22 @@ FAR struct tcb_s *this_task(void) { - irqstate_t flags; FAR struct tcb_s *tcb; - #ifdef CONFIG_ARCH_GLOBAL_IRQDISABLE - /* Disable local interrupts to avoid CPU switching */ + irqstate_t flags; + + /* If the CPU supports suppression of interprocessor interrupts, then simple + * disabling interrupts will provide sufficient protection for the following + * operations. + */ flags = up_irq_save(); #else - /* Enter a critical section */ - - //flags = enter_critical_section(); + /* REVISIT: Otherwise, there is no protection available. sched_lock() and + * enter_critical section are not viable options here (because both depend + * on this_task()). + */ +# warning "Missing critical section" #endif /* Obtain the TCB which is currently running on this CPU */ @@ -90,8 +95,6 @@ FAR struct tcb_s *this_task(void) #ifdef CONFIG_ARCH_GLOBAL_IRQDISABLE up_irq_restore(flags); -#else - //leave_critical_section(flags); #endif return tcb; }