void _Thread_Dispatch( void ) { ISR_Level level; Per_CPU_Control *cpu_self; _ISR_Disable_without_giant( level ); cpu_self = _Per_CPU_Get(); if ( cpu_self->dispatch_necessary ) { _Profiling_Thread_dispatch_disable( cpu_self, 0 ); cpu_self->thread_dispatch_disable_level = 1; _Thread_Do_dispatch( cpu_self, level ); } else { _ISR_Enable_without_giant( level ); } }
void ppc_exc_wrapup(BSP_Exception_frame *frame) { Per_CPU_Control *cpu_self; cpu_self = _Per_CPU_Get(); if (cpu_self->isr_dispatch_disable) { return; } while (cpu_self->dispatch_necessary) { rtems_interrupt_level level; cpu_self->isr_dispatch_disable = 1; cpu_self->thread_dispatch_disable_level = 1; _Thread_Do_dispatch(cpu_self, frame->EXC_SRR1); rtems_interrupt_local_disable(level); (void) level; cpu_self = _Per_CPU_Get(); } cpu_self->isr_dispatch_disable = 0; }
void _Thread_Handler( void ) { Thread_Control *executing; ISR_Level level; Per_CPU_Control *cpu_self; /* * Some CPUs need to tinker with the call frame or registers when the * thread actually begins to execute for the first time. This is a * hook point where the port gets a shot at doing whatever it requires. */ _Context_Initialization_at_thread_begin(); executing = _Thread_Executing; /* * have to put level into a register for those cpu's that use * inline asm here */ level = executing->Start.isr_level; _ISR_Set_level( level ); /* * Initialize the floating point context because we do not come * through _Thread_Dispatch on our first invocation. So the normal * code path for performing the FP context switch is not hit. */ _Thread_Restore_fp( executing ); /* * Do not use the level of the thread control block, since it has a * different format. */ _ISR_Local_disable( level ); /* * At this point, the dispatch disable level BETTER be 1. */ cpu_self = _Per_CPU_Get(); _Assert( cpu_self->thread_dispatch_disable_level == 1 ); /* * Make sure we lose no thread dispatch necessary update and execute the * post-switch actions. As a side-effect change the thread dispatch level * from one to zero. Do not use _Thread_Enable_dispatch() since there is no * valid thread dispatch necessary indicator in this context. */ _Thread_Do_dispatch( cpu_self, level ); /* * Invoke the thread begin extensions in the context of the thread entry * function with thread dispatching enabled. This enables use of dynamic * memory allocation, creation of POSIX keys and use of C++ thread local * storage. Blocking synchronization primitives are allowed also. */ _User_extensions_Thread_begin( executing ); /* * RTEMS supports multiple APIs and each API can define a different * thread/task prototype. The following code supports invoking the * user thread entry point using the prototype expected. */ ( *executing->Start.Entry.adaptor )( executing ); /* * In the call above, the return code from the user thread body which return * something was placed in return_argument. This assumed that if it * returned anything (which is not supporting in all APIs), then it would be * able to fit in a (void *). */ _User_extensions_Thread_exitted( executing ); _Internal_error( INTERNAL_ERROR_THREAD_EXITTED ); }