void Shutdown() { std::lock_guard<std::mutex> lk(s_ts_write_lock); MoveEvents(); ClearPendingEvents(); UnregisterAllEvents(); }
void Advance() { MoveEvents(); int cyclesExecuted = slicelength - DowncountToCycles(PowerPC::ppcState.downcount); globalTimer += cyclesExecuted; lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f; PowerPC::ppcState.downcount = CyclesToDowncount(slicelength); while (first && first->time <= globalTimer) { //LOG(POWERPC, "[Scheduler] %s (%lld, %lld) ", // event_types[first->type].name ? event_types[first->type].name : "?", (u64)globalTimer, (u64)first->time); Event* evt = first; first = first->next; event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time)); FreeEvent(evt); } if (!first) { WARN_LOG(POWERPC, "WARNING - no events in queue. Setting downcount to 10000"); PowerPC::ppcState.downcount += CyclesToDowncount(10000); } else { slicelength = (int)(first->time - globalTimer); if (slicelength > maxSliceLength) slicelength = maxSliceLength; PowerPC::ppcState.downcount = CyclesToDowncount(slicelength); } }
//This raise only the events required while the fifo is processing data void ProcessFifoWaitEvents() { if (Common::AtomicLoadAcquire(hasTsEvents)) MoveEvents(); if (!first) return; while (first) { if (first->time <= globalTimer) { // LOG(CPU, "[Scheduler] %s (%lld, %lld) ", // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time); Event* evt = first; first = first->next; event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time)); FreeEvent(evt); } else { break; } } }
void Advance() { s64 cycles_executed = g_slice_length - Core::g_app_core->down_count; global_timer += cycles_executed; Core::g_app_core->down_count = g_slice_length; if (has_ts_events) MoveEvents(); ProcessFifoWaitEvents(); if (!first) { if (g_slice_length < 10000) { g_slice_length += 10000; Core::g_app_core->down_count += g_slice_length; } } else { // Note that events can eat cycles as well. int target = (int)(first->time - global_timer); if (target > MAX_SLICE_LENGTH) target = MAX_SLICE_LENGTH; const int diff = target - g_slice_length; g_slice_length += diff; Core::g_app_core->down_count += diff; } if (advance_callback) advance_callback(static_cast<int>(cycles_executed)); }
void Advance() { int cyclesExecuted = slicelength - currentMIPS->downcount; globalTimer += cyclesExecuted; currentMIPS->downcount = slicelength; if (Common::AtomicLoadAcquire(hasTsEvents)) MoveEvents(); ProcessFifoWaitEvents(); if (!first) { // WARN_LOG(TIMER, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000"); currentMIPS->downcount += 10000; slicelength = 10000; } else { slicelength = (int)(first->time - globalTimer); if (slicelength > MAX_SLICE_LENGTH) slicelength = MAX_SLICE_LENGTH; currentMIPS->downcount = slicelength; } if (advanceCallback) advanceCallback(cyclesExecuted); }
void Advance() { int cyclesExecuted = slicelength - currentMIPS->downcount; globalTimer += cyclesExecuted; currentMIPS->downcount = slicelength; if (Common::AtomicLoadAcquire(hasTsEvents)) MoveEvents(); ProcessFifoWaitEvents(); if (!first) { // This should never happen in PPSSPP. // WARN_LOG_REPORT(TIME, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000"); if (slicelength < 10000) { slicelength += 10000; currentMIPS->downcount += slicelength; } } else { // Note that events can eat cycles as well. int target = (int)(first->time - globalTimer); if (target > MAX_SLICE_LENGTH) target = MAX_SLICE_LENGTH; const int diff = target - slicelength; slicelength += diff; currentMIPS->downcount += diff; } if (advanceCallback) advanceCallback(cyclesExecuted); }
void Advance() { MoveEvents(); int cycles_executed = slice_length - downcount; global_timer += cycles_executed; slice_length = MAX_SLICE_LENGTH; is_global_timer_sane = true; while (!event_queue.empty() && event_queue.front().time <= global_timer) { Event evt = std::move(event_queue.front()); std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<Event>()); event_queue.pop_back(); evt.type->callback(evt.userdata, global_timer - evt.time); } is_global_timer_sane = false; // Still events left (scheduled in the future) if (!event_queue.empty()) { slice_length = static_cast<int>( std::min<s64>(event_queue.front().time - global_timer, MAX_SLICE_LENGTH)); } downcount = slice_length; }
void DoState(PointerWrap& p) { std::lock_guard<std::mutex> lk(s_ts_write_lock); p.Do(g_slice_length); p.Do(g_global_timer); p.Do(s_idled_cycles); p.Do(s_fake_dec_start_value); p.Do(s_fake_dec_start_ticks); p.Do(g_fake_TB_start_value); p.Do(g_fake_TB_start_ticks); p.Do(s_last_OC_factor); g_last_OC_factor_inverted = 1.0f / s_last_OC_factor; p.Do(s_event_fifo_id); p.DoMarker("CoreTimingData"); MoveEvents(); p.DoEachElement(s_event_queue, [](PointerWrap& pw, Event& ev) { pw.Do(ev.time); pw.Do(ev.fifo_order); // this is why we can't have (nice things) pointers as userdata pw.Do(ev.userdata); // we can't savestate ev.type directly because events might not get registered in the same // order (or at all) every time. // so, we savestate the event's type's name, and derive ev.type from that when loading. std::string name; if (pw.GetMode() != PointerWrap::MODE_READ) name = *ev.type->name; pw.Do(name); if (pw.GetMode() == PointerWrap::MODE_READ) { auto itr = s_event_types.find(name); if (itr != s_event_types.end()) { ev.type = &itr->second; } else { WARN_LOG(POWERPC, "Lost event from savestate because its type, \"%s\", has not been registered.", name.c_str()); ev.type = s_ev_lost; } } }); p.DoMarker("CoreTimingEvents"); // When loading from a save state, we must assume the Event order is random and meaningless. // The exact layout of the heap in memory is implementation defined, therefore it is platform // and library version specific. if (p.GetMode() == PointerWrap::MODE_READ) std::make_heap(s_event_queue.begin(), s_event_queue.end(), std::greater<Event>()); }
void Shutdown() { std::lock_guard<std::mutex> lk(tsWriteLock); MoveEvents(); ClearPendingEvents(); UnregisterAllEvents(); while (eventPool) { Event *ev = eventPool; eventPool = ev->next; delete ev; } }
void DoState(PointerWrap &p) { std::lock_guard<std::mutex> lk(tsWriteLock); p.Do(slicelength); p.Do(globalTimer); p.Do(idledCycles); p.Do(fakeDecStartValue); p.Do(fakeDecStartTicks); p.Do(fakeTBStartValue); p.Do(fakeTBStartTicks); p.DoMarker("CoreTimingData"); MoveEvents(); p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, EventDoState>(first); p.DoMarker("CoreTimingEvents"); }
void Shutdown() { MoveEvents(); ClearPendingEvents(); UnregisterAllEvents(); while (event_pool) { Event* event = event_pool; event_pool = event->next; delete event; } std::lock_guard<std::recursive_mutex> lock(external_event_section); while (event_ts_pool) { Event* event = event_ts_pool; event_ts_pool = event->next; delete event; } }
void Advance() { MoveEvents(); int cyclesExecuted = g_slicelength - DowncountToCycles(PowerPC::ppcState.downcount); g_globalTimer += cyclesExecuted; s_lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f; g_lastOCFactor_inverted = 1.0f / s_lastOCFactor; PowerPC::ppcState.downcount = CyclesToDowncount(g_slicelength); globalTimerIsSane = true; while (first && first->time <= g_globalTimer) { //LOG(POWERPC, "[Scheduler] %s (%lld, %lld) ", // event_types[first->type].name ? event_types[first->type].name : "?", (u64)g_globalTimer, (u64)first->time); Event* evt = first; first = first->next; event_types[evt->type].callback(evt->userdata, (int)(g_globalTimer - evt->time)); FreeEvent(evt); } globalTimerIsSane = false; if (!first) { WARN_LOG(POWERPC, "WARNING - no events in queue. Setting downcount to 10000"); PowerPC::ppcState.downcount += CyclesToDowncount(10000); } else { g_slicelength = (int)(first->time - g_globalTimer); if (g_slicelength > maxslicelength) g_slicelength = maxslicelength; PowerPC::ppcState.downcount = CyclesToDowncount(g_slicelength); } // Check for any external exceptions. // It's important to do this after processing events otherwise any exceptions will be delayed until the next slice: // Pokemon Box refuses to boot if the first exception from the audio DMA is received late PowerPC::CheckExternalExceptions(); }
void Advance() { MoveEvents(); int cyclesExecuted = slicelength - PowerPC::ppcState.downcount; globalTimer += cyclesExecuted; PowerPC::ppcState.downcount = slicelength; while (first) { if (first->time <= globalTimer) { //LOG(POWERPC, "[Scheduler] %s (%lld, %lld) ", // event_types[first->type].name ? event_types[first->type].name : "?", (u64)globalTimer, (u64)first->time); Event* evt = first; first = first->next; event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time)); FreeEvent(evt); } else { break; } } if (!first) { WARN_LOG(POWERPC, "WARNING - no events in queue. Setting downcount to 10000"); PowerPC::ppcState.downcount += 10000; } else { slicelength = (int)(first->time - globalTimer); if (slicelength > maxSliceLength) slicelength = maxSliceLength; PowerPC::ppcState.downcount = slicelength; } if (advanceCallback) advanceCallback(cyclesExecuted); }
void DoState(PointerWrap &p) { std::lock_guard<std::mutex> lk(tsWriteLock); p.Do(g_slicelength); p.Do(g_globalTimer); p.Do(idledCycles); p.Do(fakeDecStartValue); p.Do(fakeDecStartTicks); p.Do(g_fakeTBStartValue); p.Do(g_fakeTBStartTicks); p.Do(s_lastOCFactor); if (p.GetMode() == PointerWrap::MODE_READ) g_lastOCFactor_inverted = 1.0f / s_lastOCFactor; p.DoMarker("CoreTimingData"); MoveEvents(); p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, EventDoState>(first); p.DoMarker("CoreTimingEvents"); }
void Shutdown() { MoveEvents(); ClearPendingEvents(); UnregisterAllEvents(); while(eventPool) { Event *ev = eventPool; eventPool = ev->next; delete ev; } std::lock_guard<std::recursive_mutex> lk(externalEventSection); while(eventTsPool) { Event *ev = eventTsPool; eventTsPool = ev->next; delete ev; } }
void Advance() { MoveEvents(); int cyclesExecuted = g_slice_length - DowncountToCycles(PowerPC::ppcState.downcount); g_global_timer += cyclesExecuted; s_last_OC_factor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f; g_last_OC_factor_inverted = 1.0f / s_last_OC_factor; g_slice_length = MAX_SLICE_LENGTH; s_is_global_timer_sane = true; while (!s_event_queue.empty() && s_event_queue.front().time <= g_global_timer) { Event evt = std::move(s_event_queue.front()); std::pop_heap(s_event_queue.begin(), s_event_queue.end(), std::greater<Event>()); s_event_queue.pop_back(); // NOTICE_LOG(POWERPC, "[Scheduler] %-20s (%lld, %lld)", evt.type->name->c_str(), // g_global_timer, evt.time); evt.type->callback(evt.userdata, g_global_timer - evt.time); } s_is_global_timer_sane = false; // Still events left (scheduled in the future) if (!s_event_queue.empty()) { g_slice_length = static_cast<int>( std::min<s64>(s_event_queue.front().time - g_global_timer, MAX_SLICE_LENGTH)); } PowerPC::ppcState.downcount = CyclesToDowncount(g_slice_length); // Check for any external exceptions. // It's important to do this after processing events otherwise any exceptions will be delayed // until the next slice: // Pokemon Box refuses to boot if the first exception from the audio DMA is received late PowerPC::CheckExternalExceptions(); }
void Advance() { MoveEvents(); int cyclesExecuted = slicelength - downcount; globalTimer += cyclesExecuted; downcount = slicelength; while (first) { if (first->time <= globalTimer) { // LOG(CPU, "[Scheduler] %s (%lld, %lld) ", // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time); Event* evt = first; first = first->next; event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time)); FreeEvent(evt); } else { break; } } if (!first) { // WARN_LOG(CPU, "WARNING - no events in queue. Setting downcount to 10000"); downcount += 10000; } else { slicelength = (int)(first->time - globalTimer); if (slicelength > MAX_SLICE_LENGTH) slicelength = MAX_SLICE_LENGTH; downcount = slicelength; } if (advanceCallback) advanceCallback(cyclesExecuted); }
//This raise only the events required while the fifo is processing data void ProcessFifoWaitEvents() { MoveEvents(); if (!first) return; while (first) { if (first->time <= globalTimer) { Event* evt = first; first = first->next; event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time)); FreeEvent(evt); } else { break; } } }
void RemoveAllEvents(int event_type) { MoveEvents(); RemoveEvent(event_type); }
void RemoveAllEvents(EventType* event_type) { MoveEvents(); RemoveEvent(event_type); }
void Shutdown() { MoveEvents(); ClearPendingEvents(); UnregisterAllEvents(); }
void RemoveNormalAndThreadsafeEvent(const EventType* event_type) { MoveEvents(); RemoveEvent(event_type); }