ISR_Level _ISR_SMP_Disable(void) { ISR_Level level; _ISR_Disable_on_this_core( level ); return level; }
uint32_t _Thread_Dispatch_decrement_disable_level(void) { ISR_Level isr_level; uint32_t level; /* First we must disable ISRs in order to protect * accesses to the dispatch disable level. */ _ISR_Disable_on_this_core( isr_level ); _Thread_Dispatch_disable_level--; level = _Thread_Dispatch_disable_level; /* * Note: _SMP_lock_spinlock_nested_Obtain returns with * ISR's disabled and _SMP_lock_spinlock_nested_Release * is responsable for re-enabling interrupts. */ _SMP_lock_spinlock_nested_Release( &_Thread_Dispatch_disable_level_lock, isr_level ); return level; }
int _ISR_SMP_Enter(void) { uint32_t isr_nest_level; ISR_Level level; _ISR_Disable_on_this_core( level ); isr_nest_level = _ISR_Nest_level++; _Thread_Disable_dispatch(); return isr_nest_level; }
/* * Process request to switch to the first task on a secondary core. */ void rtems_smp_run_first_task(int cpu) { Thread_Control *heir; ISR_Level level; _ISR_Disable_on_this_core( level ); /* * The Scheduler will have selected the heir thread for each CPU core. * Now we have been requested to perform the first context switch. So * force a switch to the designated heir and make it executing on * THIS core. */ heir = _Thread_Heir; _Thread_Executing = heir; _CPU_Context_switch_to_first_task_smp( &heir->Registers ); }
ISR_Level _SMP_lock_spinlock_simple_Obtain( SMP_lock_spinlock_simple_Control *lock ) { ISR_Level level = 0; uint32_t value = 1; uint32_t previous; /* Note: Disable provides an implicit memory barrier. */ _ISR_Disable_on_this_core( level ); do { RTEMS_COMPILER_MEMORY_BARRIER(); SMP_CPU_SWAP( lock, value, previous ); RTEMS_COMPILER_MEMORY_BARRIER(); } while (previous == 1); return level; }
void rtems_smp_secondary_cpu_initialize(void) { int cpu; ISR_Level level; cpu = bsp_smp_processor_id(); _ISR_Disable_on_this_core( level ); bsp_smp_secondary_cpu_initialize(cpu); /* * Inform the primary CPU that this secondary CPU is initialized * and ready to dispatch to the first thread it is supposed to * execute when the primary CPU is ready. */ _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_INITIALIZED; #if defined(RTEMS_DEBUG) printk( "Made it to %d -- ", cpu ); #endif /* * With this secondary core out of reset, we can wait for the * request to switch to the first task. */ while(1) { uint32_t message; bsp_smp_wait_for( (volatile unsigned int *)&_Per_CPU_Information[cpu].message, RTEMS_BSP_SMP_FIRST_TASK, 10000 ); level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock ); message = _Per_CPU_Information[cpu].message; if ( message & RTEMS_BSP_SMP_FIRST_TASK ) { _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level ); _ISR_Set_level( 0 ); } _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level ); } }
ISR_Level _SMP_lock_spinlock_nested_Obtain( SMP_lock_spinlock_nested_Control *lock ) { ISR_Level level = 0; uint32_t value = 1; uint32_t previous; int cpu_id; /* Note: Disable provides an implicit memory barrier. */ _ISR_Disable_on_this_core( level ); cpu_id = bsp_smp_processor_id(); /* * Attempt to obtain the lock. If we do not get it immediately, then * do a single "monitor" iteration. This should allow the loop to back * off the bus a bit and allow the other core to finish sooner. */ while (1) { RTEMS_COMPILER_MEMORY_BARRIER(); SMP_CPU_SWAP( &lock->lock, value, previous ); RTEMS_COMPILER_MEMORY_BARRIER(); if ( previous == 0 ) { /* was not locked */ break; } /* Deal with nested calls from one cpu */ if (cpu_id == lock->cpu_id) { lock->count++; debug_logit( 'l', lock ); return level; } } lock->cpu_id = cpu_id; lock->count = 1; debug_logit( 'L', lock ); return level; }
int _ISR_SMP_Exit(void) { ISR_Level level; int retval; retval = 0; _ISR_Disable_on_this_core( level ); _ISR_Nest_level--; if ( _ISR_Nest_level == 0 ) { if ( _Thread_Dispatch_necessary ) { if ( _Thread_Dispatch_get_disable_level() == 1 ) { retval = 1; } } } /* * SPARC has special support to avoid some nasty recursive type behaviour. * When dispatching in a thread and we want to return to it then it needs * to finish. */ #if defined(__sparc__) if ( _CPU_ISR_Dispatch_disable ) retval = 0; #endif _ISR_Enable_on_this_core( level ); _Thread_Dispatch_decrement_disable_level(); if ( retval == 0 ) _SMP_Request_other_cores_to_dispatch(); return retval; }
void rtems_smp_process_interrupt(void) { int cpu; uint32_t message; ISR_Level level; cpu = bsp_smp_processor_id(); level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock ); message = _Per_CPU_Information[cpu].message; #if defined(RTEMS_DEBUG) { void *sp = __builtin_frame_address(0); if ( !(message & RTEMS_BSP_SMP_SHUTDOWN) ) { printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", cpu, message, sp ); if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY ) printk( "context switch necessary\n" ); if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF ) printk( "signal to self\n" ); if ( message & RTEMS_BSP_SMP_SHUTDOWN ) printk( "shutdown\n" ); if ( message & RTEMS_BSP_SMP_FIRST_TASK ) printk( "switch to first task\n" ); } printk( "Dispatch level %d\n", _Thread_Dispatch_get_disable_level() ); } #endif if ( message & RTEMS_BSP_SMP_FIRST_TASK ) { _Per_CPU_Information[cpu].isr_nest_level = 0; _Per_CPU_Information[cpu].message &= ~message; _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_UP; _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level ); rtems_smp_run_first_task(cpu); /* does not return */ } if ( message & RTEMS_BSP_SMP_SHUTDOWN ) { _Per_CPU_Information[cpu].message &= ~message; _Per_CPU_Information[cpu].isr_nest_level = 0; _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_SHUTDOWN; _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level ); _Thread_Enable_dispatch(); /* undo ISR code */ _ISR_Disable_on_this_core( level ); while(1) ; /* does not continue past here */ } if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY ) { #if defined(RTEMS_DEBUG) printk( "switch needed\n" ); #endif _Per_CPU_Information[cpu].message &= ~message; _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level ); } }