void CPU_Sleep( SLEEP_LEVEL level, UINT64 wakeEvents ) { ASSERT_IRQ_MUST_BE_OFF(); SleepLevel = level; WakeEvents = wakeEvents; ENABLE_INTERRUPTS(); { InSleep = true; #ifdef PLATFORM_ARM_OS_PORT // if no events are already pending - use OS Signal to wait for // one. The OS will atomically clear the signal whenever this // thread is rescheduled. if( Events_MaskedRead( wakeEvents ) == 0 ) osSignalWait( ClrEventSignal, osWaitForever ); #else HAL_CPU_Sleep( level, wakeEvents ); #endif InSleep = false; } DISABLE_INTERRUPTS(); }
UINT32 Events_WaitForEvents( UINT32 sleepLevel, UINT32 WakeupSystemEvents, UINT32 Timeout_Milliseconds ) { NATIVE_PROFILE_PAL_EVENTS(); // do NOT call this routine with interrupts disabled, // as we can die here, since flags are only set in ISRs ASSERT_IRQ_MUST_BE_ON(); // schedule an interrupt for this far in the future // timeout is in milliseconds, convert to Sleep Counts UINT64 CountsRemaining = CPU_MillisecondsToTicks( Timeout_Milliseconds ); #if defined(HAL_PROFILE_ENABLED) Events_WaitForEvents_Calls++; #endif { GLOBAL_LOCK(irq); // then check to make sure the events haven't happened on the way in // we must do this before we sleep! UINT64 Expire = HAL_Time_CurrentTicks() + CountsRemaining; BOOL RunContinuations = TRUE; while(true) { UINT32 Events = Events_MaskedRead( WakeupSystemEvents ); if(Events) return Events; if(Expire <= HAL_Time_CurrentTicks()) return 0; // first check and possibly run any continuations // but only if we have slept after stalling if(RunContinuations && !SystemState_QueryNoLock( SYSTEM_STATE_NO_CONTINUATIONS )) { // restore interrupts before running a continuation irq.Release(); // if we stall on time, don't check again until after we sleep RunContinuations = HAL_CONTINUATION::Dequeue_And_Execute(); irq.Acquire(); } else { // try stalled continuations again after sleeping RunContinuations = TRUE; //lcd_printf("\fSleep=%6lld ", CountsRemaining); //lcd_printf( "Events=%08x", Events_MaskedRead(0xffffffff)); #if defined(HAL_TIMEWARP) if(s_timewarp_lastButton < HAL_Time_TicksToTime( HAL_Time_CurrentTicks() )) { CountsRemaining = Expire - HAL_Time_CurrentTicks(); if(CountsRemaining > 0) { s_timewarp_compensate += (CountsRemaining * 10*1000*1000) / CPU_TicksPerSecond(); } return 0; } #endif ASSERT_IRQ_MUST_BE_OFF(); HAL_COMPLETION::WaitForInterrupts( Expire, sleepLevel, WakeupSystemEvents ); irq.Probe(); // See if we have to serve any pending interrupts. } } } }