Commit | Line | Data |
---|---|---|
bae7f79e ILT |
1 | // workqueue.h -- the work queue for gold -*- C++ -*- |
2 | ||
b90efa5b | 3 | // Copyright (C) 2006-2015 Free Software Foundation, Inc. |
6cb15b7f ILT |
4 | // Written by Ian Lance Taylor <iant@google.com>. |
5 | ||
6 | // This file is part of gold. | |
7 | ||
8 | // This program is free software; you can redistribute it and/or modify | |
9 | // it under the terms of the GNU General Public License as published by | |
10 | // the Free Software Foundation; either version 3 of the License, or | |
11 | // (at your option) any later version. | |
12 | ||
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | ||
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | |
21 | // MA 02110-1301, USA. | |
22 | ||
bae7f79e ILT |
23 | // After processing the command line, everything the linker does is |
24 | // driven from a work queue. This permits us to parallelize the | |
25 | // linker where possible. | |
26 | ||
bae7f79e ILT |
27 | #ifndef GOLD_WORKQUEUE_H |
28 | #define GOLD_WORKQUEUE_H | |
29 | ||
17a1d0a9 ILT |
30 | #include <string> |
31 | ||
bae7f79e | 32 | #include "gold-threads.h" |
17a1d0a9 | 33 | #include "token.h" |
bae7f79e ILT |
34 | |
35 | namespace gold | |
36 | { | |
37 | ||
ead1e424 | 38 | class General_options; |
bae7f79e ILT |
39 | class Workqueue; |
40 | ||
bae7f79e ILT |
41 | // The superclass for tasks to be placed on the workqueue. Each |
42 | // specific task class will inherit from this one. | |
43 | ||
44 | class Task | |
45 | { | |
46 | public: | |
47 | Task() | |
17a1d0a9 | 48 | : list_next_(NULL), name_(), should_run_soon_(false) |
bae7f79e ILT |
49 | { } |
50 | virtual ~Task() | |
51 | { } | |
52 | ||
17a1d0a9 ILT |
53 | // Check whether the Task can be run now. This method is only |
54 | // called with the workqueue lock held. If the Task can run, this | |
55 | // returns NULL. Otherwise it returns a pointer to a token which | |
56 | // must be released before the Task can run. | |
57 | virtual Task_token* | |
58 | is_runnable() = 0; | |
59 | ||
60 | // Lock all the resources required by the Task, and store the locks | |
61 | // in a Task_locker. This method does not need to do anything if no | |
62 | // locks are required. This method is only called with the | |
63 | // workqueue lock held. | |
64 | virtual void | |
65 | locks(Task_locker*) = 0; | |
bae7f79e ILT |
66 | |
67 | // Run the task. | |
68 | virtual void | |
69 | run(Workqueue*) = 0; | |
ead1e424 | 70 | |
17a1d0a9 ILT |
71 | // Return whether this task should run soon. |
72 | bool | |
73 | should_run_soon() const | |
74 | { return this->should_run_soon_; } | |
75 | ||
76 | // Note that this task should run soon. | |
77 | void | |
78 | set_should_run_soon() | |
79 | { this->should_run_soon_ = true; } | |
80 | ||
81 | // Get the next Task on the list of Tasks. Called by Task_list. | |
82 | Task* | |
83 | list_next() const | |
84 | { return this->list_next_; } | |
85 | ||
86 | // Set the next Task on the list of Tasks. Called by Task_list. | |
87 | void | |
88 | set_list_next(Task* t) | |
89 | { | |
90 | gold_assert(this->list_next_ == NULL); | |
91 | this->list_next_ = t; | |
92 | } | |
93 | ||
94 | // Clear the next Task on the list of Tasks. Called by Task_list. | |
95 | void | |
96 | clear_list_next() | |
97 | { this->list_next_ = NULL; } | |
98 | ||
c7912668 ILT |
99 | // Return the name of the Task. This is only used for debugging |
100 | // purposes. | |
101 | const std::string& | |
102 | name() | |
103 | { | |
104 | if (this->name_.empty()) | |
105 | this->name_ = this->get_name(); | |
106 | return this->name_; | |
107 | } | |
108 | ||
109 | protected: | |
110 | // Get the name of the task. This must be implemented by the child | |
111 | // class. | |
112 | virtual std::string | |
113 | get_name() const = 0; | |
114 | ||
ead1e424 | 115 | private: |
17a1d0a9 | 116 | // Tasks may not be copied. |
ead1e424 ILT |
117 | Task(const Task&); |
118 | Task& operator=(const Task&); | |
c7912668 | 119 | |
17a1d0a9 ILT |
120 | // If this Task is on a list, this is a pointer to the next Task on |
121 | // the list. We use this simple list structure rather than building | |
122 | // a container, in order to avoid memory allocation while holding | |
123 | // the Workqueue lock. | |
124 | Task* list_next_; | |
c7912668 ILT |
125 | // Task name, for debugging purposes. |
126 | std::string name_; | |
17a1d0a9 ILT |
127 | // Whether this Task should be executed soon. This is used for |
128 | // Tasks which can be run after some data is read. | |
129 | bool should_run_soon_; | |
bae7f79e ILT |
130 | }; |
131 | ||
17a1d0a9 ILT |
132 | // An interface for Task_function. This is a convenience class to run |
133 | // a single function. | |
92e059d8 ILT |
134 | |
135 | class Task_function_runner | |
136 | { | |
137 | public: | |
138 | virtual ~Task_function_runner() | |
139 | { } | |
140 | ||
141 | virtual void | |
17a1d0a9 | 142 | run(Workqueue*, const Task*) = 0; |
92e059d8 ILT |
143 | }; |
144 | ||
17a1d0a9 ILT |
145 | // A simple task which waits for a blocker and then runs a function. |
146 | ||
92e059d8 ILT |
147 | class Task_function : public Task |
148 | { | |
149 | public: | |
17a1d0a9 ILT |
150 | // RUNNER and BLOCKER should be allocated using new, and will be |
151 | // deleted after the task runs. | |
c7912668 | 152 | Task_function(Task_function_runner* runner, Task_token* blocker, |
2ea97941 ILT |
153 | const char* name) |
154 | : runner_(runner), blocker_(blocker), name_(name) | |
135b9c78 | 155 | { gold_assert(blocker != NULL); } |
92e059d8 ILT |
156 | |
157 | ~Task_function() | |
158 | { | |
159 | delete this->runner_; | |
160 | delete this->blocker_; | |
161 | } | |
162 | ||
163 | // The standard task methods. | |
164 | ||
165 | // Wait until the task is unblocked. | |
17a1d0a9 ILT |
166 | Task_token* |
167 | is_runnable() | |
168 | { return this->blocker_->is_blocked() ? this->blocker_ : NULL; } | |
92e059d8 ILT |
169 | |
170 | // This type of task does not normally hold any locks. | |
17a1d0a9 ILT |
171 | virtual void |
172 | locks(Task_locker*) | |
173 | { } | |
92e059d8 ILT |
174 | |
175 | // Run the action. | |
176 | void | |
177 | run(Workqueue* workqueue) | |
17a1d0a9 | 178 | { this->runner_->run(workqueue, this); } |
92e059d8 | 179 | |
c7912668 ILT |
180 | // The debugging name. |
181 | std::string | |
182 | get_name() const | |
183 | { return this->name_; } | |
184 | ||
92e059d8 ILT |
185 | private: |
186 | Task_function(const Task_function&); | |
187 | Task_function& operator=(const Task_function&); | |
188 | ||
189 | Task_function_runner* runner_; | |
190 | Task_token* blocker_; | |
c7912668 | 191 | const char* name_; |
92e059d8 ILT |
192 | }; |
193 | ||
17a1d0a9 | 194 | // The workqueue itself. |
bae7f79e | 195 | |
17a1d0a9 | 196 | class Workqueue_threader; |
bae7f79e ILT |
197 | |
198 | class Workqueue | |
199 | { | |
200 | public: | |
201 | Workqueue(const General_options&); | |
202 | ~Workqueue(); | |
203 | ||
204 | // Add a new task to the work queue. | |
205 | void | |
206 | queue(Task*); | |
207 | ||
da769d56 ILT |
208 | // Add a new task to the work queue which should run soon. If the |
209 | // task is ready, it will be run before any tasks added using | |
210 | // queue(). | |
92e059d8 | 211 | void |
da769d56 ILT |
212 | queue_soon(Task*); |
213 | ||
214 | // Add a new task to the work queue which should run next if it is | |
215 | // ready. | |
216 | void | |
217 | queue_next(Task*); | |
92e059d8 | 218 | |
17a1d0a9 ILT |
219 | // Process all the tasks on the work queue. This function runs |
220 | // until all tasks have completed. The argument is the thread | |
221 | // number, used only for debugging. | |
bae7f79e | 222 | void |
17a1d0a9 | 223 | process(int); |
bae7f79e | 224 | |
17a1d0a9 ILT |
225 | // Set the desired thread count--the number of threads we want to |
226 | // have running. | |
fe9a4c12 ILT |
227 | void |
228 | set_thread_count(int); | |
229 | ||
15f8229b ILT |
230 | // Add a new blocker to an existing Task_token. This must be done |
231 | // with the workqueue lock held. This should not be done routinely, | |
232 | // only in special circumstances. | |
233 | void | |
234 | add_blocker(Task_token*); | |
235 | ||
bae7f79e ILT |
236 | private: |
237 | // This class can not be copied. | |
238 | Workqueue(const Workqueue&); | |
239 | Workqueue& operator=(const Workqueue&); | |
240 | ||
17a1d0a9 | 241 | // Add a task to a queue. |
c7912668 | 242 | void |
da769d56 | 243 | add_to_queue(Task_list* queue, Task* t, bool front); |
bae7f79e | 244 | |
17a1d0a9 ILT |
245 | // Find a runnable task, or wait for one. |
246 | Task* | |
247 | find_runnable_or_wait(int thread_number); | |
bae7f79e ILT |
248 | |
249 | // Find a runnable task. | |
c7912668 | 250 | Task* |
17a1d0a9 | 251 | find_runnable(); |
bae7f79e | 252 | |
17a1d0a9 ILT |
253 | // Find a runnable task in a list. |
254 | Task* | |
255 | find_runnable_in_list(Task_list*); | |
bae7f79e | 256 | |
17a1d0a9 | 257 | // Find an run a task. |
c7912668 | 258 | bool |
17a1d0a9 | 259 | find_and_run_task(int); |
c7912668 | 260 | |
17a1d0a9 ILT |
261 | // Release the locks for a Task. Return the next Task to run. |
262 | Task* | |
263 | release_locks(Task*, Task_locker*); | |
bae7f79e | 264 | |
17a1d0a9 ILT |
265 | // Store T into *PRET, or queue it as appropriate. |
266 | bool | |
267 | return_or_queue(Task* t, bool is_blocker, Task** pret); | |
268 | ||
269 | // Return whether to cancel this thread. | |
270 | bool | |
dcd8d12e | 271 | should_cancel_thread(int thread_number); |
bae7f79e | 272 | |
17a1d0a9 ILT |
273 | // Master Workqueue lock. This controls access to the following |
274 | // member variables. | |
275 | Lock lock_; | |
c7912668 ILT |
276 | // List of tasks to execute soon. |
277 | Task_list first_tasks_; | |
278 | // List of tasks to execute after the ones in first_tasks_. | |
bae7f79e | 279 | Task_list tasks_; |
bae7f79e ILT |
280 | // Number of tasks currently running. |
281 | int running_; | |
17a1d0a9 ILT |
282 | // Number of tasks waiting for a lock to release. |
283 | int waiting_; | |
284 | // Condition variable associated with lock_. This is signalled when | |
285 | // there may be a new Task to execute. | |
286 | Condvar condvar_; | |
287 | ||
288 | // The threading implementation. This is set at construction time | |
289 | // and not changed thereafter. | |
290 | Workqueue_threader* threader_; | |
bae7f79e ILT |
291 | }; |
292 | ||
293 | } // End namespace gold. | |
294 | ||
295 | #endif // !defined(GOLD_WORKQUEUE_H) |