sim_thread_manager.cc 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #include "sim_thread_manager.h"
  2. #include "lock.h"
  3. #include "log.h"
  4. #include "config.h"
  5. #include "simulator.h"
  6. SimThreadManager::SimThreadManager()
  7. : m_active_threads(0)
  8. {
  9. }
  10. SimThreadManager::~SimThreadManager()
  11. {
  12. LOG_ASSERT_WARNING(m_active_threads == 0,
  13. "Threads still active when SimThreadManager exits.");
  14. }
  15. void SimThreadManager::spawnSimThreads()
  16. {
  17. UInt32 num_cores = Config::getSingleton()->getTotalCores();
  18. #ifdef ENABLE_PERF_MODEL_OWN_THREAD
  19. __attribute__((unused)) UInt32 num_sim_threads = 2 * num_cores;
  20. #else
  21. __attribute__((unused)) UInt32 num_sim_threads = num_cores;
  22. #endif
  23. LOG_PRINT("Starting %d threads.", num_sim_threads);
  24. m_sim_threads = new SimThread [num_cores];
  25. #ifdef ENABLE_PERF_MODEL_OWN_THREAD
  26. m_core_threads = new CoreThread [num_cores];
  27. #endif
  28. for (UInt32 i = 0; i < num_cores; i++)
  29. {
  30. LOG_PRINT("Starting thread %i", i);
  31. m_sim_threads[i].spawn();
  32. #ifdef ENABLE_PERF_MODEL_OWN_THREAD
  33. m_core_threads[i].spawn();
  34. #endif
  35. }
  36. // PIN_SpawnInternalThread doesn't schedule its threads until after PIN_StartProgram
  37. // while (m_active_threads < num_sim_threads)
  38. // sched_yield();
  39. LOG_PRINT("Threads started: %d.", m_active_threads);
  40. }
  41. void SimThreadManager::quitSimThreads()
  42. {
  43. LOG_PRINT("Sending quit messages.");
  44. Transport::Node *global_node = Transport::getSingleton()->getGlobalNode();
  45. // This is something of a hard-wired emulation of Network::netSend
  46. // ... not the greatest thing to do, but whatever.
  47. NetPacket pkt1(SubsecondTime::Zero(), SIM_THREAD_TERMINATE_THREADS, 0, 0, 0, NULL);
  48. NetPacket pkt2(SubsecondTime::Zero(), CORE_THREAD_TERMINATE_THREADS, 0, 0, 0, NULL);
  49. for (core_id_t core_id = 0; core_id < (core_id_t)Config::getSingleton()->getTotalCores(); core_id++)
  50. {
  51. #ifdef ENABLE_PERF_MODEL_OWN_THREAD
  52. // First kill core thread (needs network thread to be alive to deliver the message)
  53. pkt2.receiver = core_id;
  54. global_node->send(core_id, &pkt2, pkt2.bufferSize());
  55. #endif
  56. // Now kill network thread
  57. pkt1.receiver = core_id;
  58. global_node->send(core_id, &pkt1, pkt1.bufferSize());
  59. }
  60. LOG_PRINT("Waiting for local sim threads to exit.");
  61. while (m_active_threads > 0)
  62. sched_yield();
  63. Transport::getSingleton()->barrier();
  64. delete [] m_sim_threads;
  65. #ifdef ENABLE_PERF_MODEL_OWN_THREAD
  66. delete [] m_core_threads;
  67. #endif
  68. LOG_PRINT("All threads have exited.");
  69. }
  70. void SimThreadManager::simThreadStartCallback()
  71. {
  72. m_active_threads_lock.acquire();
  73. ++m_active_threads;
  74. m_active_threads_lock.release();
  75. }
  76. void SimThreadManager::simThreadExitCallback()
  77. {
  78. m_active_threads_lock.acquire();
  79. --m_active_threads;
  80. m_active_threads_lock.release();
  81. }