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