/// Reschedules to the next available thread (call after current thread is suspended) void Reschedule() { Thread* prev = GetCurrentThread(); Thread* next = NextThread(); HLE::g_reschedule = false; if (next > 0) { INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); SwitchContext(next); // Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep // by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again. // This results in the current thread yielding on a VBLANK once, and then it will be // immediately placed back in the queue for execution. if (prev->wait_type == WAITTYPE_VBLANK) { ResumeThreadFromWait(prev->GetHandle()); } } }
void SaveSamples( void ) /* called from StopAndSave, and report */ { unsigned size; unsigned tid; unsigned i, j; cgraph_sample xfer; tid = 0; while( (tid = NextThread( tid )) ) { if( !CallGraphMode ) { /* record actual sample only */ if( SampleIndex > 0 ) { size = sizeof( samp_block_prefix ) + sizeof( struct samp_samples ) + (SampleIndex - 1) * sizeof( samp_address ); Samples->pref.length = size; if( SampWrite( Samples, size ) == 0 ) { Info.d.count[ SAMP_SAMPLES ].size += size; Info.d.count[ SAMP_SAMPLES ].number += 1; } SampleIndex = 0; } } else { /* record sample and callgraph information */ for( i=0; i < SampleIndex; i++ ) if( SampleCount > 0 ) { /* write sample record */ size = SIZE_PREFIX + SIZE_SAMPLE + SampleCount * SIZE_SAMP_ADDR; Samples->pref.length = size; Info.d.count[ SAMP_SAMPLES ].size += size; Info.d.count[ SAMP_SAMPLES ].number += 1; SampWrite( Samples, SIZE_PREFIX + SIZE_SAMPLE ); for( i = 0, j = 0; i < SampleCount; i++ ) { SampWrite( &Samples->d.sample.sample[ j ], SIZE_SAMP_ADDR ); j += ( Samples->d.sample.sample[ j+1 ].offset >> 16 ) + 2; } /* write callgraph record */ size = SIZE_PREFIX + SIZE_CALLGRAPH + /* prefix stuff */ SampleCount * SIZE_CGRAPH_SAMPLE + /* push/pop info */ (SampleIndex - 2*SampleCount) * /* cgraph samples */ SIZE_SAMP_ADDR; CallGraph->pref.length = size; CallGraph->d.cgraph.number = SampleCount; Info.d.count[ SAMP_CALLGRAPH ].size += size; Info.d.count[ SAMP_CALLGRAPH ].number += 1; SampWrite( CallGraph, SIZE_PREFIX + SIZE_CALLGRAPH); for( i = 0, j = 1; i < SampleCount; i++ ) { if( Samples->d.sample.sample[ j ].segment == 0 ) { xfer.pop_n = (uint_16) Samples->d.sample.sample[ j ].offset; xfer.push_n = Samples->d.sample.sample[ j ].offset >> 16; stackSize -= xfer.pop_n; if( stackSize < 0 ) { xfer.pop_n += stackSize; } stackSize += xfer.push_n; SampWrite( &xfer, SIZE_CGRAPH_SAMPLE ); SampWrite( &Samples->d.sample.sample[ j + 1 ], xfer.push_n * SIZE_SAMP_ADDR ); j += xfer.push_n + 2; } else { /* the callgraph info was not available */ xfer.pop_n = -1; /* flag this condition for */ xfer.push_n = -1; /* the profiler. */ SampWrite( &xfer, SIZE_CGRAPH_SAMPLE ); j += 2; } } SampleIndex = 0; SampleCount = 0; LastSampleIndex = 0; }