1 // gold-threads.cc -- thread support for gold 2 3 // Copyright 2006, 2007, 2008 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 23 #include "gold.h" 24 25 #include <cstring> 26 27 #ifdef ENABLE_THREADS 28 #include <pthread.h> 29 #endif 30 31 #include "options.h" 32 #include "parameters.h" 33 #include "gold-threads.h" 34 35 namespace gold 36 { 37 38 class Condvar_impl_nothreads; 39 40 // The non-threaded version of Lock_impl. 41 42 class Lock_impl_nothreads : public Lock_impl 43 { 44 public: 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(); 83 84 void acquire(); 85 86 void release(); 87 88 private: 89 // This class can not be copied. 90 Lock_impl_threads(const Lock_impl_threads&); 91 Lock_impl_threads& operator=(const Lock_impl_threads&); 92 93 friend class Condvar_impl_threads; 94 95 pthread_mutex_t mutex_; 96 }; 97 98 Lock_impl_threads::Lock_impl_threads() 99 { 100 pthread_mutexattr_t attr; 101 int err = pthread_mutexattr_init(&attr); 102 if (err != 0) 103 gold_fatal(_("pthead_mutextattr_init failed: %s"), strerror(err)); 104 #ifdef PTHREAD_MUTEXT_ADAPTIVE_NP 105 err = pthread_mutextattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); 106 if (err != 0) 107 gold_fatal(_("pthread_mutextattr_settype failed: %s"), strerror(err)); 108 #endif 109 110 err = pthread_mutex_init (&this->mutex_, &attr); 111 if (err != 0) 112 gold_fatal(_("pthread_mutex_init failed: %s"), strerror(err)); 113 114 err = pthread_mutexattr_destroy(&attr); 115 if (err != 0) 116 gold_fatal(_("pthread_mutexattr_destroy failed: %s"), strerror(err)); 117 } 118 119 Lock_impl_threads::~Lock_impl_threads() 120 { 121 int err = pthread_mutex_destroy(&this->mutex_); 122 if (err != 0) 123 gold_fatal(_("pthread_mutex_destroy failed: %s"), strerror(err)); 124 } 125 126 void 127 Lock_impl_threads::acquire() 128 { 129 int err = pthread_mutex_lock(&this->mutex_); 130 if (err != 0) 131 gold_fatal(_("pthread_mutex_lock failed: %s"), strerror(err)); 132 } 133 134 void 135 Lock_impl_threads::release() 136 { 137 int err = pthread_mutex_unlock(&this->mutex_); 138 if (err != 0) 139 gold_fatal(_("pthread_mutex_unlock failed: %s"), strerror(err)); 140 } 141 142 #endif // defined(ENABLE_THREADS) 143 144 // Class Lock. 145 146 Lock::Lock() 147 { 148 if (!parameters->options().threads()) 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 } 158 } 159 160 Lock::~Lock() 161 { 162 delete this->lock_; 163 } 164 165 // The non-threaded version of Condvar_impl. 166 167 class Condvar_impl_nothreads : public Condvar_impl 168 { 169 public: 170 Condvar_impl_nothreads() 171 { } 172 173 ~Condvar_impl_nothreads() 174 { } 175 176 void 177 wait(Lock_impl* li) 178 { gold_assert(static_cast<Lock_impl_nothreads*>(li)->acquired_); } 179 180 void 181 signal() 182 { } 183 184 void 185 broadcast() 186 { } 187 }; 188 189 #ifdef ENABLE_THREADS 190 191 // The threaded version of Condvar_impl. 192 193 class Condvar_impl_threads : public Condvar_impl 194 { 195 public: 196 Condvar_impl_threads(); 197 ~Condvar_impl_threads(); 198 199 void 200 wait(Lock_impl*); 201 202 void 203 signal(); 204 205 void 206 broadcast(); 207 208 private: 209 // This class can not be copied. 210 Condvar_impl_threads(const Condvar_impl_threads&); 211 Condvar_impl_threads& operator=(const Condvar_impl_threads&); 212 213 pthread_cond_t cond_; 214 }; 215 216 Condvar_impl_threads::Condvar_impl_threads() 217 { 218 int err = pthread_cond_init(&this->cond_, NULL); 219 if (err != 0) 220 gold_fatal(_("pthread_cond_init failed: %s"), strerror(err)); 221 } 222 223 Condvar_impl_threads::~Condvar_impl_threads() 224 { 225 int err = pthread_cond_destroy(&this->cond_); 226 if (err != 0) 227 gold_fatal(_("pthread_cond_destroy failed: %s"), strerror(err)); 228 } 229 230 void 231 Condvar_impl_threads::wait(Lock_impl* li) 232 { 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)); 237 } 238 239 void 240 Condvar_impl_threads::signal() 241 { 242 int err = pthread_cond_signal(&this->cond_); 243 if (err != 0) 244 gold_fatal(_("pthread_cond_signal failed: %s"), strerror(err)); 245 } 246 247 void 248 Condvar_impl_threads::broadcast() 249 { 250 int err = pthread_cond_broadcast(&this->cond_); 251 if (err != 0) 252 gold_fatal(_("pthread_cond_broadcast failed: %s"), strerror(err)); 253 } 254 255 #endif // defined(ENABLE_THREADS) 256 257 // Methods for Condvar class. 258 259 Condvar::Condvar(Lock& lock) 260 : lock_(lock) 261 { 262 if (!parameters->options().threads()) 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 } 272 } 273 274 Condvar::~Condvar() 275 { 276 delete this->condvar_; 277 } 278 279 } // End namespace gold. 280