core_timing.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. // Copyright 2013 Dolphin Emulator Project
  2. // Licensed under GPLv2
  3. // Refer to the license.txt file included.
  4. #include <vector>
  5. #include <cstdio>
  6. #include "common/msg_handler.h"
  7. #include "common/std_mutex.h"
  8. #include "common/atomic.h"
  9. #include "common/chunk_file.h"
  10. #include "core/core_timing.h"
  11. #include "core/core.h"
  12. int g_clock_rate_arm11 = 268123480;
  13. // is this really necessary?
  14. #define INITIAL_SLICE_LENGTH 20000
  15. #define MAX_SLICE_LENGTH 100000000
  16. namespace CoreTiming
  17. {
  18. struct EventType
  19. {
  20. EventType() {}
  21. EventType(TimedCallback cb, const char *n)
  22. : callback(cb), name(n) {}
  23. TimedCallback callback;
  24. const char *name;
  25. };
  26. std::vector<EventType> event_types;
  27. struct BaseEvent
  28. {
  29. s64 time;
  30. u64 userdata;
  31. int type;
  32. // Event *next;
  33. };
  34. typedef LinkedListItem<BaseEvent> Event;
  35. Event *first;
  36. Event *tsFirst;
  37. Event *tsLast;
  38. // event pools
  39. Event *eventPool = 0;
  40. Event *eventTsPool = 0;
  41. int allocatedTsEvents = 0;
  42. // Optimization to skip MoveEvents when possible.
  43. volatile u32 hasTsEvents = false;
  44. // Downcount has been moved to currentMIPS, to save a couple of clocks in every ARM JIT block
  45. // as we can already reach that structure through a register.
  46. int slicelength;
  47. MEMORY_ALIGNED16(s64) globalTimer;
  48. s64 idledCycles;
  49. static std::recursive_mutex externalEventSection;
  50. // Warning: not included in save state.
  51. void(*advanceCallback)(int cyclesExecuted) = NULL;
  52. void SetClockFrequencyMHz(int cpuMhz)
  53. {
  54. g_clock_rate_arm11 = cpuMhz * 1000000;
  55. // TODO: Rescale times of scheduled events?
  56. }
  57. int GetClockFrequencyMHz()
  58. {
  59. return g_clock_rate_arm11 / 1000000;
  60. }
  61. Event* GetNewEvent()
  62. {
  63. if (!eventPool)
  64. return new Event;
  65. Event* ev = eventPool;
  66. eventPool = ev->next;
  67. return ev;
  68. }
  69. Event* GetNewTsEvent()
  70. {
  71. allocatedTsEvents++;
  72. if (!eventTsPool)
  73. return new Event;
  74. Event* ev = eventTsPool;
  75. eventTsPool = ev->next;
  76. return ev;
  77. }
  78. void FreeEvent(Event* ev)
  79. {
  80. ev->next = eventPool;
  81. eventPool = ev;
  82. }
  83. void FreeTsEvent(Event* ev)
  84. {
  85. ev->next = eventTsPool;
  86. eventTsPool = ev;
  87. allocatedTsEvents--;
  88. }
  89. int RegisterEvent(const char *name, TimedCallback callback)
  90. {
  91. event_types.push_back(EventType(callback, name));
  92. return (int)event_types.size() - 1;
  93. }
  94. void AntiCrashCallback(u64 userdata, int cyclesLate)
  95. {
  96. ERROR_LOG(TIME, "Savestate broken: an unregistered event was called.");
  97. Core::Halt("invalid timing events");
  98. }
  99. void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback)
  100. {
  101. if (event_type >= (int)event_types.size())
  102. event_types.resize(event_type + 1, EventType(AntiCrashCallback, "INVALID EVENT"));
  103. event_types[event_type] = EventType(callback, name);
  104. }
  105. void UnregisterAllEvents()
  106. {
  107. if (first)
  108. PanicAlert("Cannot unregister events with events pending");
  109. event_types.clear();
  110. }
  111. void Init()
  112. {
  113. //currentMIPS->downcount = INITIAL_SLICE_LENGTH;
  114. //slicelength = INITIAL_SLICE_LENGTH;
  115. globalTimer = 0;
  116. idledCycles = 0;
  117. hasTsEvents = 0;
  118. }
  119. void Shutdown()
  120. {
  121. MoveEvents();
  122. ClearPendingEvents();
  123. UnregisterAllEvents();
  124. while (eventPool)
  125. {
  126. Event *ev = eventPool;
  127. eventPool = ev->next;
  128. delete ev;
  129. }
  130. std::lock_guard<std::recursive_mutex> lk(externalEventSection);
  131. while (eventTsPool)
  132. {
  133. Event *ev = eventTsPool;
  134. eventTsPool = ev->next;
  135. delete ev;
  136. }
  137. }
  138. u64 GetTicks()
  139. {
  140. ERROR_LOG(TIME, "Unimplemented function!");
  141. return 0;
  142. //return (u64)globalTimer + slicelength - currentMIPS->downcount;
  143. }
  144. u64 GetIdleTicks()
  145. {
  146. return (u64)idledCycles;
  147. }
  148. // This is to be called when outside threads, such as the graphics thread, wants to
  149. // schedule things to be executed on the main thread.
  150. void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata)
  151. {
  152. std::lock_guard<std::recursive_mutex> lk(externalEventSection);
  153. Event *ne = GetNewTsEvent();
  154. ne->time = GetTicks() + cyclesIntoFuture;
  155. ne->type = event_type;
  156. ne->next = 0;
  157. ne->userdata = userdata;
  158. if (!tsFirst)
  159. tsFirst = ne;
  160. if (tsLast)
  161. tsLast->next = ne;
  162. tsLast = ne;
  163. Common::AtomicStoreRelease(hasTsEvents, 1);
  164. }
  165. // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread
  166. // in which case the event will get handled immediately, before returning.
  167. void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata)
  168. {
  169. if (false) //Core::IsCPUThread())
  170. {
  171. std::lock_guard<std::recursive_mutex> lk(externalEventSection);
  172. event_types[event_type].callback(userdata, 0);
  173. }
  174. else
  175. ScheduleEvent_Threadsafe(0, event_type, userdata);
  176. }
  177. void ClearPendingEvents()
  178. {
  179. while (first)
  180. {
  181. Event *e = first->next;
  182. FreeEvent(first);
  183. first = e;
  184. }
  185. }
  186. void AddEventToQueue(Event* ne)
  187. {
  188. Event* prev = NULL;
  189. Event** pNext = &first;
  190. for (;;)
  191. {
  192. Event*& next = *pNext;
  193. if (!next || ne->time < next->time)
  194. {
  195. ne->next = next;
  196. next = ne;
  197. break;
  198. }
  199. prev = next;
  200. pNext = &prev->next;
  201. }
  202. }
  203. // This must be run ONLY from within the cpu thread
  204. // cyclesIntoFuture may be VERY inaccurate if called from anything else
  205. // than Advance
  206. void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata)
  207. {
  208. Event *ne = GetNewEvent();
  209. ne->userdata = userdata;
  210. ne->type = event_type;
  211. ne->time = GetTicks() + cyclesIntoFuture;
  212. AddEventToQueue(ne);
  213. }
  214. // Returns cycles left in timer.
  215. s64 UnscheduleEvent(int event_type, u64 userdata)
  216. {
  217. s64 result = 0;
  218. if (!first)
  219. return result;
  220. while (first)
  221. {
  222. if (first->type == event_type && first->userdata == userdata)
  223. {
  224. result = first->time - globalTimer;
  225. Event *next = first->next;
  226. FreeEvent(first);
  227. first = next;
  228. }
  229. else
  230. {
  231. break;
  232. }
  233. }
  234. if (!first)
  235. return result;
  236. Event *prev = first;
  237. Event *ptr = prev->next;
  238. while (ptr)
  239. {
  240. if (ptr->type == event_type && ptr->userdata == userdata)
  241. {
  242. result = ptr->time - globalTimer;
  243. prev->next = ptr->next;
  244. FreeEvent(ptr);
  245. ptr = prev->next;
  246. }
  247. else
  248. {
  249. prev = ptr;
  250. ptr = ptr->next;
  251. }
  252. }
  253. return result;
  254. }
  255. s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata)
  256. {
  257. s64 result = 0;
  258. std::lock_guard<std::recursive_mutex> lk(externalEventSection);
  259. if (!tsFirst)
  260. return result;
  261. while (tsFirst)
  262. {
  263. if (tsFirst->type == event_type && tsFirst->userdata == userdata)
  264. {
  265. result = tsFirst->time - globalTimer;
  266. Event *next = tsFirst->next;
  267. FreeTsEvent(tsFirst);
  268. tsFirst = next;
  269. }
  270. else
  271. {
  272. break;
  273. }
  274. }
  275. if (!tsFirst)
  276. {
  277. tsLast = NULL;
  278. return result;
  279. }
  280. Event *prev = tsFirst;
  281. Event *ptr = prev->next;
  282. while (ptr)
  283. {
  284. if (ptr->type == event_type && ptr->userdata == userdata)
  285. {
  286. result = ptr->time - globalTimer;
  287. prev->next = ptr->next;
  288. if (ptr == tsLast)
  289. tsLast = prev;
  290. FreeTsEvent(ptr);
  291. ptr = prev->next;
  292. }
  293. else
  294. {
  295. prev = ptr;
  296. ptr = ptr->next;
  297. }
  298. }
  299. return result;
  300. }
  301. // Warning: not included in save state.
  302. void RegisterAdvanceCallback(void(*callback)(int cyclesExecuted))
  303. {
  304. advanceCallback = callback;
  305. }
  306. bool IsScheduled(int event_type)
  307. {
  308. if (!first)
  309. return false;
  310. Event *e = first;
  311. while (e) {
  312. if (e->type == event_type)
  313. return true;
  314. e = e->next;
  315. }
  316. return false;
  317. }
  318. void RemoveEvent(int event_type)
  319. {
  320. if (!first)
  321. return;
  322. while (first)
  323. {
  324. if (first->type == event_type)
  325. {
  326. Event *next = first->next;
  327. FreeEvent(first);
  328. first = next;
  329. }
  330. else
  331. {
  332. break;
  333. }
  334. }
  335. if (!first)
  336. return;
  337. Event *prev = first;
  338. Event *ptr = prev->next;
  339. while (ptr)
  340. {
  341. if (ptr->type == event_type)
  342. {
  343. prev->next = ptr->next;
  344. FreeEvent(ptr);
  345. ptr = prev->next;
  346. }
  347. else
  348. {
  349. prev = ptr;
  350. ptr = ptr->next;
  351. }
  352. }
  353. }
  354. void RemoveThreadsafeEvent(int event_type)
  355. {
  356. std::lock_guard<std::recursive_mutex> lk(externalEventSection);
  357. if (!tsFirst)
  358. {
  359. return;
  360. }
  361. while (tsFirst)
  362. {
  363. if (tsFirst->type == event_type)
  364. {
  365. Event *next = tsFirst->next;
  366. FreeTsEvent(tsFirst);
  367. tsFirst = next;
  368. }
  369. else
  370. {
  371. break;
  372. }
  373. }
  374. if (!tsFirst)
  375. {
  376. tsLast = NULL;
  377. return;
  378. }
  379. Event *prev = tsFirst;
  380. Event *ptr = prev->next;
  381. while (ptr)
  382. {
  383. if (ptr->type == event_type)
  384. {
  385. prev->next = ptr->next;
  386. if (ptr == tsLast)
  387. tsLast = prev;
  388. FreeTsEvent(ptr);
  389. ptr = prev->next;
  390. }
  391. else
  392. {
  393. prev = ptr;
  394. ptr = ptr->next;
  395. }
  396. }
  397. }
  398. void RemoveAllEvents(int event_type)
  399. {
  400. RemoveThreadsafeEvent(event_type);
  401. RemoveEvent(event_type);
  402. }
  403. //This raise only the events required while the fifo is processing data
  404. void ProcessFifoWaitEvents()
  405. {
  406. while (first)
  407. {
  408. if (first->time <= globalTimer)
  409. {
  410. // LOG(TIMER, "[Scheduler] %s (%lld, %lld) ",
  411. // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
  412. Event* evt = first;
  413. first = first->next;
  414. event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time));
  415. FreeEvent(evt);
  416. }
  417. else
  418. {
  419. break;
  420. }
  421. }
  422. }
  423. void MoveEvents()
  424. {
  425. Common::AtomicStoreRelease(hasTsEvents, 0);
  426. std::lock_guard<std::recursive_mutex> lk(externalEventSection);
  427. // Move events from async queue into main queue
  428. while (tsFirst)
  429. {
  430. Event *next = tsFirst->next;
  431. AddEventToQueue(tsFirst);
  432. tsFirst = next;
  433. }
  434. tsLast = NULL;
  435. // Move free events to threadsafe pool
  436. while (allocatedTsEvents > 0 && eventPool)
  437. {
  438. Event *ev = eventPool;
  439. eventPool = ev->next;
  440. ev->next = eventTsPool;
  441. eventTsPool = ev;
  442. allocatedTsEvents--;
  443. }
  444. }
  445. void Advance()
  446. {
  447. ERROR_LOG(TIME, "Unimplemented function!");
  448. //int cyclesExecuted = slicelength - currentMIPS->downcount;
  449. //globalTimer += cyclesExecuted;
  450. //currentMIPS->downcount = slicelength;
  451. //if (Common::AtomicLoadAcquire(hasTsEvents))
  452. // MoveEvents();
  453. //ProcessFifoWaitEvents();
  454. //if (!first)
  455. //{
  456. // // WARN_LOG(TIMER, "WARNING - no events in queue. Setting currentMIPS->downcount to 10000");
  457. // currentMIPS->downcount += 10000;
  458. //}
  459. //else
  460. //{
  461. // slicelength = (int)(first->time - globalTimer);
  462. // if (slicelength > MAX_SLICE_LENGTH)
  463. // slicelength = MAX_SLICE_LENGTH;
  464. // currentMIPS->downcount = slicelength;
  465. //}
  466. //if (advanceCallback)
  467. // advanceCallback(cyclesExecuted);
  468. }
  469. void LogPendingEvents()
  470. {
  471. Event *ptr = first;
  472. while (ptr)
  473. {
  474. //INFO_LOG(TIMER, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, ptr->time, ptr->type);
  475. ptr = ptr->next;
  476. }
  477. }
  478. void Idle(int maxIdle)
  479. {
  480. ERROR_LOG(TIME, "Unimplemented function!");
  481. //int cyclesDown = currentMIPS->downcount;
  482. //if (maxIdle != 0 && cyclesDown > maxIdle)
  483. // cyclesDown = maxIdle;
  484. //if (first && cyclesDown > 0)
  485. //{
  486. // int cyclesExecuted = slicelength - currentMIPS->downcount;
  487. // int cyclesNextEvent = (int) (first->time - globalTimer);
  488. // if (cyclesNextEvent < cyclesExecuted + cyclesDown)
  489. // {
  490. // cyclesDown = cyclesNextEvent - cyclesExecuted;
  491. // // Now, now... no time machines, please.
  492. // if (cyclesDown < 0)
  493. // cyclesDown = 0;
  494. // }
  495. //}
  496. //INFO_LOG(TIME, "Idle for %i cycles! (%f ms)", cyclesDown, cyclesDown / (float)(g_clock_rate_arm11 * 0.001f));
  497. //idledCycles += cyclesDown;
  498. //currentMIPS->downcount -= cyclesDown;
  499. //if (currentMIPS->downcount == 0)
  500. // currentMIPS->downcount = -1;
  501. }
  502. std::string GetScheduledEventsSummary()
  503. {
  504. Event *ptr = first;
  505. std::string text = "Scheduled events\n";
  506. text.reserve(1000);
  507. while (ptr)
  508. {
  509. unsigned int t = ptr->type;
  510. if (t >= event_types.size())
  511. PanicAlert("Invalid event type"); // %i", t);
  512. const char *name = event_types[ptr->type].name;
  513. if (!name)
  514. name = "[unknown]";
  515. char temp[512];
  516. sprintf(temp, "%s : %i %08x%08x\n", name, (int)ptr->time, (u32)(ptr->userdata >> 32), (u32)(ptr->userdata));
  517. text += temp;
  518. ptr = ptr->next;
  519. }
  520. return text;
  521. }
  522. void Event_DoState(PointerWrap &p, BaseEvent *ev)
  523. {
  524. p.Do(*ev);
  525. }
  526. void DoState(PointerWrap &p)
  527. {
  528. std::lock_guard<std::recursive_mutex> lk(externalEventSection);
  529. auto s = p.Section("CoreTiming", 1);
  530. if (!s)
  531. return;
  532. int n = (int)event_types.size();
  533. p.Do(n);
  534. // These (should) be filled in later by the modules.
  535. event_types.resize(n, EventType(AntiCrashCallback, "INVALID EVENT"));
  536. p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(first, (Event **)NULL);
  537. p.DoLinkedList<BaseEvent, GetNewTsEvent, FreeTsEvent, Event_DoState>(tsFirst, &tsLast);
  538. p.Do(g_clock_rate_arm11);
  539. p.Do(slicelength);
  540. p.Do(globalTimer);
  541. p.Do(idledCycles);
  542. }
  543. } // namespace