Commit | Line | Data |
---|---|---|
bae7f79e ILT |
1 | // gold-threads.cc -- thread support for gold |
2 | ||
6cb15b7f ILT |
3 | // Copyright 2006, 2007 Free Software Foundation, Inc. |
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 | #include "gold.h" |
24 | ||
fe9a4c12 ILT |
25 | #include <cstring> |
26 | ||
bae7f79e ILT |
27 | #ifdef ENABLE_THREADS |
28 | #include <pthread.h> | |
29 | #endif | |
30 | ||
c7912668 | 31 | #include "parameters.h" |
bae7f79e ILT |
32 | #include "gold-threads.h" |
33 | ||
34 | namespace gold | |
35 | { | |
36 | ||
c7912668 | 37 | class Condvar_impl_nothreads; |
bae7f79e | 38 | |
c7912668 ILT |
39 | // The non-threaded version of Lock_impl. |
40 | ||
41 | class Lock_impl_nothreads : public Lock_impl | |
bae7f79e ILT |
42 | { |
43 | public: | |
c7912668 ILT |
44 | Lock_impl_nothreads() |
45 | : acquired_(false) | |
46 | { } | |
47 | ||
48 | ~Lock_impl_nothreads() | |
49 | { gold_assert(!this->acquired_); } | |
50 | ||
51 | void | |
52 | acquire() | |
53 | { | |
54 | gold_assert(!this->acquired_); | |
55 | this->acquired_ = true; | |
56 | } | |
57 | ||
58 | void | |
59 | release() | |
60 | { | |
61 | gold_assert(this->acquired_); | |
62 | this->acquired_ = false; | |
63 | } | |
64 | ||
65 | private: | |
66 | friend class Condvar_impl_nothreads; | |
67 | ||
68 | bool acquired_; | |
69 | }; | |
70 | ||
71 | #ifdef ENABLE_THREADS | |
72 | ||
73 | class Condvar_impl_threads; | |
74 | ||
75 | // The threaded version of Lock_impl. | |
76 | ||
77 | class Lock_impl_threads : public Lock_impl | |
78 | { | |
79 | public: | |
80 | Lock_impl_threads(); | |
81 | ~Lock_impl_threads(); | |
bae7f79e ILT |
82 | |
83 | void acquire(); | |
84 | ||
85 | void release(); | |
86 | ||
87 | private: | |
88 | // This class can not be copied. | |
c7912668 ILT |
89 | Lock_impl_threads(const Lock_impl_threads&); |
90 | Lock_impl_threads& operator=(const Lock_impl_threads&); | |
bae7f79e | 91 | |
c7912668 | 92 | friend class Condvar_impl_threads; |
bae7f79e | 93 | |
bae7f79e | 94 | pthread_mutex_t mutex_; |
bae7f79e ILT |
95 | }; |
96 | ||
c7912668 | 97 | Lock_impl_threads::Lock_impl_threads() |
bae7f79e ILT |
98 | { |
99 | pthread_mutexattr_t attr; | |
c7912668 ILT |
100 | int err = pthread_mutexattr_init(&attr); |
101 | if (err != 0) | |
102 | gold_fatal(_("pthead_mutextattr_init failed: %s"), strerror(err)); | |
bae7f79e | 103 | #ifdef PTHREAD_MUTEXT_ADAPTIVE_NP |
c7912668 ILT |
104 | err = pthread_mutextattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); |
105 | if (err != 0) | |
106 | gold_fatal(_("pthread_mutextattr_settype failed: %s"), strerror(err)); | |
bae7f79e ILT |
107 | #endif |
108 | ||
c7912668 ILT |
109 | err = pthread_mutex_init (&this->mutex_, &attr); |
110 | if (err != 0) | |
111 | gold_fatal(_("pthread_mutex_init failed: %s"), strerror(err)); | |
bae7f79e | 112 | |
c7912668 ILT |
113 | err = pthread_mutexattr_destroy(&attr); |
114 | if (err != 0) | |
115 | gold_fatal(_("pthread_mutexattr_destroy failed: %s"), strerror(err)); | |
bae7f79e ILT |
116 | } |
117 | ||
c7912668 | 118 | Lock_impl_threads::~Lock_impl_threads() |
bae7f79e | 119 | { |
c7912668 ILT |
120 | int err = pthread_mutex_destroy(&this->mutex_); |
121 | if (err != 0) | |
122 | gold_fatal(_("pthread_mutex_destroy failed: %s"), strerror(err)); | |
bae7f79e ILT |
123 | } |
124 | ||
125 | void | |
c7912668 | 126 | Lock_impl_threads::acquire() |
bae7f79e | 127 | { |
c7912668 ILT |
128 | int err = pthread_mutex_lock(&this->mutex_); |
129 | if (err != 0) | |
130 | gold_fatal(_("pthread_mutex_lock failed: %s"), strerror(err)); | |
bae7f79e ILT |
131 | } |
132 | ||
133 | void | |
c7912668 | 134 | Lock_impl_threads::release() |
bae7f79e | 135 | { |
c7912668 ILT |
136 | int err = pthread_mutex_unlock(&this->mutex_); |
137 | if (err != 0) | |
138 | gold_fatal(_("pthread_mutex_unlock failed: %s"), strerror(err)); | |
bae7f79e ILT |
139 | } |
140 | ||
c7912668 | 141 | #endif // defined(ENABLE_THREADS) |
bae7f79e | 142 | |
c7912668 | 143 | // Class Lock. |
bae7f79e | 144 | |
c7912668 | 145 | Lock::Lock() |
bae7f79e | 146 | { |
c7912668 ILT |
147 | if (!parameters->threads()) |
148 | this->lock_ = new Lock_impl_nothreads; | |
149 | else | |
150 | { | |
151 | #ifdef ENABLE_THREADS | |
152 | this->lock_ = new Lock_impl_threads; | |
153 | #else | |
154 | gold_unreachable(); | |
155 | #endif | |
156 | } | |
bae7f79e ILT |
157 | } |
158 | ||
c7912668 | 159 | Lock::~Lock() |
bae7f79e | 160 | { |
c7912668 | 161 | delete this->lock_; |
bae7f79e ILT |
162 | } |
163 | ||
c7912668 ILT |
164 | // The non-threaded version of Condvar_impl. |
165 | ||
166 | class Condvar_impl_nothreads : public Condvar_impl | |
bae7f79e | 167 | { |
c7912668 ILT |
168 | public: |
169 | Condvar_impl_nothreads() | |
170 | { } | |
bae7f79e | 171 | |
c7912668 ILT |
172 | ~Condvar_impl_nothreads() |
173 | { } | |
bae7f79e | 174 | |
c7912668 ILT |
175 | void |
176 | wait(Lock_impl* li) | |
177 | { gold_assert(static_cast<Lock_impl_nothreads*>(li)->acquired_); } | |
bae7f79e | 178 | |
c7912668 ILT |
179 | void |
180 | signal() | |
181 | { } | |
bae7f79e | 182 | |
c7912668 ILT |
183 | void |
184 | broadcast() | |
185 | { } | |
186 | }; | |
bae7f79e | 187 | |
c7912668 | 188 | #ifdef ENABLE_THREADS |
bae7f79e | 189 | |
c7912668 | 190 | // The threaded version of Condvar_impl. |
bae7f79e | 191 | |
c7912668 | 192 | class Condvar_impl_threads : public Condvar_impl |
bae7f79e ILT |
193 | { |
194 | public: | |
c7912668 ILT |
195 | Condvar_impl_threads(); |
196 | ~Condvar_impl_threads(); | |
bae7f79e | 197 | |
c7912668 ILT |
198 | void |
199 | wait(Lock_impl*); | |
200 | ||
201 | void | |
202 | signal(); | |
203 | ||
204 | void | |
205 | broadcast(); | |
bae7f79e ILT |
206 | |
207 | private: | |
208 | // This class can not be copied. | |
c7912668 ILT |
209 | Condvar_impl_threads(const Condvar_impl_threads&); |
210 | Condvar_impl_threads& operator=(const Condvar_impl_threads&); | |
bae7f79e | 211 | |
bae7f79e | 212 | pthread_cond_t cond_; |
bae7f79e ILT |
213 | }; |
214 | ||
c7912668 | 215 | Condvar_impl_threads::Condvar_impl_threads() |
bae7f79e | 216 | { |
c7912668 ILT |
217 | int err = pthread_cond_init(&this->cond_, NULL); |
218 | if (err != 0) | |
219 | gold_fatal(_("pthread_cond_init failed: %s"), strerror(err)); | |
bae7f79e ILT |
220 | } |
221 | ||
c7912668 | 222 | Condvar_impl_threads::~Condvar_impl_threads() |
bae7f79e | 223 | { |
c7912668 ILT |
224 | int err = pthread_cond_destroy(&this->cond_); |
225 | if (err != 0) | |
226 | gold_fatal(_("pthread_cond_destroy failed: %s"), strerror(err)); | |
bae7f79e ILT |
227 | } |
228 | ||
229 | void | |
c7912668 | 230 | Condvar_impl_threads::wait(Lock_impl* li) |
bae7f79e | 231 | { |
c7912668 ILT |
232 | Lock_impl_threads* lit = static_cast<Lock_impl_threads*>(li); |
233 | int err = pthread_cond_wait(&this->cond_, &lit->mutex_); | |
234 | if (err != 0) | |
235 | gold_fatal(_("pthread_cond_wait failed: %s"), strerror(err)); | |
bae7f79e ILT |
236 | } |
237 | ||
238 | void | |
c7912668 | 239 | Condvar_impl_threads::signal() |
bae7f79e | 240 | { |
c7912668 ILT |
241 | int err = pthread_cond_signal(&this->cond_); |
242 | if (err != 0) | |
243 | gold_fatal(_("pthread_cond_signal failed: %s"), strerror(err)); | |
bae7f79e ILT |
244 | } |
245 | ||
246 | void | |
c7912668 | 247 | Condvar_impl_threads::broadcast() |
bae7f79e | 248 | { |
c7912668 ILT |
249 | int err = pthread_cond_broadcast(&this->cond_); |
250 | if (err != 0) | |
251 | gold_fatal(_("pthread_cond_broadcast failed: %s"), strerror(err)); | |
bae7f79e ILT |
252 | } |
253 | ||
c7912668 | 254 | #endif // defined(ENABLE_THREADS) |
bae7f79e ILT |
255 | |
256 | // Methods for Condvar class. | |
257 | ||
258 | Condvar::Condvar(Lock& lock) | |
259 | : lock_(lock) | |
260 | { | |
c7912668 ILT |
261 | if (!parameters->threads()) |
262 | this->condvar_ = new Condvar_impl_nothreads; | |
263 | else | |
264 | { | |
265 | #ifdef ENABLE_THREADS | |
266 | this->condvar_ = new Condvar_impl_threads; | |
267 | #else | |
268 | gold_unreachable(); | |
269 | #endif | |
270 | } | |
bae7f79e ILT |
271 | } |
272 | ||
273 | Condvar::~Condvar() | |
274 | { | |
275 | delete this->condvar_; | |
276 | } | |
277 | ||
bae7f79e | 278 | } // End namespace gold. |