core_timing.cpp 14 KB

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