1 // workqueue.cc -- the workqueue for gold
10 // Task_token methods.
12 Task_token::Task_token()
13 : is_blocker_(false), readers_(0), writer_(NULL
)
17 Task_token::~Task_token()
19 gold_assert(this->readers_
== 0 && this->writer_
== NULL
);
23 Task_token::is_readable() const
25 gold_assert(!this->is_blocker_
);
26 return this->writer_
== NULL
;
30 Task_token::add_reader()
32 gold_assert(!this->is_blocker_
);
33 gold_assert(this->is_readable());
38 Task_token::remove_reader()
40 gold_assert(!this->is_blocker_
);
41 gold_assert(this->readers_
> 0);
46 Task_token::is_writable() const
48 gold_assert(!this->is_blocker_
);
49 return this->writer_
== NULL
&& this->readers_
== 0;
53 Task_token::add_writer(const Task
* t
)
55 gold_assert(!this->is_blocker_
);
56 gold_assert(this->is_writable());
61 Task_token::remove_writer(const Task
* t
)
63 gold_assert(!this->is_blocker_
);
64 gold_assert(this->writer_
== t
);
69 Task_token::has_write_lock(const Task
* t
)
71 gold_assert(!this->is_blocker_
);
72 return this->writer_
== t
;
75 // For blockers, we just use the readers_ field.
78 Task_token::add_blocker()
80 if (this->readers_
== 0 && this->writer_
== NULL
)
81 this->is_blocker_
= true;
83 gold_assert(this->is_blocker_
);
88 Task_token::remove_blocker()
90 gold_assert(this->is_blocker_
&& this->readers_
> 0);
92 return this->readers_
== 0;
96 Task_token::is_blocked() const
98 gold_assert(this->is_blocker_
99 || (this->readers_
== 0 && this->writer_
== NULL
));
100 return this->readers_
> 0;
103 // The Task_block_token class.
105 Task_block_token::Task_block_token(Task_token
& token
, Workqueue
* workqueue
)
106 : token_(token
), workqueue_(workqueue
)
108 // We must increment the block count when the task is created and
109 // put on the queue. This object is created when the task is run,
110 // so we don't increment the block count here.
111 gold_assert(this->token_
.is_blocked());
114 Task_block_token::~Task_block_token()
116 if (this->token_
.remove_blocker())
118 // Tell the workqueue that a blocker was cleared. This is
119 // always called in the main thread, so no locking is required.
120 this->workqueue_
->cleared_blocker();
124 // The Workqueue_runner abstract class.
126 class Workqueue_runner
129 Workqueue_runner(Workqueue
* workqueue
)
130 : workqueue_(workqueue
)
132 virtual ~Workqueue_runner()
135 // Run a task. This is always called in the main thread.
136 virtual void run(Task
*, Task_locker
*) = 0;
139 // This is called by an implementation when a task is completed.
140 void completed(Task
* t
, Task_locker
* tl
)
141 { this->workqueue_
->completed(t
, tl
); }
143 Workqueue
* get_workqueue() const
144 { return this->workqueue_
; }
147 Workqueue
* workqueue_
;
150 // The simple single-threaded implementation of Workqueue_runner.
152 class Workqueue_runner_single
: public Workqueue_runner
155 Workqueue_runner_single(Workqueue
* workqueue
)
156 : Workqueue_runner(workqueue
)
158 ~Workqueue_runner_single()
161 void run(Task
*, Task_locker
*);
165 Workqueue_runner_single::run(Task
* t
, Task_locker
* tl
)
167 t
->run(this->get_workqueue());
168 this->completed(t
, tl
);
171 // Workqueue methods.
173 Workqueue::Workqueue(const General_options
&)
179 completed_condvar_(this->completed_lock_
),
182 // At some point we will select the specific implementation of
183 // Workqueue_runner to use based on the command line options.
184 this->runner_
= new Workqueue_runner_single(this);
187 Workqueue::~Workqueue()
189 gold_assert(this->tasks_
.empty());
190 gold_assert(this->completed_
.empty());
191 gold_assert(this->running_
== 0);
194 // Add a task to the queue.
197 Workqueue::queue(Task
* t
)
199 Hold_lock
hl(this->tasks_lock_
);
200 this->tasks_
.push_back(t
);
203 // Add a task to the front of the queue.
206 Workqueue::queue_front(Task
* t
)
208 Hold_lock
hl(this->tasks_lock_
);
209 this->tasks_
.push_front(t
);
212 // Clear the list of completed tasks. Return whether we cleared
213 // anything. The completed_lock_ must be held when this is called.
216 Workqueue::clear_completed()
218 if (this->completed_
.empty())
222 delete this->completed_
.front();
223 this->completed_
.pop_front();
225 while (!this->completed_
.empty());
229 // Find a runnable task in TASKS, which is non-empty. Return NULL if
230 // none could be found. The tasks_lock_ must be held when this is
231 // called. Sets ALL_BLOCKED if all non-runnable tasks are waiting on
235 Workqueue::find_runnable(Task_list
& tasks
, bool* all_blocked
)
237 Task
* tlast
= tasks
.back();
241 Task
* t
= tasks
.front();
244 Task::Is_runnable_type is_runnable
= t
->is_runnable(this);
245 if (is_runnable
== Task::IS_RUNNABLE
)
248 if (is_runnable
!= Task::IS_BLOCKED
)
249 *all_blocked
= false;
255 // We couldn't find any runnable task. If there are any
256 // completed tasks, free their locks and try again.
259 Hold_lock
hl2(this->completed_lock_
);
261 if (!this->clear_completed())
263 // There had better be some tasks running, or we will
264 // never find a runnable task.
265 gold_assert(this->running_
> 0);
267 // We couldn't find any runnable tasks, and we
268 // couldn't release any locks.
273 // We're going around again, so recompute ALL_BLOCKED.
279 // Process all the tasks on the workqueue. This is the main loop in
280 // the linker. Note that as we process tasks, new tasks will be
293 Hold_lock
hl(this->tasks_lock_
);
295 if (this->tasks_
.empty())
303 t
= this->find_runnable(this->tasks_
, &all_blocked
);
308 // If T != NULL, it is a task we can run.
309 // If T == NULL && empty, then there are no tasks waiting to
310 // be run at this level.
311 // If T == NULL && !empty, then there tasks waiting to be
312 // run at this level, but they are waiting for something to
320 Hold_lock
hl(this->completed_lock_
);
322 // There must be something for us to wait for, or we won't
323 // be able to make progress.
324 gold_assert(this->running_
> 0 || !this->completed_
.empty());
328 this->cleared_blockers_
= 0;
329 this->clear_completed();
330 while (this->cleared_blockers_
== 0)
332 gold_assert(this->running_
> 0);
333 this->completed_condvar_
.wait();
334 this->clear_completed();
339 if (this->running_
> 0)
341 // Wait for a task to finish.
342 this->completed_condvar_
.wait();
344 this->clear_completed();
351 Hold_lock
hl(this->completed_lock_
);
353 // If there are no running tasks, then we are done.
354 if (this->running_
== 0)
356 this->clear_completed();
360 // Wait for a task to finish. Then we have to loop around
361 // again in case it added any new tasks before finishing.
362 this->completed_condvar_
.wait();
363 this->clear_completed();
369 // Run a task. This is always called in the main thread.
372 Workqueue::run(Task
* t
)
375 this->runner_
->run(t
, t
->locks(this));
378 // This is called when a task is completed to put the locks on the
379 // list to be released. We use a list because we only want the locks
380 // to be released in the main thread.
383 Workqueue::completed(Task
* t
, Task_locker
* tl
)
386 Hold_lock
hl(this->completed_lock_
);
387 gold_assert(this->running_
> 0);
389 this->completed_
.push_back(tl
);
390 this->completed_condvar_
.signal();
395 // This is called when the last task for a blocker has completed.
396 // This is always called in the main thread.
399 Workqueue::cleared_blocker()
401 ++this->cleared_blockers_
;
404 } // End namespace gold.