mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	core_timing: Lock CoreTiming event queue while deserializing
To handle those classic asymmetric constructor/destructor side effects
This commit is contained in:
		
							parent
							
								
									b2531310b4
								
							
						
					
					
						commit
						996ca25a2e
					
				
					 3 changed files with 23 additions and 0 deletions
				
			
		|  | @ -629,6 +629,7 @@ void System::serialize(Archive& ar, const unsigned int file_version) { | ||||||
| 
 | 
 | ||||||
|     // This needs to be set from somewhere - might as well be here!
 |     // This needs to be set from somewhere - might as well be here!
 | ||||||
|     if (Archive::is_loading::value) { |     if (Archive::is_loading::value) { | ||||||
|  |         timing->UnlockEventQueue(); | ||||||
|         Service::GSP::SetGlobalModule(*this); |         Service::GSP::SetGlobalModule(*this); | ||||||
|         memory->SetDSP(*dsp_core); |         memory->SetDSP(*dsp_core); | ||||||
|         cheat_engine->Connect(); |         cheat_engine->Connect(); | ||||||
|  |  | ||||||
|  | @ -49,6 +49,10 @@ TimingEventType* Timing::RegisterEvent(const std::string& name, TimedCallback ca | ||||||
| 
 | 
 | ||||||
| void Timing::ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_type, u64 userdata, | void Timing::ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_type, u64 userdata, | ||||||
|                            std::size_t core_id) { |                            std::size_t core_id) { | ||||||
|  |     if (event_queue_locked) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ASSERT(event_type != nullptr); |     ASSERT(event_type != nullptr); | ||||||
|     Timing::Timer* timer = nullptr; |     Timing::Timer* timer = nullptr; | ||||||
|     if (core_id == std::numeric_limits<std::size_t>::max()) { |     if (core_id == std::numeric_limits<std::size_t>::max()) { | ||||||
|  | @ -74,6 +78,9 @@ void Timing::ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Timing::UnscheduleEvent(const TimingEventType* event_type, u64 userdata) { | void Timing::UnscheduleEvent(const TimingEventType* event_type, u64 userdata) { | ||||||
|  |     if (event_queue_locked) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     for (auto timer : timers) { |     for (auto timer : timers) { | ||||||
|         auto itr = std::remove_if( |         auto itr = std::remove_if( | ||||||
|             timer->event_queue.begin(), timer->event_queue.end(), |             timer->event_queue.begin(), timer->event_queue.end(), | ||||||
|  | @ -89,6 +96,9 @@ void Timing::UnscheduleEvent(const TimingEventType* event_type, u64 userdata) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Timing::RemoveEvent(const TimingEventType* event_type) { | void Timing::RemoveEvent(const TimingEventType* event_type) { | ||||||
|  |     if (event_queue_locked) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     for (auto timer : timers) { |     for (auto timer : timers) { | ||||||
|         auto itr = std::remove_if(timer->event_queue.begin(), timer->event_queue.end(), |         auto itr = std::remove_if(timer->event_queue.begin(), timer->event_queue.end(), | ||||||
|                                   [&](const Event& e) { return e.type == event_type; }); |                                   [&](const Event& e) { return e.type == event_type; }); | ||||||
|  |  | ||||||
|  | @ -280,6 +280,11 @@ public: | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<Timer> GetTimer(std::size_t cpu_id); |     std::shared_ptr<Timer> GetTimer(std::size_t cpu_id); | ||||||
| 
 | 
 | ||||||
|  |     // Used after deserializing to unprotect the event queue.
 | ||||||
|  |     void UnlockEventQueue() { | ||||||
|  |         event_queue_locked = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     // unordered_map stores each element separately as a linked list node so pointers to
 |     // unordered_map stores each element separately as a linked list node so pointers to
 | ||||||
|     // elements remain stable regardless of rehashes/resizing.
 |     // elements remain stable regardless of rehashes/resizing.
 | ||||||
|  | @ -292,6 +297,10 @@ private: | ||||||
|     // under/overclocking the guest cpu
 |     // under/overclocking the guest cpu
 | ||||||
|     double cpu_clock_scale = 1.0; |     double cpu_clock_scale = 1.0; | ||||||
| 
 | 
 | ||||||
|  |     // When true, the event queue can't be modified. Used while deserializing to workaround
 | ||||||
|  |     // destructor side effects.
 | ||||||
|  |     bool event_queue_locked = false; | ||||||
|  | 
 | ||||||
|     template <class Archive> |     template <class Archive> | ||||||
|     void serialize(Archive& ar, const unsigned int file_version) { |     void serialize(Archive& ar, const unsigned int file_version) { | ||||||
|         // event_types set during initialization of other things
 |         // event_types set during initialization of other things
 | ||||||
|  | @ -303,6 +312,9 @@ private: | ||||||
|         } else { |         } else { | ||||||
|             ar& current_timer; |             ar& current_timer; | ||||||
|         } |         } | ||||||
|  |         if (Archive::is_loading::value) { | ||||||
|  |             event_queue_locked = true; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     friend class boost::serialization::access; |     friend class boost::serialization::access; | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue