gold-threads.cc revision 1.1
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 35namespace gold 36{ 37 38class Condvar_impl_nothreads; 39 40// The non-threaded version of Lock_impl. 41 42class 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 74class Condvar_impl_threads; 75 76// The threaded version of Lock_impl. 77 78class 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 88private: 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 98Lock_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 119Lock_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 126void 127Lock_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 134void 135Lock_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 146Lock::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 160Lock::~Lock() 161{ 162 delete this->lock_; 163} 164 165// The non-threaded version of Condvar_impl. 166 167class 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 193class 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 216Condvar_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 223Condvar_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 230void 231Condvar_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 239void 240Condvar_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 247void 248Condvar_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 259Condvar::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 274Condvar::~Condvar() 275{ 276 delete this->condvar_; 277} 278 279} // End namespace gold. 280