workqueue.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. // workqueue.cc -- the workqueue for gold
  2. // Copyright (C) 2006-2022 Free Software Foundation, Inc.
  3. // Written by Ian Lance Taylor <iant@google.com>.
  4. // This file is part of gold.
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. // MA 02110-1301, USA.
  17. #include "gold.h"
  18. #include "debug.h"
  19. #include "options.h"
  20. #include "timer.h"
  21. #include "workqueue.h"
  22. #include "workqueue-internal.h"
  23. namespace gold
  24. {
  25. // Class Task_list.
  26. // Add T to the end of the list.
  27. inline void
  28. Task_list::push_back(Task* t)
  29. {
  30. gold_assert(t->list_next() == NULL);
  31. if (this->head_ == NULL)
  32. {
  33. this->head_ = t;
  34. this->tail_ = t;
  35. }
  36. else
  37. {
  38. this->tail_->set_list_next(t);
  39. this->tail_ = t;
  40. }
  41. }
  42. // Add T to the front of the list.
  43. inline void
  44. Task_list::push_front(Task* t)
  45. {
  46. gold_assert(t->list_next() == NULL);
  47. if (this->head_ == NULL)
  48. {
  49. this->head_ = t;
  50. this->tail_ = t;
  51. }
  52. else
  53. {
  54. t->set_list_next(this->head_);
  55. this->head_ = t;
  56. }
  57. }
  58. // Remove and return the first Task waiting for this lock to be
  59. // released.
  60. inline Task*
  61. Task_list::pop_front()
  62. {
  63. Task* ret = this->head_;
  64. if (ret != NULL)
  65. {
  66. if (ret == this->tail_)
  67. {
  68. gold_assert(ret->list_next() == NULL);
  69. this->head_ = NULL;
  70. this->tail_ = NULL;
  71. }
  72. else
  73. {
  74. this->head_ = ret->list_next();
  75. gold_assert(this->head_ != NULL);
  76. ret->clear_list_next();
  77. }
  78. }
  79. return ret;
  80. }
  81. // The simple single-threaded implementation of Workqueue_threader.
  82. class Workqueue_threader_single : public Workqueue_threader
  83. {
  84. public:
  85. Workqueue_threader_single(Workqueue* workqueue)
  86. : Workqueue_threader(workqueue)
  87. { }
  88. ~Workqueue_threader_single()
  89. { }
  90. void
  91. set_thread_count(int thread_count)
  92. { gold_assert(thread_count > 0); }
  93. bool
  94. should_cancel_thread(int)
  95. { return false; }
  96. };
  97. // Workqueue methods.
  98. Workqueue::Workqueue(const General_options& options)
  99. : lock_(),
  100. first_tasks_(),
  101. tasks_(),
  102. running_(0),
  103. waiting_(0),
  104. condvar_(this->lock_),
  105. threader_(NULL)
  106. {
  107. bool threads = options.threads();
  108. #ifndef ENABLE_THREADS
  109. threads = false;
  110. #endif
  111. if (!threads)
  112. this->threader_ = new Workqueue_threader_single(this);
  113. else
  114. {
  115. #ifdef ENABLE_THREADS
  116. this->threader_ = new Workqueue_threader_threadpool(this);
  117. #else
  118. gold_unreachable();
  119. #endif
  120. }
  121. }
  122. Workqueue::~Workqueue()
  123. {
  124. }
  125. // Add a task to the end of a specific queue, or put it on the list
  126. // waiting for a Token.
  127. void
  128. Workqueue::add_to_queue(Task_list* queue, Task* t, bool front)
  129. {
  130. Hold_lock hl(this->lock_);
  131. Task_token* token = t->is_runnable();
  132. if (token != NULL)
  133. {
  134. if (front)
  135. token->add_waiting_front(t);
  136. else
  137. token->add_waiting(t);
  138. ++this->waiting_;
  139. }
  140. else
  141. {
  142. if (front)
  143. queue->push_front(t);
  144. else
  145. queue->push_back(t);
  146. // Tell any waiting thread that there is work to do.
  147. this->condvar_.signal();
  148. }
  149. }
  150. // Add a task to the queue.
  151. void
  152. Workqueue::queue(Task* t)
  153. {
  154. this->add_to_queue(&this->tasks_, t, false);
  155. }
  156. // Queue a task which should run soon.
  157. void
  158. Workqueue::queue_soon(Task* t)
  159. {
  160. t->set_should_run_soon();
  161. this->add_to_queue(&this->first_tasks_, t, false);
  162. }
  163. // Queue a task which should run next.
  164. void
  165. Workqueue::queue_next(Task* t)
  166. {
  167. t->set_should_run_soon();
  168. this->add_to_queue(&this->first_tasks_, t, true);
  169. }
  170. // Return whether to cancel the current thread.
  171. inline bool
  172. Workqueue::should_cancel_thread(int thread_number)
  173. {
  174. return this->threader_->should_cancel_thread(thread_number);
  175. }
  176. // Find a runnable task in TASKS. Return NULL if none could be found.
  177. // If we find a Task waiting for a Token, add it to the list for that
  178. // Token. The workqueue lock must be held when this is called.
  179. Task*
  180. Workqueue::find_runnable_in_list(Task_list* tasks)
  181. {
  182. Task* t;
  183. while ((t = tasks->pop_front()) != NULL)
  184. {
  185. Task_token* token = t->is_runnable();
  186. if (token == NULL)
  187. return t;
  188. token->add_waiting(t);
  189. ++this->waiting_;
  190. }
  191. // We couldn't find any runnable task.
  192. return NULL;
  193. }
  194. // Find a runnable task. Return NULL if none could be found. The
  195. // workqueue lock must be held when this is called.
  196. Task*
  197. Workqueue::find_runnable()
  198. {
  199. Task* t = this->find_runnable_in_list(&this->first_tasks_);
  200. if (t == NULL)
  201. t = this->find_runnable_in_list(&this->tasks_);
  202. return t;
  203. }
  204. // Find a runnable a task, and wait until we find one. Return NULL if
  205. // we should exit. The workqueue lock must be held when this is
  206. // called.
  207. Task*
  208. Workqueue::find_runnable_or_wait(int thread_number)
  209. {
  210. Task* t = this->find_runnable();
  211. while (t == NULL)
  212. {
  213. if (this->running_ == 0
  214. && this->first_tasks_.empty()
  215. && this->tasks_.empty())
  216. {
  217. // Kick all the threads to make them exit.
  218. this->condvar_.broadcast();
  219. gold_assert(this->waiting_ == 0);
  220. return NULL;
  221. }
  222. if (this->should_cancel_thread(thread_number))
  223. return NULL;
  224. gold_debug(DEBUG_TASK, "%3d sleeping", thread_number);
  225. this->condvar_.wait();
  226. gold_debug(DEBUG_TASK, "%3d awake", thread_number);
  227. t = this->find_runnable();
  228. }
  229. return t;
  230. }
  231. // Find and run tasks. If we can't find a runnable task, wait for one
  232. // to become available. If we run a task, and it frees up another
  233. // runnable task, then run that one too. This returns true if we
  234. // should look for another task, false if we are cancelling this
  235. // thread.
  236. bool
  237. Workqueue::find_and_run_task(int thread_number)
  238. {
  239. Task* t;
  240. Task_locker tl;
  241. {
  242. Hold_lock hl(this->lock_);
  243. // Find a runnable task.
  244. t = this->find_runnable_or_wait(thread_number);
  245. if (t == NULL)
  246. return false;
  247. // Get the locks for the task. This must be called while we are
  248. // still holding the Workqueue lock.
  249. t->locks(&tl);
  250. ++this->running_;
  251. }
  252. while (t != NULL)
  253. {
  254. gold_debug(DEBUG_TASK, "%3d running task %s", thread_number,
  255. t->name().c_str());
  256. Timer timer;
  257. if (is_debugging_enabled(DEBUG_TASK))
  258. timer.start();
  259. t->run(this);
  260. if (is_debugging_enabled(DEBUG_TASK))
  261. {
  262. Timer::TimeStats elapsed = timer.get_elapsed_time();
  263. gold_debug(DEBUG_TASK,
  264. "%3d completed task %s "
  265. "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)",
  266. thread_number, t->name().c_str(),
  267. elapsed.user / 1000, (elapsed.user % 1000) * 1000,
  268. elapsed.sys / 1000, (elapsed.sys % 1000) * 1000,
  269. elapsed.wall / 1000, (elapsed.wall % 1000) * 1000);
  270. }
  271. Task* next;
  272. {
  273. Hold_lock hl(this->lock_);
  274. --this->running_;
  275. // Release the locks for the task. This must be done with the
  276. // workqueue lock held. Get the next Task to run if any.
  277. next = this->release_locks(t, &tl);
  278. if (next == NULL)
  279. next = this->find_runnable();
  280. // If we have another Task to run, get the Locks. This must
  281. // be called while we are still holding the Workqueue lock.
  282. if (next != NULL)
  283. {
  284. tl.clear();
  285. next->locks(&tl);
  286. ++this->running_;
  287. }
  288. }
  289. // We are done with this task.
  290. delete t;
  291. t = next;
  292. }
  293. return true;
  294. }
  295. // Handle the return value of release_locks, and get tasks ready to
  296. // run.
  297. // 1) If T is not runnable, queue it on the appropriate token.
  298. // 2) Otherwise, T is runnable. If *PRET is not NULL, then we have
  299. // already decided which Task to run next. Add T to the list of
  300. // runnable tasks, and signal another thread.
  301. // 3) Otherwise, *PRET is NULL. If IS_BLOCKER is false, then T was
  302. // waiting on a write lock. We can grab that lock now, so we run T
  303. // now.
  304. // 4) Otherwise, IS_BLOCKER is true. If we should run T soon, then
  305. // run it now.
  306. // 5) Otherwise, check whether there are other tasks to run. If there
  307. // are, then we generally get a better ordering if we run those tasks
  308. // now, before T. A typical example is tasks waiting on the Dirsearch
  309. // blocker. We don't want to run those tasks right away just because
  310. // the Dirsearch was unblocked.
  311. // 6) Otherwise, there are no other tasks to run, so we might as well
  312. // run this one now.
  313. // This function must be called with the Workqueue lock held.
  314. // Return true if we set *PRET to T, false otherwise.
  315. bool
  316. Workqueue::return_or_queue(Task* t, bool is_blocker, Task** pret)
  317. {
  318. Task_token* token = t->is_runnable();
  319. if (token != NULL)
  320. {
  321. token->add_waiting(t);
  322. ++this->waiting_;
  323. return false;
  324. }
  325. bool should_queue = false;
  326. bool should_return = false;
  327. if (*pret != NULL)
  328. should_queue = true;
  329. else if (!is_blocker)
  330. should_return = true;
  331. else if (t->should_run_soon())
  332. should_return = true;
  333. else if (!this->first_tasks_.empty() || !this->tasks_.empty())
  334. should_queue = true;
  335. else
  336. should_return = true;
  337. if (should_return)
  338. {
  339. gold_assert(*pret == NULL);
  340. *pret = t;
  341. return true;
  342. }
  343. else if (should_queue)
  344. {
  345. if (t->should_run_soon())
  346. this->first_tasks_.push_back(t);
  347. else
  348. this->tasks_.push_back(t);
  349. this->condvar_.signal();
  350. return false;
  351. }
  352. gold_unreachable();
  353. }
  354. // Release the locks associated with a Task. Return the first
  355. // runnable Task that we find. If we find more runnable tasks, add
  356. // them to the run queue and signal any other threads. This must be
  357. // called with the Workqueue lock held.
  358. Task*
  359. Workqueue::release_locks(Task* t, Task_locker* tl)
  360. {
  361. Task* ret = NULL;
  362. for (Task_locker::iterator p = tl->begin(); p != tl->end(); ++p)
  363. {
  364. Task_token* token = *p;
  365. if (token->is_blocker())
  366. {
  367. if (token->remove_blocker())
  368. {
  369. // The token has been unblocked. Every waiting Task may
  370. // now be runnable.
  371. Task* t;
  372. while ((t = token->remove_first_waiting()) != NULL)
  373. {
  374. --this->waiting_;
  375. this->return_or_queue(t, true, &ret);
  376. }
  377. }
  378. }
  379. else
  380. {
  381. token->remove_writer(t);
  382. // One more waiting Task may now be runnable. If we are
  383. // going to run it next, we can stop. Otherwise we need to
  384. // move all the Tasks to the runnable queue, to avoid a
  385. // potential deadlock if the locking status changes before
  386. // we run the next thread.
  387. Task* t;
  388. while ((t = token->remove_first_waiting()) != NULL)
  389. {
  390. --this->waiting_;
  391. if (this->return_or_queue(t, false, &ret))
  392. break;
  393. }
  394. }
  395. }
  396. return ret;
  397. }
  398. // Process all the tasks on the workqueue. Keep going until the
  399. // workqueue is empty, or until we have been told to exit. This
  400. // function is called by all threads.
  401. void
  402. Workqueue::process(int thread_number)
  403. {
  404. while (this->find_and_run_task(thread_number))
  405. ;
  406. }
  407. // Set the number of threads to use for the workqueue, if we are using
  408. // threads.
  409. void
  410. Workqueue::set_thread_count(int threads)
  411. {
  412. Hold_lock hl(this->lock_);
  413. this->threader_->set_thread_count(threads);
  414. // Wake up all the threads, since something has changed.
  415. this->condvar_.broadcast();
  416. }
  417. // Add a new blocker to an existing Task_token.
  418. void
  419. Workqueue::add_blocker(Task_token* token)
  420. {
  421. Hold_lock hl(this->lock_);
  422. token->add_blocker();
  423. }
  424. } // End namespace gold.