/* * sigaltstack will cause this function to be called on an alternate stack. * This allows us to bootstrap new threads. */ void HalStackTrampoline( int SignalNumber ) { int status; //Save stack startup state before releaseing the tempContext. STACK_INIT_ROUTINE * foo = halTempContext->Foo; void * arg = halTempContext->Arg; status = _setjmp( halTempContext->Registers ); if( status == 0 ) { //Because status was 0 we know that this is the creation of //the stack frame. We can use the locals to construct the frame. halTempContextProcessed = TRUE; halTempContext = NULL; return; } else { //If we get here, then someone has jumped into a newly created thread. //Test to make sure we are atomic ASSERT( HalIsIrqAtomic(IRQ_LEVEL_MAX) ); foo(arg); //Returning from a function which was invoked by siglongjmp is not //supported. Foo should never retrun. HalPanic("Tried to return from trampoline!"); return; } }
/* * sigaltstack will cause this fuction to be called on an alternate stack. * This allows us to bootstrap new threads. */ void HalStackTrampoline( int SignalNumber ) { int status; status = _setjmp( halTempContext->Registers ); if( status == 0 ) { //Because status was 0 we know that this is the creation of //the stack frame. We can use the locals to construct the frame. halTempContextProcessed = TRUE; halTempContext = NULL; return; } else { //If we get here, then someone has jumped into a newly created thread. //Test to make sure we are atomic ASSERT( HalIsIrqAtomic(IRQ_LEVEL_TIMER) ); StackInitRoutine(); //Returning from a function which was invoked by siglongjmp is not //supported. Foo should never retrun. HalPanic("Tried to return from StackInitRoutine!\n", 0 ); return; } }
/* * Performs a context switch between one MACHINE_CONTEXT (thread) and another. * Because want to avoid having interrupts fire while the register file is in an intermidiate * state, all regilar interrupts should be disabled when calling this function. */ void HalContextSwitch(struct MACHINE_CONTEXT * oldStack, struct MACHINE_CONTEXT * newStack) { int status; ASSERT( HalIsIrqAtomic(IRQ_LEVEL_MAX) ); //Save the stack state into old context. status = _setjmp( oldStack->Registers ); if( status == 0 ) { //This was the saving call to setjmp. _longjmp( newStack->Registers, 1 ); } else { //This was the restore call started by longjmp call. //We have just switched into a different thread. } ASSERT( HalIsIrqAtomic(IRQ_LEVEL_MAX) ); }
/* * IRQ based systems typically have a reserved space in memory which * serves as a jump table. The table is filled with function pointers * to invoke when various irq level transitions occur. Typically different * offsets also get a level associated with it. So that you can change the * order of various devices. (so a can mask c and b can mask c. * * handler - the function pointer to invoke. * which - the location which indicates what hardware event happed. * level - what irq to assign to the hardware event. */ void HalRegisterIsrHandler( ISR_HANDLER handler, void * which, enum IRQ_LEVEL level) { INDEX i; INDEX signum = (INDEX) which; ASSERT(HalIsIrqAtomic(IRQ_LEVEL_MAX)); for(i=level; i < IRQ_LEVEL_COUNT; i++) { sigaddset(&HalIrqTable[i].sa_mask, signum); } HalIrqToSignal[level] = signum; HalIsrJumpTable[level] = handler; HalIrqTable[level].sa_handler = HalIsrHandler; HalIsrFinalize(); HalSetIrq(IRQ_LEVEL_MAX); }
void HalSleepProcessor() { ASSERT( !HalIsIrqAtomic(IRQ_LEVEL_TIMER) ); pause(); }