threadSimpleManager.cxx 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. // Filename: threadSimpleManager.cxx
  2. // Created by: drose (19Jun07)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "threadSimpleManager.h"
  15. #ifdef THREAD_SIMPLE_IMPL
  16. #include "threadSimpleImpl.h"
  17. #include "blockerSimple.h"
  18. #include "mainThread.h"
  19. #ifdef WIN32
  20. #define WIN32_LEAN_AND_MEAN
  21. #include <windows.h>
  22. #endif
  23. bool ThreadSimpleManager::_pointers_initialized;
  24. ThreadSimpleManager *ThreadSimpleManager::_global_ptr;
  25. ////////////////////////////////////////////////////////////////////
  26. // Function: ThreadSimpleManager::Constructor
  27. // Access: Private
  28. // Description:
  29. ////////////////////////////////////////////////////////////////////
  30. ThreadSimpleManager::
  31. ThreadSimpleManager() :
  32. _simple_thread_epoch_timeslice
  33. ("simple-thread-epoch-timeslice", 0.05,
  34. PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, "
  35. "in seconds, that should be considered the "
  36. "typical timeslice for one epoch (to run all threads once).")),
  37. _simple_thread_volunteer_delay
  38. ("simple-thread-volunteer-delay", 0.0,
  39. PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, "
  40. "in seconds, for which a task that voluntarily yields should "
  41. "be delayed.")),
  42. _simple_thread_window
  43. ("simple-thread-window", 1.0,
  44. PRC_DESC("When SIMPLE_THREADS is defined, this defines the amount of time, "
  45. "in seconds, over which to average all the threads' runtimes, "
  46. "for the purpose of scheduling threads.")),
  47. _simple_thread_low_weight
  48. ("simple-thread-low-weight", 0.2,
  49. PRC_DESC("When SIMPLE_THREADS is defined, this determines the relative "
  50. "amount of time that is given to threads with priority TP_low.")),
  51. _simple_thread_normal_weight
  52. ("simple-thread-normal-weight", 1.0,
  53. PRC_DESC("When SIMPLE_THREADS is defined, this determines the relative "
  54. "amount of time that is given to threads with priority TP_normal.")),
  55. _simple_thread_high_weight
  56. ("simple-thread-high-weight", 5.0,
  57. PRC_DESC("When SIMPLE_THREADS is defined, this determines the relative "
  58. "amount of time that is given to threads with priority TP_high.")),
  59. _simple_thread_urgent_weight
  60. ("simple-thread-urgent-weight", 10.0,
  61. PRC_DESC("When SIMPLE_THREADS is defined, this determines the relative "
  62. "amount of time that is given to threads with priority TP_urgent."))
  63. {
  64. _tick_scale = 1000000.0;
  65. _total_ticks = 0;
  66. _current_thread = NULL;
  67. _clock = TrueClock::get_global_ptr();
  68. _waiting_for_exit = NULL;
  69. #ifdef HAVE_POSIX_THREADS
  70. _posix_system_thread_id = pthread_self();
  71. #endif
  72. #ifdef WIN32
  73. _win32_system_thread_id = GetCurrentThreadId();
  74. #endif
  75. // Install these global pointers so very low-level code (code
  76. // defined before the pipeline directory) can yield when necessary.
  77. global_thread_yield = &Thread::force_yield;
  78. global_thread_consider_yield = &Thread::consider_yield;
  79. }
  80. ////////////////////////////////////////////////////////////////////
  81. // Function: ThreadSimpleManager::enqueue_ready
  82. // Access: Public
  83. // Description: Adds the indicated thread to the ready queue. The
  84. // thread will be executed when its turn comes. If the
  85. // thread is not the currently executing thread, its
  86. // _jmp_context should be filled appropriately.
  87. //
  88. // If volunteer is true, the thread is volunteering to
  89. // sleep before its timeslice has been used up. If
  90. // volunteer is false, the thread would still be running
  91. // if it could.
  92. ////////////////////////////////////////////////////////////////////
  93. void ThreadSimpleManager::
  94. enqueue_ready(ThreadSimpleImpl *thread, bool volunteer) {
  95. // We actually add it to _next_ready, so that we can tell when we
  96. // have processed every thread in a given epoch.
  97. if (!volunteer) {
  98. _next_ready.push_back(thread);
  99. } else {
  100. // Unless it's a volunteer, in which case we actually put it to
  101. // sleep for the duration of the timeslice, so it won't interfere
  102. // with timeslice accounting for the remaining ready threads.
  103. double now = get_current_time();
  104. thread->_wake_time = now + _simple_thread_volunteer_delay;
  105. _volunteers.push_back(thread);
  106. push_heap(_volunteers.begin(), _volunteers.end(), CompareStartTime());
  107. }
  108. }
  109. ////////////////////////////////////////////////////////////////////
  110. // Function: ThreadSimpleManager::enqueue_sleep
  111. // Access: Public
  112. // Description: Adds the indicated thread to the sleep queue, until
  113. // the indicated number of seconds have elapsed. Then
  114. // the thread will be automatically moved to the ready
  115. // queue.
  116. ////////////////////////////////////////////////////////////////////
  117. void ThreadSimpleManager::
  118. enqueue_sleep(ThreadSimpleImpl *thread, double seconds) {
  119. if (thread_cat->is_debug()) {
  120. thread_cat.debug()
  121. << *_current_thread->_parent_obj << " sleeping for "
  122. << seconds << " seconds\n";
  123. }
  124. double now = get_current_time();
  125. thread->_wake_time = now + seconds;
  126. _sleeping.push_back(thread);
  127. push_heap(_sleeping.begin(), _sleeping.end(), CompareStartTime());
  128. }
  129. ////////////////////////////////////////////////////////////////////
  130. // Function: ThreadSimpleManager::enqueue_block
  131. // Access: Public
  132. // Description: Adds the indicated thread to the blocked queue for
  133. // the indicated blocker. The thread will be awoken by
  134. // a later call to unblock_one() or unblock_all().
  135. ////////////////////////////////////////////////////////////////////
  136. void ThreadSimpleManager::
  137. enqueue_block(ThreadSimpleImpl *thread, BlockerSimple *blocker) {
  138. _blocked[blocker].push_back(thread);
  139. blocker->_flags |= BlockerSimple::F_has_waiters;
  140. }
  141. ////////////////////////////////////////////////////////////////////
  142. // Function: ThreadSimpleManager::unblock_one
  143. // Access: Public
  144. // Description: Unblocks one thread waiting on the indicated blocker,
  145. // if any. Returns true if anything was unblocked,
  146. // false otherwise.
  147. ////////////////////////////////////////////////////////////////////
  148. bool ThreadSimpleManager::
  149. unblock_one(BlockerSimple *blocker) {
  150. Blocked::iterator bi = _blocked.find(blocker);
  151. if (bi != _blocked.end()) {
  152. nassertr(blocker->_flags & BlockerSimple::F_has_waiters, false);
  153. FifoThreads &threads = (*bi).second;
  154. nassertr(!threads.empty(), false);
  155. ThreadSimpleImpl *thread = threads.front();
  156. threads.pop_front();
  157. _ready.push_back(thread);
  158. if (threads.empty()) {
  159. blocker->_flags &= ~BlockerSimple::F_has_waiters;
  160. _blocked.erase(bi);
  161. }
  162. return true;
  163. }
  164. return false;
  165. }
  166. ////////////////////////////////////////////////////////////////////
  167. // Function: ThreadSimpleManager::unblock_all
  168. // Access: Public
  169. // Description: Unblocks all threads waiting on the indicated
  170. // blocker. Returns true if anything was unblocked,
  171. // false otherwise.
  172. ////////////////////////////////////////////////////////////////////
  173. bool ThreadSimpleManager::
  174. unblock_all(BlockerSimple *blocker) {
  175. Blocked::iterator bi = _blocked.find(blocker);
  176. if (bi != _blocked.end()) {
  177. nassertr(blocker->_flags & BlockerSimple::F_has_waiters, false);
  178. FifoThreads &threads = (*bi).second;
  179. nassertr(!threads.empty(), false);
  180. while (!threads.empty()) {
  181. ThreadSimpleImpl *thread = threads.front();
  182. threads.pop_front();
  183. _ready.push_back(thread);
  184. }
  185. blocker->_flags &= ~BlockerSimple::F_has_waiters;
  186. _blocked.erase(bi);
  187. return true;
  188. }
  189. return false;
  190. }
  191. ////////////////////////////////////////////////////////////////////
  192. // Function: ThreadSimpleManager::enqueue_finished
  193. // Access: Public
  194. // Description: Adds the indicated thread to the finished queue.
  195. // The manager will drop the reference count on the
  196. // indicated thread at the next epoch. (A thread can't
  197. // drop its own reference count while it is running,
  198. // since that might deallocate its own stack.)
  199. ////////////////////////////////////////////////////////////////////
  200. void ThreadSimpleManager::
  201. enqueue_finished(ThreadSimpleImpl *thread) {
  202. _finished.push_back(thread);
  203. }
  204. ////////////////////////////////////////////////////////////////////
  205. // Function: ThreadSimpleManager::preempt
  206. // Access: Public
  207. // Description: Moves the indicated thread to the head of the ready
  208. // queue. If it is not already on the ready queue, does
  209. // nothing.
  210. ////////////////////////////////////////////////////////////////////
  211. void ThreadSimpleManager::
  212. preempt(ThreadSimpleImpl *thread) {
  213. FifoThreads::iterator ti;
  214. ti = find(_ready.begin(), _ready.end(), thread);
  215. if (ti != _ready.end()) {
  216. _ready.erase(ti);
  217. _ready.push_front(thread);
  218. }
  219. }
  220. ////////////////////////////////////////////////////////////////////
  221. // Function: ThreadSimpleManager::next_context
  222. // Access: Public
  223. // Description: Switches out the currently executing thread and
  224. // chooses a new thread for execution. Before calling
  225. // this, the current thread should have already
  226. // re-enqueued itself with a call to enqueue(), if it
  227. // intends to run again.
  228. //
  229. // This will fill in the current thread's _jmp_context
  230. // member appropriately, and then change the global
  231. // current_thread pointer.
  232. ////////////////////////////////////////////////////////////////////
  233. void ThreadSimpleManager::
  234. next_context() {
  235. // Delete any threads that need it. We can't delete the current
  236. // thread, though.
  237. while (!_finished.empty() && _finished.front() != _current_thread) {
  238. ThreadSimpleImpl *finished_thread = _finished.front();
  239. _finished.pop_front();
  240. unref_delete(finished_thread->_parent_obj);
  241. }
  242. // Mark the current thread's resume point.
  243. #ifdef HAVE_PYTHON
  244. // Save the current Python thread state.
  245. _current_thread->_python_state = PyThreadState_Swap(NULL);
  246. #endif // HAVE_PYTHON
  247. #ifdef DO_PSTATS
  248. Thread::PStatsCallback *pstats_callback = _current_thread->_parent_obj->get_pstats_callback();
  249. if (pstats_callback != NULL) {
  250. pstats_callback->deactivate_hook(_current_thread->_parent_obj);
  251. }
  252. #endif // DO_PSTATS
  253. save_thread_context(&_current_thread->_context, st_choose_next_context, this);
  254. // Pass 2: we have returned into the context, and are now resuming
  255. // the current thread.
  256. #ifdef DO_PSTATS
  257. if (pstats_callback != NULL) {
  258. pstats_callback->activate_hook(_current_thread->_parent_obj);
  259. }
  260. #endif // DO_PSTATS
  261. #ifdef HAVE_PYTHON
  262. PyThreadState_Swap(_current_thread->_python_state);
  263. #endif // HAVE_PYTHON
  264. }
  265. ////////////////////////////////////////////////////////////////////
  266. // Function: ThreadSimpleManager::prepare_for_exit
  267. // Access: Public
  268. // Description: Blocks until all running threads (other than the
  269. // current thread) have finished. This only works when
  270. // called from the main thread; if called on any other
  271. // thread, nothing will happen.
  272. ////////////////////////////////////////////////////////////////////
  273. void ThreadSimpleManager::
  274. prepare_for_exit() {
  275. if (!_current_thread->_parent_obj->is_exact_type(MainThread::get_class_type())) {
  276. if (thread_cat->is_debug()) {
  277. thread_cat.debug()
  278. << "Ignoring prepare_for_exit called from "
  279. << *(_current_thread->_parent_obj) << "\n";
  280. }
  281. return;
  282. }
  283. if (thread_cat->is_debug()) {
  284. thread_cat.debug()
  285. << "prepare_for_exit\n";
  286. }
  287. nassertv(_waiting_for_exit == NULL);
  288. _waiting_for_exit = _current_thread;
  289. // At this point, any non-joinable threads on any of the queues are
  290. // automatically killed.
  291. kill_non_joinable(_ready);
  292. Blocked::iterator bi = _blocked.begin();
  293. while (bi != _blocked.end()) {
  294. Blocked::iterator bnext = bi;
  295. ++bnext;
  296. BlockerSimple *blocker = (*bi).first;
  297. FifoThreads &threads = (*bi).second;
  298. kill_non_joinable(threads);
  299. if (threads.empty()) {
  300. blocker->_flags &= ~BlockerSimple::F_has_waiters;
  301. _blocked.erase(bi);
  302. }
  303. bi = bnext;
  304. }
  305. kill_non_joinable(_sleeping);
  306. kill_non_joinable(_volunteers);
  307. next_context();
  308. // Delete any remaining threads.
  309. while (!_finished.empty() && _finished.front() != _current_thread) {
  310. ThreadSimpleImpl *finished_thread = _finished.front();
  311. _finished.pop_front();
  312. unref_delete(finished_thread->_parent_obj);
  313. }
  314. }
  315. ////////////////////////////////////////////////////////////////////
  316. // Function: ThreadSimpleManager::set_current_thread
  317. // Access: Public
  318. // Description: Sets the initial value of the current_thread pointer,
  319. // i.e. the main thread. It is valid to call this
  320. // method only exactly once.
  321. ////////////////////////////////////////////////////////////////////
  322. void ThreadSimpleManager::
  323. set_current_thread(ThreadSimpleImpl *current_thread) {
  324. nassertv(_current_thread == (ThreadSimpleImpl *)NULL);
  325. _current_thread = current_thread;
  326. }
  327. ////////////////////////////////////////////////////////////////////
  328. // Function: ThreadSimpleManager::remove_thread
  329. // Access: Public
  330. // Description: Removes the indicated thread from the accounting, for
  331. // instance just before the thread destructs.
  332. ////////////////////////////////////////////////////////////////////
  333. void ThreadSimpleManager::
  334. remove_thread(ThreadSimpleImpl *thread) {
  335. TickRecords new_records;
  336. TickRecords::iterator ri;
  337. for (ri = _tick_records.begin(); ri != _tick_records.end(); ++ri) {
  338. if ((*ri)._thread != thread) {
  339. // Keep this record.
  340. new_records.push_back(*ri);
  341. } else {
  342. // Lose this record.
  343. nassertv(_total_ticks >= (*ri)._tick_count);
  344. _total_ticks -= (*ri)._tick_count;
  345. }
  346. }
  347. _tick_records.swap(new_records);
  348. }
  349. ////////////////////////////////////////////////////////////////////
  350. // Function: ThreadSimpleManager::system_sleep
  351. // Access: Public, Static
  352. // Description: Calls the appropriate system sleep function to sleep
  353. // the whole process for the indicated number of
  354. // seconds.
  355. ////////////////////////////////////////////////////////////////////
  356. void ThreadSimpleManager::
  357. system_sleep(double seconds) {
  358. #ifdef WIN32
  359. Sleep((int)(seconds * 1000));
  360. #else
  361. struct timespec rqtp;
  362. rqtp.tv_sec = time_t(seconds);
  363. rqtp.tv_nsec = long((seconds - (double)rqtp.tv_sec) * 1000000000.0);
  364. nanosleep(&rqtp, NULL);
  365. #endif // WIN32
  366. }
  367. ////////////////////////////////////////////////////////////////////
  368. // Function: ThreadSimpleManager::write_status
  369. // Access: Public
  370. // Description: Writes a list of threads running and threads blocked.
  371. ////////////////////////////////////////////////////////////////////
  372. void ThreadSimpleManager::
  373. write_status(ostream &out) const {
  374. out << "Currently running: " << *_current_thread->_parent_obj << "\n";
  375. out << "Ready:";
  376. FifoThreads::const_iterator ti;
  377. Sleeping::const_iterator si;
  378. for (ti = _ready.begin(); ti != _ready.end(); ++ti) {
  379. out << " " << *(*ti)->_parent_obj;
  380. }
  381. for (ti = _next_ready.begin(); ti != _next_ready.end(); ++ti) {
  382. out << " " << *(*ti)->_parent_obj;
  383. }
  384. for (si = _volunteers.begin(); si != _volunteers.end(); ++si) {
  385. out << " " << *(*si)->_parent_obj;
  386. }
  387. out << "\n";
  388. double now = get_current_time();
  389. out << "Sleeping:";
  390. // Copy and sort for convenience.
  391. Sleeping s2 = _sleeping;
  392. sort(s2.begin(), s2.end(), CompareStartTime());
  393. for (si = s2.begin(); si != s2.end(); ++si) {
  394. out << " " << *(*si)->_parent_obj << "(" << (*si)->_wake_time - now
  395. << "s)";
  396. }
  397. out << "\n";
  398. Blocked::const_iterator bi;
  399. for (bi = _blocked.begin(); bi != _blocked.end(); ++bi) {
  400. BlockerSimple *blocker = (*bi).first;
  401. const FifoThreads &threads = (*bi).second;
  402. out << "On blocker " << blocker << ":\n";
  403. FifoThreads::const_iterator ti;
  404. for (ti = threads.begin(); ti != threads.end(); ++ti) {
  405. ThreadSimpleImpl *thread = (*ti);
  406. out << " " << *thread->_parent_obj;
  407. #ifdef DEBUG_THREADS
  408. out << " (";
  409. thread->_parent_obj->output_blocker(out);
  410. out << ")";
  411. #endif // DEBUG_THREADS
  412. }
  413. out << "\n";
  414. }
  415. }
  416. ////////////////////////////////////////////////////////////////////
  417. // Function: ThreadSimpleManager::system_yield
  418. // Access: Public, Static
  419. // Description: Calls the appropriate system function to yield
  420. // the whole process to any other system processes.
  421. ////////////////////////////////////////////////////////////////////
  422. void ThreadSimpleManager::
  423. system_yield() {
  424. #ifdef WIN32
  425. Sleep(0);
  426. #else
  427. struct timespec rqtp;
  428. rqtp.tv_sec = 0;
  429. rqtp.tv_nsec = 0;
  430. nanosleep(&rqtp, NULL);
  431. #endif // WIN32
  432. }
  433. ////////////////////////////////////////////////////////////////////
  434. // Function: ThreadSimpleManager::init_pointers
  435. // Access: Private, Static
  436. // Description: Should be called at startup to initialize the
  437. // simple threading system.
  438. ////////////////////////////////////////////////////////////////////
  439. void ThreadSimpleManager::
  440. init_pointers() {
  441. if (!_pointers_initialized) {
  442. _pointers_initialized = true;
  443. _global_ptr = new ThreadSimpleManager;
  444. Thread::get_main_thread();
  445. #ifdef HAVE_PYTHON
  446. // Ensure that the Python threading system is initialized and ready
  447. // to go.
  448. PyEval_InitThreads();
  449. #endif
  450. }
  451. }
  452. ////////////////////////////////////////////////////////////////////
  453. // Function: ThreadSimpleManager::st_choose_next_context
  454. // Access: Private, Static
  455. // Description: Select the next context to run. Continuing the work
  456. // of next_context().
  457. ////////////////////////////////////////////////////////////////////
  458. void ThreadSimpleManager::
  459. st_choose_next_context(void *data) {
  460. ThreadSimpleManager *self = (ThreadSimpleManager *)data;
  461. self->choose_next_context();
  462. }
  463. ////////////////////////////////////////////////////////////////////
  464. // Function: ThreadSimpleManager::choose_next_context
  465. // Access: Private
  466. // Description: Select the next context to run. Continuing the work
  467. // of next_context().
  468. ////////////////////////////////////////////////////////////////////
  469. void ThreadSimpleManager::
  470. choose_next_context() {
  471. double now = get_current_time();
  472. do_timeslice_accounting(_current_thread, now);
  473. _current_thread = NULL;
  474. if (!_sleeping.empty() || !_volunteers.empty()) {
  475. if (_ready.empty() && _next_ready.empty()) {
  476. // All of our threads are currently sleeping. Therefore, wake
  477. // the volunteer(s) immediately.
  478. wake_all_sleepers(_volunteers);
  479. // We should also yield the whole process now, to be polite to
  480. // the rest of the system.
  481. system_yield();
  482. now = get_current_time();
  483. }
  484. wake_sleepers(_sleeping, now);
  485. wake_sleepers(_volunteers, now);
  486. }
  487. bool new_epoch = !_ready.empty() && _next_ready.empty();
  488. // Choose a new thread to execute.
  489. while (true) {
  490. // If there are no threads, sleep.
  491. while (_ready.empty()) {
  492. if (!_next_ready.empty()) {
  493. // We've finished an epoch.
  494. _ready.swap(_next_ready);
  495. if (new_epoch && !_tick_records.empty()) {
  496. // Pop the oldest timeslice record off when we finish an
  497. // epoch without executing any threads, to ensure we don't
  498. // get caught in an "all threads reached budget" loop.
  499. if (thread_cat->is_debug()) {
  500. thread_cat.debug()
  501. << "All threads exceeded budget.\n";
  502. }
  503. TickRecord &record = _tick_records.front();
  504. _total_ticks -= record._tick_count;
  505. nassertv(record._thread->_run_ticks >= record._tick_count);
  506. record._thread->_run_ticks -= record._tick_count;
  507. _tick_records.pop_front();
  508. }
  509. new_epoch = true;
  510. } else if (!_volunteers.empty()) {
  511. // There are some volunteers. Wake them. Also wake any
  512. // sleepers that need it.
  513. if (thread_cat->is_debug()) {
  514. thread_cat.debug()
  515. << "Waking volunteers.\n";
  516. }
  517. // We should yield the whole process now, to be polite to the
  518. // rest of the system.
  519. system_yield();
  520. now = get_current_time();
  521. wake_all_sleepers(_volunteers);
  522. wake_sleepers(_sleeping, now);
  523. } else if (!_sleeping.empty()) {
  524. // All threads are sleeping.
  525. double wait = _sleeping.front()->_wake_time - now;
  526. if (wait > 0.0) {
  527. if (thread_cat->is_debug()) {
  528. thread_cat.debug()
  529. << "Sleeping all threads " << wait << " seconds\n";
  530. }
  531. system_sleep(wait);
  532. }
  533. now = get_current_time();
  534. wake_sleepers(_sleeping, now);
  535. wake_sleepers(_volunteers, now);
  536. } else {
  537. // No threads are ready!
  538. if (_waiting_for_exit != NULL) {
  539. // This is a shutdown situation. In this case, we quietly
  540. // abandoned the remaining blocked threads, if any, and
  541. // switch back to the main thread to finish shutting down.
  542. _ready.push_back(_waiting_for_exit);
  543. _waiting_for_exit = NULL;
  544. break;
  545. }
  546. // No threads are ready to rull, but we're not explicitly
  547. // shutting down. This is an error condition, an
  548. // unintentional deadlock.
  549. if (!_blocked.empty()) {
  550. thread_cat->error()
  551. << "Deadlock! All threads blocked.\n";
  552. report_deadlock();
  553. abort();
  554. }
  555. // No threads are queued anywhere. This is some kind of
  556. // internal error, since normally the main thread, at least,
  557. // should be queued somewhere.
  558. thread_cat->error()
  559. << "All threads disappeared!\n";
  560. exit(0);
  561. }
  562. }
  563. ThreadSimpleImpl *chosen_thread = _ready.front();
  564. _ready.pop_front();
  565. double timeslice = determine_timeslice(chosen_thread);
  566. if (timeslice > 0.0) {
  567. // This thread is ready to roll. Break out of the loop.
  568. chosen_thread->_start_time = now;
  569. chosen_thread->_stop_time = now + timeslice;
  570. _current_thread = chosen_thread;
  571. break;
  572. }
  573. // This thread is not ready to wake up yet. Put it back for next
  574. // epoch. It doesn't count as a volunteer, though--its timeslice
  575. // was used up.
  576. _next_ready.push_back(chosen_thread);
  577. }
  578. // All right, the thread is ready to roll. Begin.
  579. if (thread_cat->is_debug()) {
  580. size_t blocked_count = 0;
  581. Blocked::const_iterator bi;
  582. for (bi = _blocked.begin(); bi != _blocked.end(); ++bi) {
  583. const FifoThreads &threads = (*bi).second;
  584. blocked_count += threads.size();
  585. }
  586. double timeslice = _current_thread->_stop_time - _current_thread->_start_time;
  587. thread_cat.debug()
  588. << "Switching to " << *_current_thread->_parent_obj
  589. << " for " << timeslice << " s ("
  590. << _ready.size() << " + " << _next_ready.size()
  591. << " + " << _volunteers.size()
  592. << " other threads ready, " << blocked_count
  593. << " blocked, " << _sleeping.size() << " sleeping)\n";
  594. }
  595. switch_to_thread_context(&_current_thread->_context);
  596. // Shouldn't get here.
  597. nassertv(false);
  598. abort();
  599. }
  600. ////////////////////////////////////////////////////////////////////
  601. // Function: ThreadSimpleManager::do_timeslice_accounting
  602. // Access: Private
  603. // Description: Records the amount of time the indicated thread has
  604. // run, and updates the moving average.
  605. ////////////////////////////////////////////////////////////////////
  606. void ThreadSimpleManager::
  607. do_timeslice_accounting(ThreadSimpleImpl *thread, double now) {
  608. double elapsed = now - thread->_start_time;
  609. if (thread_cat.is_debug()) {
  610. thread_cat.debug()
  611. << *thread->_parent_obj << " ran for " << elapsed << " s of "
  612. << thread->_stop_time - thread->_start_time << " requested.\n";
  613. }
  614. // Clamp the elapsed time at 0. (If it's less than 0, the clock is
  615. // running backwards, ick.)
  616. elapsed = max(elapsed, 0.0);
  617. unsigned int ticks = (unsigned int)(elapsed * _tick_scale + 0.5);
  618. thread->_run_ticks += ticks;
  619. // Now remove any old records.
  620. unsigned int ticks_window = (unsigned int)(_simple_thread_window * _tick_scale + 0.5);
  621. while (_total_ticks > ticks_window) {
  622. nassertv(!_tick_records.empty());
  623. TickRecord &record = _tick_records.front();
  624. _total_ticks -= record._tick_count;
  625. nassertv(record._thread->_run_ticks >= record._tick_count);
  626. record._thread->_run_ticks -= record._tick_count;
  627. _tick_records.pop_front();
  628. }
  629. // Finally, record the new record.
  630. TickRecord record;
  631. record._tick_count = ticks;
  632. record._thread = thread;
  633. _tick_records.push_back(record);
  634. _total_ticks += ticks;
  635. }
  636. ////////////////////////////////////////////////////////////////////
  637. // Function: ThreadSimpleManager::wake_sleepers
  638. // Access: Private
  639. // Description: Moves any threads due to wake up from the sleeping
  640. // queue to the ready queue.
  641. ////////////////////////////////////////////////////////////////////
  642. void ThreadSimpleManager::
  643. wake_sleepers(ThreadSimpleManager::Sleeping &sleepers, double now) {
  644. while (!sleepers.empty() && sleepers.front()->_wake_time <= now) {
  645. ThreadSimpleImpl *thread = sleepers.front();
  646. pop_heap(sleepers.begin(), sleepers.end(), CompareStartTime());
  647. sleepers.pop_back();
  648. _ready.push_back(thread);
  649. }
  650. }
  651. ////////////////////////////////////////////////////////////////////
  652. // Function: ThreadSimpleManager::wake_all_sleepers
  653. // Access: Private
  654. // Description: Moves all threads from the indicated sleeping queue
  655. // to the ready queue, regardless of wake time.
  656. ////////////////////////////////////////////////////////////////////
  657. void ThreadSimpleManager::
  658. wake_all_sleepers(ThreadSimpleManager::Sleeping &sleepers) {
  659. while (!sleepers.empty()) {
  660. ThreadSimpleImpl *thread = sleepers.front();
  661. pop_heap(sleepers.begin(), sleepers.end(), CompareStartTime());
  662. sleepers.pop_back();
  663. _ready.push_back(thread);
  664. }
  665. }
  666. ////////////////////////////////////////////////////////////////////
  667. // Function: ThreadSimpleManager::report_deadlock
  668. // Access: Private
  669. // Description:
  670. ////////////////////////////////////////////////////////////////////
  671. void ThreadSimpleManager::
  672. report_deadlock() {
  673. Blocked::const_iterator bi;
  674. for (bi = _blocked.begin(); bi != _blocked.end(); ++bi) {
  675. BlockerSimple *blocker = (*bi).first;
  676. const FifoThreads &threads = (*bi).second;
  677. thread_cat.info()
  678. << "On blocker " << blocker << ":\n";
  679. FifoThreads::const_iterator ti;
  680. for (ti = threads.begin(); ti != threads.end(); ++ti) {
  681. ThreadSimpleImpl *thread = (*ti);
  682. thread_cat.info()
  683. << " " << *thread->_parent_obj;
  684. #ifdef DEBUG_THREADS
  685. thread_cat.info(false) << " (";
  686. thread->_parent_obj->output_blocker(thread_cat.info(false));
  687. thread_cat.info(false) << ")";
  688. #endif // DEBUG_THREADS
  689. thread_cat.info(false) << "\n";
  690. }
  691. }
  692. }
  693. ////////////////////////////////////////////////////////////////////
  694. // Function: ThreadSimpleManager::determine_timeslice
  695. // Access: Private
  696. // Description: Determines the amount of time that should be
  697. // allocated to the next timeslice of this thread, based
  698. // on its priority weight and the amount of time it has
  699. // run recently relative to other threads.
  700. ////////////////////////////////////////////////////////////////////
  701. double ThreadSimpleManager::
  702. determine_timeslice(ThreadSimpleImpl *chosen_thread) {
  703. if (_ready.empty() && _next_ready.empty()) {
  704. // This is the only ready thread. It gets the full timeslice.
  705. return _simple_thread_epoch_timeslice;
  706. }
  707. // Count up the total runtime and weight of all ready threads.
  708. unsigned int total_ticks = chosen_thread->_run_ticks;
  709. double total_weight = chosen_thread->_priority_weight;
  710. FifoThreads::const_iterator ti;
  711. for (ti = _ready.begin(); ti != _ready.end(); ++ti) {
  712. total_ticks += (*ti)->_run_ticks;
  713. total_weight += (*ti)->_priority_weight;
  714. }
  715. for (ti = _next_ready.begin(); ti != _next_ready.end(); ++ti) {
  716. total_ticks += (*ti)->_run_ticks;
  717. total_weight += (*ti)->_priority_weight;
  718. }
  719. nassertr(total_weight != 0.0, 0.0);
  720. double budget_ratio = chosen_thread->_priority_weight / total_weight;
  721. if (total_ticks == 0) {
  722. // This must be the first thread. Special case.
  723. return budget_ratio * _simple_thread_epoch_timeslice;
  724. }
  725. double run_ratio = (double)chosen_thread->_run_ticks / (double)total_ticks;
  726. double remaining_ratio = budget_ratio - run_ratio;
  727. if (thread_cat->is_debug()) {
  728. thread_cat.debug()
  729. << *chosen_thread->_parent_obj << " accrued "
  730. << chosen_thread->_run_ticks / _tick_scale << " s of "
  731. << total_ticks / _tick_scale << "; budget is "
  732. << budget_ratio * total_ticks / _tick_scale << ".\n";
  733. if (remaining_ratio <= 0.0) {
  734. thread_cat.debug()
  735. << "Exceeded budget.\n";
  736. }
  737. }
  738. return remaining_ratio * _simple_thread_epoch_timeslice;
  739. }
  740. ////////////////////////////////////////////////////////////////////
  741. // Function: ThreadSimpleManager::kill_non_joinable
  742. // Access: Private
  743. // Description: Removes any non-joinable threads from the indicated
  744. // queue and marks them killed.
  745. ////////////////////////////////////////////////////////////////////
  746. void ThreadSimpleManager::
  747. kill_non_joinable(ThreadSimpleManager::FifoThreads &threads) {
  748. FifoThreads new_threads;
  749. FifoThreads::iterator ti;
  750. for (ti = threads.begin(); ti != threads.end(); ++ti) {
  751. ThreadSimpleImpl *thread = (*ti);
  752. if (thread->_joinable) {
  753. new_threads.push_back(thread);
  754. } else {
  755. if (thread_cat->is_debug()) {
  756. thread_cat.debug()
  757. << "Killing " << *thread->_parent_obj << "\n";
  758. }
  759. thread->_status = ThreadSimpleImpl::S_killed;
  760. enqueue_finished(thread);
  761. }
  762. }
  763. threads.swap(new_threads);
  764. }
  765. ////////////////////////////////////////////////////////////////////
  766. // Function: ThreadSimpleManager::kill_non_joinable
  767. // Access: Private
  768. // Description: Removes any non-joinable threads from the indicated
  769. // queue and marks them killed.
  770. ////////////////////////////////////////////////////////////////////
  771. void ThreadSimpleManager::
  772. kill_non_joinable(ThreadSimpleManager::Sleeping &threads) {
  773. Sleeping new_threads;
  774. Sleeping::iterator ti;
  775. for (ti = threads.begin(); ti != threads.end(); ++ti) {
  776. ThreadSimpleImpl *thread = (*ti);
  777. if (thread->_joinable) {
  778. new_threads.push_back(thread);
  779. } else {
  780. if (thread_cat->is_debug()) {
  781. thread_cat.debug()
  782. << "Killing " << *thread->_parent_obj << "\n";
  783. }
  784. thread->_status = ThreadSimpleImpl::S_killed;
  785. enqueue_finished(thread);
  786. }
  787. }
  788. make_heap(new_threads.begin(), new_threads.end(), CompareStartTime());
  789. threads.swap(new_threads);
  790. }
  791. #endif // THREAD_SIMPLE_IMPL