summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/src/core_timing.cpp826
-rw-r--r--src/core/src/core_timing.h116
2 files changed, 455 insertions, 487 deletions
diff --git a/src/core/src/core_timing.cpp b/src/core/src/core_timing.cpp
index 73dd9b549..78bbaafe2 100644
--- a/src/core/src/core_timing.cpp
+++ b/src/core/src/core_timing.cpp
@@ -1,20 +1,6 @@
1// Copyright (c) 2012- PPSSPP Project / Dolphin Project. 1// Copyright 2013 Dolphin Emulator Project
2 2// Licensed under GPLv2
3// This program is free software: you can redistribute it and/or modify 3// Refer to the license.txt file included.
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, version 2.0 or later versions.
6
7// This program is distributed in the hope that it will be useful,
8// but WITHOUT ANY WARRANTY; without even the implied warranty of
9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10// GNU General Public License 2.0 for more details.
11
12// A copy of the GPL 2.0 should have been included with the program.
13// If not, see http://www.gnu.org/licenses/
14
15// Official git repository and contact information can be found at
16// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18 4
19#include <vector> 5#include <vector>
20#include <cstdio> 6#include <cstdio>
@@ -26,8 +12,6 @@
26#include "core.h" 12#include "core.h"
27#include "chunk_file.h" 13#include "chunk_file.h"
28 14
29//#include "HLE/sceKernelThread.h"
30
31int g_clock_rate_arm11 = 268123480; 15int g_clock_rate_arm11 = 268123480;
32 16
33// is this really necessary? 17// is this really necessary?
@@ -39,23 +23,23 @@ namespace CoreTiming
39 23
40struct EventType 24struct EventType
41{ 25{
42 EventType() {} 26 EventType() {}
43 27
44 EventType(TimedCallback cb, const char *n) 28 EventType(TimedCallback cb, const char *n)
45 : callback(cb), name(n) {} 29 : callback(cb), name(n) {}
46 30
47 TimedCallback callback; 31 TimedCallback callback;
48 const char *name; 32 const char *name;
49}; 33};
50 34
51std::vector<EventType> event_types; 35std::vector<EventType> event_types;
52 36
53struct BaseEvent 37struct BaseEvent
54{ 38{
55 s64 time; 39 s64 time;
56 u64 userdata; 40 u64 userdata;
57 int type; 41 int type;
58// Event *next; 42 // Event *next;
59}; 43};
60 44
61typedef LinkedListItem<BaseEvent> Event; 45typedef LinkedListItem<BaseEvent> Event;
@@ -81,123 +65,123 @@ s64 idledCycles;
81static std::recursive_mutex externalEventSection; 65static std::recursive_mutex externalEventSection;
82 66
83// Warning: not included in save state. 67// Warning: not included in save state.
84void (*advanceCallback)(int cyclesExecuted) = NULL; 68void(*advanceCallback)(int cyclesExecuted) = NULL;
85 69
86void SetClockFrequencyMHz(int cpuMhz) 70void SetClockFrequencyMHz(int cpuMhz)
87{ 71{
88 g_clock_rate_arm11 = cpuMhz * 1000000; 72 g_clock_rate_arm11 = cpuMhz * 1000000;
89 // TODO: Rescale times of scheduled events? 73 // TODO: Rescale times of scheduled events?
90} 74}
91 75
92int GetClockFrequencyMHz() 76int GetClockFrequencyMHz()
93{ 77{
94 return g_clock_rate_arm11 / 1000000; 78 return g_clock_rate_arm11 / 1000000;
95} 79}
96 80
97 81
98Event* GetNewEvent() 82Event* GetNewEvent()
99{ 83{
100 if(!eventPool) 84 if (!eventPool)
101 return new Event; 85 return new Event;
102 86
103 Event* ev = eventPool; 87 Event* ev = eventPool;
104 eventPool = ev->next; 88 eventPool = ev->next;
105 return ev; 89 return ev;
106} 90}
107 91
108Event* GetNewTsEvent() 92Event* GetNewTsEvent()
109{ 93{
110 allocatedTsEvents++; 94 allocatedTsEvents++;
111 95
112 if(!eventTsPool) 96 if (!eventTsPool)
113 return new Event; 97 return new Event;
114 98
115 Event* ev = eventTsPool; 99 Event* ev = eventTsPool;
116 eventTsPool = ev->next; 100 eventTsPool = ev->next;
117 return ev; 101 return ev;
118} 102}
119 103
120void FreeEvent(Event* ev) 104void FreeEvent(Event* ev)
121{ 105{
122 ev->next = eventPool; 106 ev->next = eventPool;
123 eventPool = ev; 107 eventPool = ev;
124} 108}
125 109
126void FreeTsEvent(Event* ev) 110void FreeTsEvent(Event* ev)
127{ 111{
128 ev->next = eventTsPool; 112 ev->next = eventTsPool;
129 eventTsPool = ev; 113 eventTsPool = ev;
130 allocatedTsEvents--; 114 allocatedTsEvents--;
131} 115}
132 116
133int RegisterEvent(const char *name, TimedCallback callback) 117int RegisterEvent(const char *name, TimedCallback callback)
134{ 118{
135 event_types.push_back(EventType(callback, name)); 119 event_types.push_back(EventType(callback, name));
136 return (int)event_types.size() - 1; 120 return (int)event_types.size() - 1;
137} 121}
138 122
139void AntiCrashCallback(u64 userdata, int cyclesLate) 123void AntiCrashCallback(u64 userdata, int cyclesLate)
140{ 124{
141 ERROR_LOG(TIME, "Savestate broken: an unregistered event was called."); 125 ERROR_LOG(TIME, "Savestate broken: an unregistered event was called.");
142 Core::Halt("invalid timing events"); 126 Core::Halt("invalid timing events");
143} 127}
144 128
145void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback) 129void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback)
146{ 130{
147 if (event_type >= (int) event_types.size()) 131 if (event_type >= (int)event_types.size())
148 event_types.resize(event_type + 1, EventType(AntiCrashCallback, "INVALID EVENT")); 132 event_types.resize(event_type + 1, EventType(AntiCrashCallback, "INVALID EVENT"));
149 133
150 event_types[event_type] = EventType(callback, name); 134 event_types[event_type] = EventType(callback, name);
151} 135}
152 136
153void UnregisterAllEvents() 137void UnregisterAllEvents()
154{ 138{
155 if (first) 139 if (first)
156 PanicAlert("Cannot unregister events with events pending"); 140 PanicAlert("Cannot unregister events with events pending");
157 event_types.clear(); 141 event_types.clear();
158} 142}
159 143
160void Init() 144void Init()
161{ 145{
162 //currentMIPS->downcount = INITIAL_SLICE_LENGTH; 146 //currentMIPS->downcount = INITIAL_SLICE_LENGTH;
163 //slicelength = INITIAL_SLICE_LENGTH; 147 //slicelength = INITIAL_SLICE_LENGTH;
164 globalTimer = 0; 148 globalTimer = 0;
165 idledCycles = 0; 149 idledCycles = 0;
166 hasTsEvents = 0; 150 hasTsEvents = 0;
167} 151}
168 152
169void Shutdown() 153void Shutdown()
170{ 154{
171 MoveEvents(); 155 MoveEvents();
172 ClearPendingEvents(); 156 ClearPendingEvents();
173 UnregisterAllEvents(); 157 UnregisterAllEvents();
174 158
175 while(eventPool) 159 while (eventPool)
176 { 160 {
177 Event *ev = eventPool; 161 Event *ev = eventPool;
178 eventPool = ev->next; 162 eventPool = ev->next;
179 delete ev; 163 delete ev;
180 } 164 }
181 165
182 std::lock_guard<std::recursive_mutex> lk(externalEventSection); 166 std::lock_guard<std::recursive_mutex> lk(externalEventSection);
183 while(eventTsPool) 167 while (eventTsPool)
184 { 168 {
185 Event *ev = eventTsPool; 169 Event *ev = eventTsPool;
186 eventTsPool = ev->next; 170 eventTsPool = ev->next;
187 delete ev; 171 delete ev;
188 } 172 }
189} 173}
190 174
191u64 GetTicks() 175u64 GetTicks()
192{ 176{
193 ERROR_LOG(TIME, "Unimplemented function!"); 177 ERROR_LOG(TIME, "Unimplemented function!");
194 return 0; 178 return 0;
195 //return (u64)globalTimer + slicelength - currentMIPS->downcount; 179 //return (u64)globalTimer + slicelength - currentMIPS->downcount;
196} 180}
197 181
198u64 GetIdleTicks() 182u64 GetIdleTicks()
199{ 183{
200 return (u64)idledCycles; 184 return (u64)idledCycles;
201} 185}
202 186
203 187
@@ -205,60 +189,60 @@ u64 GetIdleTicks()
205// schedule things to be executed on the main thread. 189// schedule things to be executed on the main thread.
206void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata) 190void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata)
207{ 191{
208 std::lock_guard<std::recursive_mutex> lk(externalEventSection); 192 std::lock_guard<std::recursive_mutex> lk(externalEventSection);
209 Event *ne = GetNewTsEvent(); 193 Event *ne = GetNewTsEvent();
210 ne->time = GetTicks() + cyclesIntoFuture; 194 ne->time = GetTicks() + cyclesIntoFuture;
211 ne->type = event_type; 195 ne->type = event_type;
212 ne->next = 0; 196 ne->next = 0;
213 ne->userdata = userdata; 197 ne->userdata = userdata;
214 if(!tsFirst) 198 if (!tsFirst)
215 tsFirst = ne; 199 tsFirst = ne;
216 if(tsLast) 200 if (tsLast)
217 tsLast->next = ne; 201 tsLast->next = ne;
218 tsLast = ne; 202 tsLast = ne;
219 203
220 Common::AtomicStoreRelease(hasTsEvents, 1); 204 Common::AtomicStoreRelease(hasTsEvents, 1);
221} 205}
222 206
223// Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread 207// Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread
224// in which case the event will get handled immediately, before returning. 208// in which case the event will get handled immediately, before returning.
225void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) 209void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata)
226{ 210{
227 if(false) //Core::IsCPUThread()) 211 if (false) //Core::IsCPUThread())
228 { 212 {
229 std::lock_guard<std::recursive_mutex> lk(externalEventSection); 213 std::lock_guard<std::recursive_mutex> lk(externalEventSection);
230 event_types[event_type].callback(userdata, 0); 214 event_types[event_type].callback(userdata, 0);
231 } 215 }
232 else 216 else
233 ScheduleEvent_Threadsafe(0, event_type, userdata); 217 ScheduleEvent_Threadsafe(0, event_type, userdata);
234} 218}
235 219
236void ClearPendingEvents() 220void ClearPendingEvents()
237{ 221{
238 while (first) 222 while (first)
239 { 223 {
240 Event *e = first->next; 224 Event *e = first->next;
241 FreeEvent(first); 225 FreeEvent(first);
242 first = e; 226 first = e;
243 } 227 }
244} 228}
245 229
246void AddEventToQueue(Event* ne) 230void AddEventToQueue(Event* ne)
247{ 231{
248 Event* prev = NULL; 232 Event* prev = NULL;
249 Event** pNext = &first; 233 Event** pNext = &first;
250 for(;;) 234 for (;;)
251 { 235 {
252 Event*& next = *pNext; 236 Event*& next = *pNext;
253 if(!next || ne->time < next->time) 237 if (!next || ne->time < next->time)
254 { 238 {
255 ne->next = next; 239 ne->next = next;
256 next = ne; 240 next = ne;
257 break; 241 break;
258 } 242 }
259 prev = next; 243 prev = next;
260 pNext = &prev->next; 244 pNext = &prev->next;
261 } 245 }
262} 246}
263 247
264// This must be run ONLY from within the cpu thread 248// This must be run ONLY from within the cpu thread
@@ -266,374 +250,374 @@ void AddEventToQueue(Event* ne)
266// than Advance 250// than Advance
267void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata) 251void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata)
268{ 252{
269 Event *ne = GetNewEvent(); 253 Event *ne = GetNewEvent();
270 ne->userdata = userdata; 254 ne->userdata = userdata;
271 ne->type = event_type; 255 ne->type = event_type;
272 ne->time = GetTicks() + cyclesIntoFuture; 256 ne->time = GetTicks() + cyclesIntoFuture;
273 AddEventToQueue(ne); 257 AddEventToQueue(ne);
274} 258}
275 259
276// Returns cycles left in timer. 260// Returns cycles left in timer.
277s64 UnscheduleEvent(int event_type, u64 userdata) 261s64 UnscheduleEvent(int event_type, u64 userdata)
278{ 262{
279 s64 result = 0; 263 s64 result = 0;
280 if (!first) 264 if (!first)
281 return result; 265 return result;
282 while(first) 266 while (first)
283 { 267 {
284 if (first->type == event_type && first->userdata == userdata) 268 if (first->type == event_type && first->userdata == userdata)
285 { 269 {
286 result = first->time - globalTimer; 270 result = first->time - globalTimer;
287 271
288 Event *next = first->next; 272 Event *next = first->next;
289 FreeEvent(first); 273 FreeEvent(first);
290 first = next; 274 first = next;
291 } 275 }
292 else 276 else
293 { 277 {
294 break; 278 break;
295 } 279 }
296 } 280 }
297 if (!first) 281 if (!first)
298 return result; 282 return result;
299 Event *prev = first; 283 Event *prev = first;
300 Event *ptr = prev->next; 284 Event *ptr = prev->next;
301 while (ptr) 285 while (ptr)
302 { 286 {
303 if (ptr->type == event_type && ptr->userdata == userdata) 287 if (ptr->type == event_type && ptr->userdata == userdata)
304 { 288 {
305 result = ptr->time - globalTimer; 289 result = ptr->time - globalTimer;
306 290
307 prev->next = ptr->next; 291 prev->next = ptr->next;
308 FreeEvent(ptr); 292 FreeEvent(ptr);
309 ptr = prev->next; 293 ptr = prev->next;
310 } 294 }
311 else 295 else
312 { 296 {
313 prev = ptr; 297 prev = ptr;
314 ptr = ptr->next; 298 ptr = ptr->next;
315 } 299 }
316 } 300 }
317 301
318 return result; 302 return result;
319} 303}
320 304
321s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata) 305s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata)
322{ 306{
323 s64 result = 0; 307 s64 result = 0;
324 std::lock_guard<std::recursive_mutex> lk(externalEventSection); 308 std::lock_guard<std::recursive_mutex> lk(externalEventSection);
325 if (!tsFirst) 309 if (!tsFirst)
326 return result; 310 return result;
327 while(tsFirst) 311 while (tsFirst)
328 { 312 {
329 if (tsFirst->type == event_type && tsFirst->userdata == userdata) 313 if (tsFirst->type == event_type && tsFirst->userdata == userdata)
330 { 314 {
331 result = tsFirst->time - globalTimer; 315 result = tsFirst->time - globalTimer;
332 316
333 Event *next = tsFirst->next; 317 Event *next = tsFirst->next;
334 FreeTsEvent(tsFirst); 318 FreeTsEvent(tsFirst);
335 tsFirst = next; 319 tsFirst = next;
336 } 320 }
337 else 321 else
338 { 322 {
339 break; 323 break;
340 } 324 }
341 } 325 }
342 if (!tsFirst) 326 if (!tsFirst)
343 { 327 {
344 tsLast = NULL; 328 tsLast = NULL;
345 return result; 329 return result;
346 } 330 }
347 331
348 Event *prev = tsFirst; 332 Event *prev = tsFirst;
349 Event *ptr = prev->next; 333 Event *ptr = prev->next;
350 while (ptr) 334 while (ptr)
351 { 335 {
352 if (ptr->type == event_type && ptr->userdata == userdata) 336 if (ptr->type == event_type && ptr->userdata == userdata)
353 { 337 {
354 result = ptr->time - globalTimer; 338 result = ptr->time - globalTimer;
355 339
356 prev->next = ptr->next; 340 prev->next = ptr->next;
357 if (ptr == tsLast) 341 if (ptr == tsLast)
358 tsLast = prev; 342 tsLast = prev;
359 FreeTsEvent(ptr); 343 FreeTsEvent(ptr);
360 ptr = prev->next; 344 ptr = prev->next;
361 } 345 }
362 else 346 else
363 { 347 {
364 prev = ptr; 348 prev = ptr;
365 ptr = ptr->next; 349 ptr = ptr->next;
366 } 350 }
367 } 351 }
368 352
369 return result; 353 return result;
370} 354}
371 355
372// Warning: not included in save state. 356// Warning: not included in save state.
373void RegisterAdvanceCallback(void (*callback)(int cyclesExecuted)) 357void RegisterAdvanceCallback(void(*callback)(int cyclesExecuted))
374{ 358{
375 advanceCallback = callback; 359 advanceCallback = callback;
376} 360}
377 361
378bool IsScheduled(int event_type) 362bool IsScheduled(int event_type)
379{ 363{
380 if (!first) 364 if (!first)
381 return false; 365 return false;
382 Event *e = first; 366 Event *e = first;
383 while (e) { 367 while (e) {
384 if (e->type == event_type) 368 if (e->type == event_type)
385 return true; 369 return true;
386 e = e->next; 370 e = e->next;
387 } 371 }
388 return false; 372 return false;
389} 373}
390 374
391void RemoveEvent(int event_type) 375void RemoveEvent(int event_type)
392{ 376{
393 if (!first) 377 if (!first)
394 return; 378 return;
395 while(first) 379 while (first)
396 { 380 {
397 if (first->type == event_type) 381 if (first->type == event_type)
398 { 382 {
399 Event *next = first->next; 383 Event *next = first->next;
400 FreeEvent(first); 384 FreeEvent(first);
401 first = next; 385 first = next;
402 } 386 }
403 else 387 else
404 { 388 {
405 break; 389 break;
406 } 390 }
407 } 391 }
408 if (!first) 392 if (!first)
409 return; 393 return;
410 Event *prev = first; 394 Event *prev = first;
411 Event *ptr = prev->next; 395 Event *ptr = prev->next;
412 while (ptr) 396 while (ptr)
413 { 397 {
414 if (ptr->type == event_type) 398 if (ptr->type == event_type)
415 { 399 {
416 prev->next = ptr->next; 400 prev->next = ptr->next;
417 FreeEvent(ptr); 401 FreeEvent(ptr);
418 ptr = prev->next; 402 ptr = prev->next;
419 } 403 }
420 else 404 else
421 { 405 {
422 prev = ptr; 406 prev = ptr;
423 ptr = ptr->next; 407 ptr = ptr->next;
424 } 408 }
425 } 409 }
426} 410}
427 411
428void RemoveThreadsafeEvent(int event_type) 412void RemoveThreadsafeEvent(int event_type)
429{ 413{
430 std::lock_guard<std::recursive_mutex> lk(externalEventSection); 414 std::lock_guard<std::recursive_mutex> lk(externalEventSection);
431 if (!tsFirst) 415 if (!tsFirst)
432 { 416 {
433 return; 417 return;
434 } 418 }
435 while(tsFirst) 419 while (tsFirst)
436 { 420 {
437 if (tsFirst->type == event_type) 421 if (tsFirst->type == event_type)
438 { 422 {
439 Event *next = tsFirst->next; 423 Event *next = tsFirst->next;
440 FreeTsEvent(tsFirst); 424 FreeTsEvent(tsFirst);
441 tsFirst = next; 425 tsFirst = next;
442 } 426 }
443 else 427 else
444 { 428 {
445 break; 429 break;
446 } 430 }
447 } 431 }
448 if (!tsFirst) 432 if (!tsFirst)
449 { 433 {
450 tsLast = NULL; 434 tsLast = NULL;
451 return; 435 return;
452 } 436 }
453 Event *prev = tsFirst; 437 Event *prev = tsFirst;
454 Event *ptr = prev->next; 438 Event *ptr = prev->next;
455 while (ptr) 439 while (ptr)
456 { 440 {
457 if (ptr->type == event_type) 441 if (ptr->type == event_type)
458 { 442 {
459 prev->next = ptr->next; 443 prev->next = ptr->next;
460 if (ptr == tsLast) 444 if (ptr == tsLast)
461 tsLast = prev; 445 tsLast = prev;
462 FreeTsEvent(ptr); 446 FreeTsEvent(ptr);
463 ptr = prev->next; 447 ptr = prev->next;
464 } 448 }
465 else 449 else
466 { 450 {
467 prev = ptr; 451 prev = ptr;
468 ptr = ptr->next; 452 ptr = ptr->next;
469 } 453 }
470 } 454 }
471} 455}
472 456
473void RemoveAllEvents(int event_type) 457void RemoveAllEvents(int event_type)
474{ 458{
475 RemoveThreadsafeEvent(event_type); 459 RemoveThreadsafeEvent(event_type);
476 RemoveEvent(event_type); 460 RemoveEvent(event_type);
477} 461}
478 462
479//This raise only the events required while the fifo is processing data 463//This raise only the events required while the fifo is processing data
480void ProcessFifoWaitEvents() 464void ProcessFifoWaitEvents()
481{ 465{
482 while (first) 466 while (first)
483 { 467 {
484 if (first->time <= globalTimer) 468 if (first->time <= globalTimer)
485 { 469 {
486// LOG(TIMER, "[Scheduler] %s (%lld, %lld) ", 470 // LOG(TIMER, "[Scheduler] %s (%lld, %lld) ",
487// first->name ? first->name : "?", (u64)globalTimer, (u64)first->time); 471 // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
488 Event* evt = first; 472 Event* evt = first;
489 first = first->next; 473 first = first->next;
490 event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time)); 474 event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time));
491 FreeEvent(evt); 475 FreeEvent(evt);
492 } 476 }
493 else 477 else
494 { 478 {
495 break; 479 break;
496 } 480 }
497 } 481 }
498} 482}
499 483
500void MoveEvents() 484void MoveEvents()
501{ 485{
502 Common::AtomicStoreRelease(hasTsEvents, 0); 486 Common::AtomicStoreRelease(hasTsEvents, 0);
503 487
504 std::lock_guard<std::recursive_mutex> lk(externalEventSection); 488 std::lock_guard<std::recursive_mutex> lk(externalEventSection);
505 // Move events from async queue into main queue 489 // Move events from async queue into main queue
506 while (tsFirst) 490 while (tsFirst)
507 { 491 {
508 Event *next = tsFirst->next; 492 Event *next = tsFirst->next;
509 AddEventToQueue(tsFirst); 493 AddEventToQueue(tsFirst);
510 tsFirst = next; 494 tsFirst = next;
511 } 495 }
512 tsLast = NULL; 496 tsLast = NULL;
513 497
514 // Move free events to threadsafe pool 498 // Move free events to threadsafe pool
515 while(allocatedTsEvents > 0 && eventPool) 499 while (allocatedTsEvents > 0 && eventPool)
516 { 500 {
517 Event *ev = eventPool; 501 Event *ev = eventPool;
518 eventPool = ev->next; 502 eventPool = ev->next;
519 ev->next = eventTsPool; 503 ev->next = eventTsPool;
520 eventTsPool = ev; 504 eventTsPool = ev;
521 allocatedTsEvents--; 505 allocatedTsEvents--;
522 } 506 }
523} 507}
524 508
525void Advance() 509void Advance()
526{ 510{
527 ERROR_LOG(TIME, "Unimplemented function!"); 511 ERROR_LOG(TIME, "Unimplemented function!");
528 //int cyclesExecuted = slicelength - currentMIPS->downcount; 512 //int cyclesExecuted = slicelength - currentMIPS->downcount;
529 //globalTimer += cyclesExecuted; 513 //globalTimer += cyclesExecuted;
530 //currentMIPS->downcount = slicelength; 514 //currentMIPS->downcount = slicelength;
531 515
532 //if (Common::AtomicLoadAcquire(hasTsEvents)) 516 //if (Common::AtomicLoadAcquire(hasTsEvents))
533 // MoveEvents(); 517 // MoveEvents();
534 //ProcessFifoWaitEvents(); 518 //ProcessFifoWaitEvents();
535 519
536 //if (!first) 520 //if (!first)
537 //{ 521 //{
538 // // WARN_LOG(TIMER, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000"); 522 // // WARN_LOG(TIMER, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000");
539 // currentMIPS->downcount += 10000; 523 // currentMIPS->downcount += 10000;
540 //} 524 //}
541 //else 525 //else
542 //{ 526 //{
543 // slicelength = (int)(first->time - globalTimer); 527 // slicelength = (int)(first->time - globalTimer);
544 // if (slicelength > MAX_SLICE_LENGTH) 528 // if (slicelength > MAX_SLICE_LENGTH)
545 // slicelength = MAX_SLICE_LENGTH; 529 // slicelength = MAX_SLICE_LENGTH;
546 // currentMIPS->downcount = slicelength; 530 // currentMIPS->downcount = slicelength;
547 //} 531 //}
548 //if (advanceCallback) 532 //if (advanceCallback)
549 // advanceCallback(cyclesExecuted); 533 // advanceCallback(cyclesExecuted);
550} 534}
551 535
552void LogPendingEvents() 536void LogPendingEvents()
553{ 537{
554 Event *ptr = first; 538 Event *ptr = first;
555 while (ptr) 539 while (ptr)
556 { 540 {
557 //INFO_LOG(TIMER, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, ptr->time, ptr->type); 541 //INFO_LOG(TIMER, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, ptr->time, ptr->type);
558 ptr = ptr->next; 542 ptr = ptr->next;
559 } 543 }
560} 544}
561 545
562void Idle(int maxIdle) 546void Idle(int maxIdle)
563{ 547{
564 ERROR_LOG(TIME, "Unimplemented function!"); 548 ERROR_LOG(TIME, "Unimplemented function!");
565 //int cyclesDown = currentMIPS->downcount; 549 //int cyclesDown = currentMIPS->downcount;
566 //if (maxIdle != 0 && cyclesDown > maxIdle) 550 //if (maxIdle != 0 && cyclesDown > maxIdle)
567 // cyclesDown = maxIdle; 551 // cyclesDown = maxIdle;
568 552
569 //if (first && cyclesDown > 0) 553 //if (first && cyclesDown > 0)
570 //{ 554 //{
571 // int cyclesExecuted = slicelength - currentMIPS->downcount; 555 // int cyclesExecuted = slicelength - currentMIPS->downcount;
572 // int cyclesNextEvent = (int) (first->time - globalTimer); 556 // int cyclesNextEvent = (int) (first->time - globalTimer);
573 557
574 // if (cyclesNextEvent < cyclesExecuted + cyclesDown) 558 // if (cyclesNextEvent < cyclesExecuted + cyclesDown)
575 // { 559 // {
576 // cyclesDown = cyclesNextEvent - cyclesExecuted; 560 // cyclesDown = cyclesNextEvent - cyclesExecuted;
577 // // Now, now... no time machines, please. 561 // // Now, now... no time machines, please.
578 // if (cyclesDown < 0) 562 // if (cyclesDown < 0)
579 // cyclesDown = 0; 563 // cyclesDown = 0;
580 // } 564 // }
581 //} 565 //}
582 566
583 //INFO_LOG(TIME, "Idle for %i cycles! (%f ms)", cyclesDown, cyclesDown / (float)(g_clock_rate_arm11 * 0.001f)); 567 //INFO_LOG(TIME, "Idle for %i cycles! (%f ms)", cyclesDown, cyclesDown / (float)(g_clock_rate_arm11 * 0.001f));
584 568
585 //idledCycles += cyclesDown; 569 //idledCycles += cyclesDown;
586 //currentMIPS->downcount -= cyclesDown; 570 //currentMIPS->downcount -= cyclesDown;
587 //if (currentMIPS->downcount == 0) 571 //if (currentMIPS->downcount == 0)
588 // currentMIPS->downcount = -1; 572 // currentMIPS->downcount = -1;
589} 573}
590 574
591std::string GetScheduledEventsSummary() 575std::string GetScheduledEventsSummary()
592{ 576{
593 Event *ptr = first; 577 Event *ptr = first;
594 std::string text = "Scheduled events\n"; 578 std::string text = "Scheduled events\n";
595 text.reserve(1000); 579 text.reserve(1000);
596 while (ptr) 580 while (ptr)
597 { 581 {
598 unsigned int t = ptr->type; 582 unsigned int t = ptr->type;
599 if (t >= event_types.size()) 583 if (t >= event_types.size())
600 PanicAlert("Invalid event type"); // %i", t); 584 PanicAlert("Invalid event type"); // %i", t);
601 const char *name = event_types[ptr->type].name; 585 const char *name = event_types[ptr->type].name;
602 if (!name) 586 if (!name)
603 name = "[unknown]"; 587 name = "[unknown]";
604 char temp[512]; 588 char temp[512];
605 sprintf(temp, "%s : %i %08x%08x\n", name, (int)ptr->time, (u32)(ptr->userdata >> 32), (u32)(ptr->userdata)); 589 sprintf(temp, "%s : %i %08x%08x\n", name, (int)ptr->time, (u32)(ptr->userdata >> 32), (u32)(ptr->userdata));
606 text += temp; 590 text += temp;
607 ptr = ptr->next; 591 ptr = ptr->next;
608 } 592 }
609 return text; 593 return text;
610} 594}
611 595
612void Event_DoState(PointerWrap &p, BaseEvent *ev) 596void Event_DoState(PointerWrap &p, BaseEvent *ev)
613{ 597{
614 p.Do(*ev); 598 p.Do(*ev);
615} 599}
616 600
617void DoState(PointerWrap &p) 601void DoState(PointerWrap &p)
618{ 602{
619 std::lock_guard<std::recursive_mutex> lk(externalEventSection); 603 std::lock_guard<std::recursive_mutex> lk(externalEventSection);
620 604
621 auto s = p.Section("CoreTiming", 1); 605 auto s = p.Section("CoreTiming", 1);
622 if (!s) 606 if (!s)
623 return; 607 return;
624 608
625 int n = (int) event_types.size(); 609 int n = (int)event_types.size();
626 p.Do(n); 610 p.Do(n);
627 // These (should) be filled in later by the modules. 611 // These (should) be filled in later by the modules.
628 event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT")); 612 event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT"));
629 613
630 p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **) NULL); 614 p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **)NULL);
631 p.DoLinkedList<BaseEvent, GetNewTsEvent, FreeTsEvent, Event_DoState>(tsFirst, &tsLast); 615 p.DoLinkedList<BaseEvent, GetNewTsEvent, FreeTsEvent, Event_DoState>(tsFirst, &tsLast);
632 616
633 p.Do(g_clock_rate_arm11); 617 p.Do(g_clock_rate_arm11);
634 p.Do(slicelength); 618 p.Do(slicelength);
635 p.Do(globalTimer); 619 p.Do(globalTimer);
636 p.Do(idledCycles); 620 p.Do(idledCycles);
637} 621}
638 622
639} // namespace 623} // namespace
diff --git a/src/core/src/core_timing.h b/src/core/src/core_timing.h
index 1ef17f6f8..b62acea6c 100644
--- a/src/core/src/core_timing.h
+++ b/src/core/src/core_timing.h
@@ -1,22 +1,8 @@
1// Copyright (c) 2012- PPSSPP Project / Dolphin Project. 1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
2 4
3// This program is free software: you can redistribute it and/or modify 5#pragma once
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, version 2.0 or later versions.
6
7// This program is distributed in the hope that it will be useful,
8// but WITHOUT ANY WARRANTY; without even the implied warranty of
9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10// GNU General Public License 2.0 for more details.
11
12// A copy of the GPL 2.0 should have been included with the program.
13// If not, see http://www.gnu.org/licenses/
14
15// Official git repository and contact information can be found at
16// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18#ifndef CORE_CORE_TIMING_H_
19#define CORE_CORE_TIMING_H_
20 6
21// This is a system to schedule events into the emulated machine's future. Time is measured 7// This is a system to schedule events into the emulated machine's future. Time is measured
22// in main CPU clock cycles. 8// in main CPU clock cycles.
@@ -38,88 +24,86 @@ class PointerWrap;
38extern int g_clock_rate_arm11; 24extern int g_clock_rate_arm11;
39 25
40inline s64 msToCycles(int ms) { 26inline s64 msToCycles(int ms) {
41 return g_clock_rate_arm11 / 1000 * ms; 27 return g_clock_rate_arm11 / 1000 * ms;
42} 28}
43 29
44inline s64 msToCycles(float ms) { 30inline s64 msToCycles(float ms) {
45 return (s64)(g_clock_rate_arm11 * ms * (0.001f)); 31 return (s64)(g_clock_rate_arm11 * ms * (0.001f));
46} 32}
47 33
48inline s64 msToCycles(double ms) { 34inline s64 msToCycles(double ms) {
49 return (s64)(g_clock_rate_arm11 * ms * (0.001)); 35 return (s64)(g_clock_rate_arm11 * ms * (0.001));
50} 36}
51 37
52inline s64 usToCycles(float us) { 38inline s64 usToCycles(float us) {
53 return (s64)(g_clock_rate_arm11 * us * (0.000001f)); 39 return (s64)(g_clock_rate_arm11 * us * (0.000001f));
54} 40}
55 41
56inline s64 usToCycles(int us) { 42inline s64 usToCycles(int us) {
57 return (g_clock_rate_arm11 / 1000000 * (s64)us); 43 return (g_clock_rate_arm11 / 1000000 * (s64)us);
58} 44}
59 45
60inline s64 usToCycles(s64 us) { 46inline s64 usToCycles(s64 us) {
61 return (g_clock_rate_arm11 / 1000000 * us); 47 return (g_clock_rate_arm11 / 1000000 * us);
62} 48}
63 49
64inline s64 usToCycles(u64 us) { 50inline s64 usToCycles(u64 us) {
65 return (s64)(g_clock_rate_arm11 / 1000000 * us); 51 return (s64)(g_clock_rate_arm11 / 1000000 * us);
66} 52}
67 53
68inline s64 cyclesToUs(s64 cycles) { 54inline s64 cyclesToUs(s64 cycles) {
69 return cycles / (g_clock_rate_arm11 / 1000000); 55 return cycles / (g_clock_rate_arm11 / 1000000);
70} 56}
71 57
72namespace CoreTiming 58namespace CoreTiming {
73{
74 void Init();
75 void Shutdown();
76 59
77 typedef void (*TimedCallback)(u64 userdata, int cyclesLate); 60void Init();
61void Shutdown();
78 62
79 u64 GetTicks(); 63typedef void(*TimedCallback)(u64 userdata, int cyclesLate);
80 u64 GetIdleTicks();
81 64
82 // Returns the event_type identifier. 65u64 GetTicks();
83 int RegisterEvent(const char *name, TimedCallback callback); 66u64 GetIdleTicks();
84 // For save states.
85 void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback);
86 void UnregisterAllEvents();
87 67
88 // userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, 68// Returns the event_type identifier.
89 // when we implement state saves. 69int RegisterEvent(const char *name, TimedCallback callback);
90 void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata=0); 70// For save states.
91 void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata=0); 71void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback);
92 void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata=0); 72void UnregisterAllEvents();
93 s64 UnscheduleEvent(int event_type, u64 userdata);
94 s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata);
95 73
96 void RemoveEvent(int event_type); 74// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk,
97 void RemoveThreadsafeEvent(int event_type); 75// when we implement state saves.
98 void RemoveAllEvents(int event_type); 76void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata = 0);
99 bool IsScheduled(int event_type); 77void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata = 0);
100 void Advance(); 78void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata = 0);
101 void MoveEvents(); 79s64 UnscheduleEvent(int event_type, u64 userdata);
102 void ProcessFifoWaitEvents(); 80s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata);
103 81
104 // Pretend that the main CPU has executed enough cycles to reach the next event. 82void RemoveEvent(int event_type);
105 void Idle(int maxIdle = 0); 83void RemoveThreadsafeEvent(int event_type);
84void RemoveAllEvents(int event_type);
85bool IsScheduled(int event_type);
86void Advance();
87void MoveEvents();
88void ProcessFifoWaitEvents();
106 89
107 // Clear all pending events. This should ONLY be done on exit or state load. 90// Pretend that the main CPU has executed enough cycles to reach the next event.
108 void ClearPendingEvents(); 91void Idle(int maxIdle = 0);
109 92
110 void LogPendingEvents(); 93// Clear all pending events. This should ONLY be done on exit or state load.
94void ClearPendingEvents();
111 95
112 // Warning: not included in save states. 96void LogPendingEvents();
113 void RegisterAdvanceCallback(void (*callback)(int cyclesExecuted));
114 97
115 std::string GetScheduledEventsSummary(); 98// Warning: not included in save states.
99void RegisterAdvanceCallback(void(*callback)(int cyclesExecuted));
116 100
117 void DoState(PointerWrap &p); 101std::string GetScheduledEventsSummary();
118 102
119 void SetClockFrequencyMHz(int cpuMhz); 103void DoState(PointerWrap &p);
120 int GetClockFrequencyMHz();
121 extern int slicelength;
122 104
123}; // namespace 105void SetClockFrequencyMHz(int cpuMhz);
106int GetClockFrequencyMHz();
107extern int slicelength;
124 108
125#endif // CORE_CORE_TIMING_H_ 109}; // namespace