rtems_task Test_task( rtems_task_argument unused ) { rtems_id tid; rtems_time_of_day time; uint32_t task_index; rtems_status_code status; int cpu_num; char name[5]; char *p; /* Get the task name */ p = rtems_object_get_name( RTEMS_SELF, 5, name ); rtems_test_assert( p != NULL ); status = rtems_task_ident( RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &tid ); task_index = task_number( tid ); for ( ; ; ) { /* Get the CPU Number */ cpu_num = bsp_smp_processor_id(); status = rtems_clock_get_tod( &time ); if ( time.second >= 35 ) { locked_printf( "*** END OF SMP08 TEST ***" ); rtems_test_exit( 0 ); } PrintTaskInfo( p, &time ); status = rtems_task_wake_after( task_index * 5 * rtems_clock_get_ticks_per_second() ); } }
void _SMP_lock_spinlock_nested_Release( SMP_lock_spinlock_nested_Control *lock, ISR_Level level ) { #if defined (RTEMS_DEBUG) || defined(SMPLOCK_DEBUG) if ( lock->count == 0 ) { printk( "\ncpu %d lock %d Releasing spinlock when count is already " "zero (%p from %p,%p)?!?!\n", bsp_smp_processor_id(), lock->cpu_id, lock, __builtin_return_address(0), __builtin_return_address(1) ); debug_dump_log(); return; } #endif /* assume we actually have it */ if (lock->count == 1) { lock->cpu_id = -1; debug_logit( 'U', lock ); lock->count = 0; RTEMS_COMPILER_MEMORY_BARRIER(); lock->lock = 0; } else { debug_logit( 'u', lock ); lock->count--; } _ISR_Enable_on_this_core( level ); }
void _SMP_Request_other_cores_to_shutdown(void) { bool allDown; int ncpus; int n; int cpu; cpu = bsp_smp_processor_id(); ncpus = _SMP_Processor_count; _SMP_Broadcast_message( RTEMS_BSP_SMP_SHUTDOWN ); allDown = true; for (n=0 ; n<ncpus ; n++ ) { if ( n == cpu ) continue; bsp_smp_wait_for( (unsigned int *)&_Per_CPU_Information[n].state, RTEMS_BSP_SMP_CPU_SHUTDOWN, 10000 ); if ( _Per_CPU_Information[n].state != RTEMS_BSP_SMP_CPU_SHUTDOWN ) allDown = false; } if ( !allDown ) printk( "not all down -- timed out\n" ); #if defined(RTEMS_DEBUG) else printk( "All CPUs shutdown successfully\n" ); #endif }
rtems_task Test_task( rtems_task_argument argument ) { locked_printf( "Shut down from CPU %d\n", bsp_smp_processor_id() ); locked_printf( "*** END OF TEST SMP05 ***\n" ); rtems_test_exit(0); }
void PrintTaskInfo( const char *task_name ) { int cpu_num; cpu_num = bsp_smp_processor_id(); locked_printf(" CPU %d running task %s\n", cpu_num, task_name ); }
static void debug_logit( char act, SMP_lock_spinlock_nested_Control *lock ) { debug_debug_spinlog_t *sp; if ( DEBUG_SPINLOG_INDEX == DEBUG_SPINLOG_MAX ) #if defined (ENABLE_LOOPED_DEBUG_LOGGING) DEBUG_SPINLOG_INDEX = 0; #else return; #endif sp = &DEBUG_SPINLOG[ DEBUG_SPINLOG_INDEX++ ]; sp->action = act; #if 0 if ( lock == &_ISR_SMP_Lock ) sp->lock = 'I'; else #endif if ( lock == &_Thread_Dispatch_disable_level_lock ) sp->lock = 'D'; sp->cpu = bsp_smp_processor_id() + '0'; sp->count = lock->count; #if 0 if ( sp->lock == 'I' ) { if ( _Thread_Dispatch_smp_spin_lock.id == 0 ) printk( "not nested %p from %p %p %p %p\n", sp, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2), __builtin_return_address(3) ); } #endif sp->nest_level = _ISR_Nest_level; sp->ret1 = 0; sp->ret2 = 0; sp->ret3 = 0; sp->ret4 = 0; sp->ret1 = __builtin_return_address(0); if ( sp->ret1 >= start && sp->ret1 <= _fini ) { sp->ret2 = __builtin_return_address(1); if ( sp->ret2 >= start && sp->ret2 <= _fini ) { sp->ret3 = __builtin_return_address(2); if ( sp->ret3 >= start && sp->ret3 <= _fini ) { sp->ret4 = __builtin_return_address(3); } } } }
rtems_task Init( rtems_task_argument argument ) { int i; char ch; int cpu_num; rtems_id id; rtems_status_code status; locked_print_initialize(); locked_printf( "\n\n*** TEST SMP09 ***\n" ); for ( killtime=0; killtime<1000000; killtime++ ) ; for ( i=0; i<rtems_smp_get_number_of_processors() -1; i++ ) { ch = '1' + i; status = rtems_task_create( rtems_build_name( 'T', 'A', ch, ' ' ), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &id ); directive_failed( status, "task create" ); cpu_num = bsp_smp_processor_id(); locked_printf(" CPU %d start task TA%c\n", cpu_num, ch); status = rtems_task_start( id, Test_task, i+1 ); directive_failed( status, "task start" ); } locked_printf(" kill 10 clock ticks\n" ); while ( rtems_clock_get_ticks_since_boot() < 10 ) ; rtems_cpu_usage_report(); locked_printf( "*** END OF TEST SMP09 ***" ); rtems_test_exit(0); }
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 ); } }
void _SMP_Request_other_cores_to_dispatch(void) { int i; int cpu; cpu = bsp_smp_processor_id(); if ( !_System_state_Is_up (_System_state_Current) ) return; for (i=1 ; i < _SMP_Processor_count ; i++ ) { if ( cpu == i ) continue; if ( _Per_CPU_Information[i].state != RTEMS_BSP_SMP_CPU_UP ) continue; if ( !_Per_CPU_Information[i].dispatch_necessary ) continue; _SMP_Send_message( i, RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY ); } }
void _SMP_Broadcast_message( uint32_t message ) { int dest_cpu; int cpu; ISR_Level level; cpu = bsp_smp_processor_id(); for ( dest_cpu=0 ; dest_cpu < _SMP_Processor_count; dest_cpu++ ) { if ( cpu == dest_cpu ) continue; level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock ); _Per_CPU_Information[dest_cpu].message |= message; _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level ); } bsp_smp_broadcast_interrupt(); }
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; }
rtems_task Test_task( rtems_task_argument do_exit ) { int cpu_num; char name[5]; char *p; p = rtems_object_get_name( RTEMS_SELF, 5, name ); rtems_test_assert( p != NULL ); cpu_num = bsp_smp_processor_id(); locked_printf(" CPU %d running Task %s\n", cpu_num, name); Ran = true; if ( do_exit ) { locked_printf( "*** END OF TEST SMP06 ***\n" ); rtems_test_exit(0); } while(1) ; }
rtems_task Init( rtems_task_argument argument ) { int i; char ch; int cpu_num; rtems_id id; rtems_status_code status; locked_print_initialize(); locked_printf( "\n\n*** TEST SMP05 ***\n" ); for ( i=0; i<rtems_smp_get_number_of_processors() ; i++ ) { ch = '1' + i; status = rtems_task_create( rtems_build_name( 'T', 'A', ch, ' ' ), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &id ); directive_failed( status, "task create" ); cpu_num = bsp_smp_processor_id(); locked_printf(" CPU %d start task TA%c\n", cpu_num, ch); status = rtems_task_start( id, Test_task, i+1 ); directive_failed( status, "task start" ); } while (1) ; }
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 ); } }
rtems_task Init( rtems_task_argument argument ) { int cpu_num; rtems_id id; rtems_status_code status; locked_print_initialize(); locked_printf( "\n\n*** TEST SMP06 ***\n" ); locked_printf( "rtems_clock_tick - so this task has run longer\n" ); status = rtems_clock_tick(); directive_failed( status, "clock tick" ); rtems_test_assert( rtems_smp_get_number_of_processors() > 1 ); cpu_num = bsp_smp_processor_id(); /* * Create a task at equal priority. */ Ran = false; status = rtems_task_create( rtems_build_name( 'T', 'A', '1', ' ' ), 2, RTEMS_MINIMUM_STACK_SIZE, RTEMS_PREEMPT, RTEMS_DEFAULT_ATTRIBUTES, &id ); directive_failed( status, "task create" ); locked_printf(" CPU %d start task TA1\n", cpu_num ); status = rtems_task_start( id, Test_task, 0 ); directive_failed( status, "task start" ); while ( Ran == false ) ; /* * Create a task at greater priority. */ Ran = false; status = rtems_task_create( rtems_build_name( 'T', 'A', '2', ' ' ), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_PREEMPT, RTEMS_DEFAULT_ATTRIBUTES, &id ); directive_failed( status, "task create" ); cpu_num = bsp_smp_processor_id(); locked_printf(" CPU %d start task TA2\n", cpu_num ); status = rtems_task_start( id, Test_task, 1 ); directive_failed( status, "task start" ); while ( 1 ) ; }
rtems_task Init( rtems_task_argument argument ) { int i; char ch; int cpu_num; rtems_id id; rtems_status_code status; char str[80]; locked_print_initialize(); locked_printf( "\n\n*** SMP02 TEST ***\n" ); /* Create/verify synchronisation semaphore */ status = rtems_semaphore_create( rtems_build_name ('S', 'E', 'M', '1'), 1, RTEMS_LOCAL | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY, 1, &Semaphore); directive_failed( status, "rtems_semaphore_create" ); /* Lock semaphore */ status = rtems_semaphore_obtain( Semaphore, RTEMS_WAIT, 0); directive_failed( status,"rtems_semaphore_obtain of SEM1\n"); for ( i=1; i < rtems_smp_get_number_of_processors(); i++ ){ /* Create and start tasks for each CPU */ ch = '0' + i; status = rtems_task_create( rtems_build_name( 'T', 'A', ch, ' ' ), 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &id ); cpu_num = bsp_smp_processor_id(); locked_printf(" CPU %d start task TA%c\n", cpu_num, ch); status = rtems_task_start( id, Test_task, i+1 ); directive_failed( status, str ); } /* * Release the semaphore, allowing the blocked tasks to start. */ status = rtems_semaphore_release( Semaphore ); directive_failed( status,"rtems_semaphore_release of SEM1\n"); /* * Wait for log full. print the log and end the program. */ while (Log_index < LOG_SIZE) ; for (i=0; i< LOG_SIZE; i++) { if ( Log[i].IsLocked ) { locked_printf( " CPU %d Task TA%" PRIu32 " Obtain\n", Log[i].cpu_num, Log[i].task_index ); } else { locked_printf( " CPU %d Task TA%" PRIu32 " Release\n", Log[i].cpu_num, Log[i].task_index ); } } locked_printf( "*** END OF TEST SMP02 ***\n" ); rtems_test_exit( 0 ); }