/** * @file * * @brief Thread Dispatch Disable Functions * * @ingroup ScoreThread */ /* * COPYRIGHT (c) 1989-2011. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ #include #include #include #include #define NO_OWNER_CPU NULL typedef struct { SMP_lock_Control lock; Per_CPU_Control *owner_cpu; uint32_t nest_level; } Giant_Control; static Giant_Control _Giant = { .lock = SMP_LOCK_INITIALIZER("Giant"), .owner_cpu = NO_OWNER_CPU, .nest_level = 0 }; static void _Giant_Do_acquire( Per_CPU_Control *self_cpu ) { Giant_Control *giant = &_Giant; if ( giant->owner_cpu != self_cpu ) { _SMP_lock_Acquire( &giant->lock, &self_cpu->Giant_lock_context ); giant->owner_cpu = self_cpu; giant->nest_level = 1; } else { ++giant->nest_level; } } static void _Giant_Do_release( Per_CPU_Control *self_cpu ) { Giant_Control *giant = &_Giant; --giant->nest_level; if ( giant->nest_level == 0 ) { giant->owner_cpu = NO_OWNER_CPU; _SMP_lock_Release( &giant->lock, &self_cpu->Giant_lock_context ); } } void _Giant_Drop( Per_CPU_Control *self_cpu ) { Giant_Control *giant = &_Giant; _Assert( _ISR_Get_level() != 0 ); if ( giant->owner_cpu == self_cpu ) { giant->nest_level = 0; giant->owner_cpu = NO_OWNER_CPU; _SMP_lock_Release( &giant->lock, &self_cpu->Giant_lock_context ); } } uint32_t _Thread_Dispatch_increment_disable_level( void ) { ISR_Level isr_level; uint32_t disable_level; Per_CPU_Control *self_cpu; _ISR_Disable_without_giant( isr_level ); /* * We must obtain the processor after interrupts are disabled to prevent * thread migration. */ self_cpu = _Per_CPU_Get(); _Giant_Do_acquire( self_cpu ); disable_level = self_cpu->thread_dispatch_disable_level; _Profiling_Thread_dispatch_disable( self_cpu, disable_level ); ++disable_level; self_cpu->thread_dispatch_disable_level = disable_level; _ISR_Enable_without_giant( isr_level ); return disable_level; } uint32_t _Thread_Dispatch_decrement_disable_level( void ) { ISR_Level isr_level; uint32_t disable_level; Per_CPU_Control *self_cpu; _ISR_Disable_without_giant( isr_level ); self_cpu = _Per_CPU_Get(); disable_level = self_cpu->thread_dispatch_disable_level; --disable_level; self_cpu->thread_dispatch_disable_level = disable_level; _Giant_Do_release( self_cpu ); _Assert( disable_level != 0 || _Giant.owner_cpu != self_cpu ); _Profiling_Thread_dispatch_enable( self_cpu, disable_level ); _ISR_Enable_without_giant( isr_level ); return disable_level; } void _Giant_Acquire( void ) { ISR_Level isr_level; _ISR_Disable_without_giant( isr_level ); _Assert( _Thread_Dispatch_disable_level != 0 ); _Giant_Do_acquire( _Per_CPU_Get() ); _ISR_Enable_without_giant( isr_level ); } void _Giant_Release( void ) { ISR_Level isr_level; _ISR_Disable_without_giant( isr_level ); _Assert( _Thread_Dispatch_disable_level != 0 ); _Giant_Do_release( _Per_CPU_Get() ); _ISR_Enable_without_giant( isr_level ); } #if defined( RTEMS_DEBUG ) bool _Debug_Is_owner_of_giant( void ) { Giant_Control *giant = &_Giant; return giant->owner_cpu == _Per_CPU_Get_snapshot() || !_System_state_Is_up( _System_state_Get() ); } #endif