1*fae548d3Szrj // gold-threads.cc -- thread support for gold
2*fae548d3Szrj 
3*fae548d3Szrj // Copyright (C) 2006-2020 Free Software Foundation, Inc.
4*fae548d3Szrj // Written by Ian Lance Taylor <iant@google.com>.
5*fae548d3Szrj 
6*fae548d3Szrj // This file is part of gold.
7*fae548d3Szrj 
8*fae548d3Szrj // This program is free software; you can redistribute it and/or modify
9*fae548d3Szrj // it under the terms of the GNU General Public License as published by
10*fae548d3Szrj // the Free Software Foundation; either version 3 of the License, or
11*fae548d3Szrj // (at your option) any later version.
12*fae548d3Szrj 
13*fae548d3Szrj // This program is distributed in the hope that it will be useful,
14*fae548d3Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
15*fae548d3Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*fae548d3Szrj // GNU General Public License for more details.
17*fae548d3Szrj 
18*fae548d3Szrj // You should have received a copy of the GNU General Public License
19*fae548d3Szrj // along with this program; if not, write to the Free Software
20*fae548d3Szrj // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*fae548d3Szrj // MA 02110-1301, USA.
22*fae548d3Szrj 
23*fae548d3Szrj #include "gold.h"
24*fae548d3Szrj 
25*fae548d3Szrj #include <cstring>
26*fae548d3Szrj 
27*fae548d3Szrj #ifdef ENABLE_THREADS
28*fae548d3Szrj #include <pthread.h>
29*fae548d3Szrj #endif
30*fae548d3Szrj 
31*fae548d3Szrj #include "options.h"
32*fae548d3Szrj #include "parameters.h"
33*fae548d3Szrj #include "gold-threads.h"
34*fae548d3Szrj 
35*fae548d3Szrj namespace gold
36*fae548d3Szrj {
37*fae548d3Szrj 
38*fae548d3Szrj class Condvar_impl_nothreads;
39*fae548d3Szrj 
40*fae548d3Szrj // The non-threaded version of Lock_impl.
41*fae548d3Szrj 
42*fae548d3Szrj class Lock_impl_nothreads : public Lock_impl
43*fae548d3Szrj {
44*fae548d3Szrj  public:
Lock_impl_nothreads()45*fae548d3Szrj   Lock_impl_nothreads()
46*fae548d3Szrj     : acquired_(false)
47*fae548d3Szrj   { }
48*fae548d3Szrj 
~Lock_impl_nothreads()49*fae548d3Szrj   ~Lock_impl_nothreads()
50*fae548d3Szrj   { gold_assert(!this->acquired_); }
51*fae548d3Szrj 
52*fae548d3Szrj   void
acquire()53*fae548d3Szrj   acquire()
54*fae548d3Szrj   {
55*fae548d3Szrj     gold_assert(!this->acquired_);
56*fae548d3Szrj     this->acquired_ = true;
57*fae548d3Szrj   }
58*fae548d3Szrj 
59*fae548d3Szrj   void
release()60*fae548d3Szrj   release()
61*fae548d3Szrj   {
62*fae548d3Szrj     gold_assert(this->acquired_);
63*fae548d3Szrj     this->acquired_ = false;
64*fae548d3Szrj   }
65*fae548d3Szrj 
66*fae548d3Szrj  private:
67*fae548d3Szrj   friend class Condvar_impl_nothreads;
68*fae548d3Szrj 
69*fae548d3Szrj   bool acquired_;
70*fae548d3Szrj };
71*fae548d3Szrj 
72*fae548d3Szrj #ifdef ENABLE_THREADS
73*fae548d3Szrj 
74*fae548d3Szrj class Condvar_impl_threads;
75*fae548d3Szrj 
76*fae548d3Szrj // The threaded version of Lock_impl.
77*fae548d3Szrj 
78*fae548d3Szrj class Lock_impl_threads : public Lock_impl
79*fae548d3Szrj {
80*fae548d3Szrj  public:
81*fae548d3Szrj   Lock_impl_threads();
82*fae548d3Szrj   ~Lock_impl_threads();
83*fae548d3Szrj 
84*fae548d3Szrj   void acquire();
85*fae548d3Szrj 
86*fae548d3Szrj   void release();
87*fae548d3Szrj 
88*fae548d3Szrj private:
89*fae548d3Szrj   // This class can not be copied.
90*fae548d3Szrj   Lock_impl_threads(const Lock_impl_threads&);
91*fae548d3Szrj   Lock_impl_threads& operator=(const Lock_impl_threads&);
92*fae548d3Szrj 
93*fae548d3Szrj   friend class Condvar_impl_threads;
94*fae548d3Szrj 
95*fae548d3Szrj   pthread_mutex_t mutex_;
96*fae548d3Szrj };
97*fae548d3Szrj 
Lock_impl_threads()98*fae548d3Szrj Lock_impl_threads::Lock_impl_threads()
99*fae548d3Szrj {
100*fae548d3Szrj   pthread_mutexattr_t attr;
101*fae548d3Szrj   int err = pthread_mutexattr_init(&attr);
102*fae548d3Szrj   if (err != 0)
103*fae548d3Szrj     gold_fatal(_("pthead_mutexattr_init failed: %s"), strerror(err));
104*fae548d3Szrj #ifdef PTHREAD_MUTEX_ADAPTIVE_NP
105*fae548d3Szrj   err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
106*fae548d3Szrj   if (err != 0)
107*fae548d3Szrj     gold_fatal(_("pthread_mutexattr_settype failed: %s"), strerror(err));
108*fae548d3Szrj #endif
109*fae548d3Szrj 
110*fae548d3Szrj   err = pthread_mutex_init(&this->mutex_, &attr);
111*fae548d3Szrj   if (err != 0)
112*fae548d3Szrj     gold_fatal(_("pthread_mutex_init failed: %s"), strerror(err));
113*fae548d3Szrj 
114*fae548d3Szrj   err = pthread_mutexattr_destroy(&attr);
115*fae548d3Szrj   if (err != 0)
116*fae548d3Szrj     gold_fatal(_("pthread_mutexattr_destroy failed: %s"), strerror(err));
117*fae548d3Szrj }
118*fae548d3Szrj 
~Lock_impl_threads()119*fae548d3Szrj Lock_impl_threads::~Lock_impl_threads()
120*fae548d3Szrj {
121*fae548d3Szrj   int err = pthread_mutex_destroy(&this->mutex_);
122*fae548d3Szrj   if (err != 0)
123*fae548d3Szrj     gold_fatal(_("pthread_mutex_destroy failed: %s"), strerror(err));
124*fae548d3Szrj }
125*fae548d3Szrj 
126*fae548d3Szrj void
acquire()127*fae548d3Szrj Lock_impl_threads::acquire()
128*fae548d3Szrj {
129*fae548d3Szrj   int err = pthread_mutex_lock(&this->mutex_);
130*fae548d3Szrj   if (err != 0)
131*fae548d3Szrj     gold_fatal(_("pthread_mutex_lock failed: %s"), strerror(err));
132*fae548d3Szrj }
133*fae548d3Szrj 
134*fae548d3Szrj void
release()135*fae548d3Szrj Lock_impl_threads::release()
136*fae548d3Szrj {
137*fae548d3Szrj   int err = pthread_mutex_unlock(&this->mutex_);
138*fae548d3Szrj   if (err != 0)
139*fae548d3Szrj     gold_fatal(_("pthread_mutex_unlock failed: %s"), strerror(err));
140*fae548d3Szrj }
141*fae548d3Szrj 
142*fae548d3Szrj #endif // defined(ENABLE_THREADS)
143*fae548d3Szrj 
144*fae548d3Szrj // Class Lock.
145*fae548d3Szrj 
Lock()146*fae548d3Szrj Lock::Lock()
147*fae548d3Szrj {
148*fae548d3Szrj   if (!parameters->options().threads())
149*fae548d3Szrj     this->lock_ = new Lock_impl_nothreads;
150*fae548d3Szrj   else
151*fae548d3Szrj     {
152*fae548d3Szrj #ifdef ENABLE_THREADS
153*fae548d3Szrj       this->lock_ = new Lock_impl_threads;
154*fae548d3Szrj #else
155*fae548d3Szrj       gold_unreachable();
156*fae548d3Szrj #endif
157*fae548d3Szrj     }
158*fae548d3Szrj }
159*fae548d3Szrj 
~Lock()160*fae548d3Szrj Lock::~Lock()
161*fae548d3Szrj {
162*fae548d3Szrj   delete this->lock_;
163*fae548d3Szrj }
164*fae548d3Szrj 
165*fae548d3Szrj // The non-threaded version of Condvar_impl.
166*fae548d3Szrj 
167*fae548d3Szrj class Condvar_impl_nothreads : public Condvar_impl
168*fae548d3Szrj {
169*fae548d3Szrj  public:
Condvar_impl_nothreads()170*fae548d3Szrj   Condvar_impl_nothreads()
171*fae548d3Szrj   { }
172*fae548d3Szrj 
~Condvar_impl_nothreads()173*fae548d3Szrj   ~Condvar_impl_nothreads()
174*fae548d3Szrj   { }
175*fae548d3Szrj 
176*fae548d3Szrj   void
wait(Lock_impl * li)177*fae548d3Szrj   wait(Lock_impl* li)
178*fae548d3Szrj   { gold_assert(static_cast<Lock_impl_nothreads*>(li)->acquired_); }
179*fae548d3Szrj 
180*fae548d3Szrj   void
signal()181*fae548d3Szrj   signal()
182*fae548d3Szrj   { }
183*fae548d3Szrj 
184*fae548d3Szrj   void
broadcast()185*fae548d3Szrj   broadcast()
186*fae548d3Szrj   { }
187*fae548d3Szrj };
188*fae548d3Szrj 
189*fae548d3Szrj #ifdef ENABLE_THREADS
190*fae548d3Szrj 
191*fae548d3Szrj // The threaded version of Condvar_impl.
192*fae548d3Szrj 
193*fae548d3Szrj class Condvar_impl_threads : public Condvar_impl
194*fae548d3Szrj {
195*fae548d3Szrj  public:
196*fae548d3Szrj   Condvar_impl_threads();
197*fae548d3Szrj   ~Condvar_impl_threads();
198*fae548d3Szrj 
199*fae548d3Szrj   void
200*fae548d3Szrj   wait(Lock_impl*);
201*fae548d3Szrj 
202*fae548d3Szrj   void
203*fae548d3Szrj   signal();
204*fae548d3Szrj 
205*fae548d3Szrj   void
206*fae548d3Szrj   broadcast();
207*fae548d3Szrj 
208*fae548d3Szrj  private:
209*fae548d3Szrj   // This class can not be copied.
210*fae548d3Szrj   Condvar_impl_threads(const Condvar_impl_threads&);
211*fae548d3Szrj   Condvar_impl_threads& operator=(const Condvar_impl_threads&);
212*fae548d3Szrj 
213*fae548d3Szrj   pthread_cond_t cond_;
214*fae548d3Szrj };
215*fae548d3Szrj 
Condvar_impl_threads()216*fae548d3Szrj Condvar_impl_threads::Condvar_impl_threads()
217*fae548d3Szrj {
218*fae548d3Szrj   int err = pthread_cond_init(&this->cond_, NULL);
219*fae548d3Szrj   if (err != 0)
220*fae548d3Szrj     gold_fatal(_("pthread_cond_init failed: %s"), strerror(err));
221*fae548d3Szrj }
222*fae548d3Szrj 
~Condvar_impl_threads()223*fae548d3Szrj Condvar_impl_threads::~Condvar_impl_threads()
224*fae548d3Szrj {
225*fae548d3Szrj   int err = pthread_cond_destroy(&this->cond_);
226*fae548d3Szrj   if (err != 0)
227*fae548d3Szrj     gold_fatal(_("pthread_cond_destroy failed: %s"), strerror(err));
228*fae548d3Szrj }
229*fae548d3Szrj 
230*fae548d3Szrj void
wait(Lock_impl * li)231*fae548d3Szrj Condvar_impl_threads::wait(Lock_impl* li)
232*fae548d3Szrj {
233*fae548d3Szrj   Lock_impl_threads* lit = static_cast<Lock_impl_threads*>(li);
234*fae548d3Szrj   int err = pthread_cond_wait(&this->cond_, &lit->mutex_);
235*fae548d3Szrj   if (err != 0)
236*fae548d3Szrj     gold_fatal(_("pthread_cond_wait failed: %s"), strerror(err));
237*fae548d3Szrj }
238*fae548d3Szrj 
239*fae548d3Szrj void
signal()240*fae548d3Szrj Condvar_impl_threads::signal()
241*fae548d3Szrj {
242*fae548d3Szrj   int err = pthread_cond_signal(&this->cond_);
243*fae548d3Szrj   if (err != 0)
244*fae548d3Szrj     gold_fatal(_("pthread_cond_signal failed: %s"), strerror(err));
245*fae548d3Szrj }
246*fae548d3Szrj 
247*fae548d3Szrj void
broadcast()248*fae548d3Szrj Condvar_impl_threads::broadcast()
249*fae548d3Szrj {
250*fae548d3Szrj   int err = pthread_cond_broadcast(&this->cond_);
251*fae548d3Szrj   if (err != 0)
252*fae548d3Szrj     gold_fatal(_("pthread_cond_broadcast failed: %s"), strerror(err));
253*fae548d3Szrj }
254*fae548d3Szrj 
255*fae548d3Szrj #endif // defined(ENABLE_THREADS)
256*fae548d3Szrj 
257*fae548d3Szrj // Methods for Condvar class.
258*fae548d3Szrj 
Condvar(Lock & lock)259*fae548d3Szrj Condvar::Condvar(Lock& lock)
260*fae548d3Szrj   : lock_(lock)
261*fae548d3Szrj {
262*fae548d3Szrj   if (!parameters->options().threads())
263*fae548d3Szrj     this->condvar_ = new Condvar_impl_nothreads;
264*fae548d3Szrj   else
265*fae548d3Szrj     {
266*fae548d3Szrj #ifdef ENABLE_THREADS
267*fae548d3Szrj       this->condvar_ = new Condvar_impl_threads;
268*fae548d3Szrj #else
269*fae548d3Szrj       gold_unreachable();
270*fae548d3Szrj #endif
271*fae548d3Szrj     }
272*fae548d3Szrj }
273*fae548d3Szrj 
~Condvar()274*fae548d3Szrj Condvar::~Condvar()
275*fae548d3Szrj {
276*fae548d3Szrj   delete this->condvar_;
277*fae548d3Szrj }
278*fae548d3Szrj 
279*fae548d3Szrj #ifdef ENABLE_THREADS
280*fae548d3Szrj 
281*fae548d3Szrj // Class Once_initialize.  This exists to hold a pthread_once_t
282*fae548d3Szrj // structure for Once.
283*fae548d3Szrj 
284*fae548d3Szrj class Once_initialize
285*fae548d3Szrj {
286*fae548d3Szrj  public:
Once_initialize()287*fae548d3Szrj   Once_initialize()
288*fae548d3Szrj     : once_(PTHREAD_ONCE_INIT)
289*fae548d3Szrj   { }
290*fae548d3Szrj 
291*fae548d3Szrj   // Return a pointer to the pthread_once_t variable.
292*fae548d3Szrj   pthread_once_t*
once_control()293*fae548d3Szrj   once_control()
294*fae548d3Szrj   { return &this->once_; }
295*fae548d3Szrj 
296*fae548d3Szrj  private:
297*fae548d3Szrj   pthread_once_t once_;
298*fae548d3Szrj };
299*fae548d3Szrj 
300*fae548d3Szrj #endif // defined(ENABLE_THREADS)
301*fae548d3Szrj 
302*fae548d3Szrj #ifdef ENABLE_THREADS
303*fae548d3Szrj 
304*fae548d3Szrj // A single lock which controls access to once_pointer.  This is used
305*fae548d3Szrj // because we can't pass parameters to functions passed to
306*fae548d3Szrj // pthread_once.
307*fae548d3Szrj 
308*fae548d3Szrj static pthread_mutex_t once_pointer_control = PTHREAD_MUTEX_INITIALIZER;
309*fae548d3Szrj 
310*fae548d3Szrj // A pointer to Once structure we want to run.  Access to this is
311*fae548d3Szrj // controlled by once_pointer_control.
312*fae548d3Szrj 
313*fae548d3Szrj static Once* once_pointer;
314*fae548d3Szrj 
315*fae548d3Szrj // The argument to pass to the Once structure.  Access to this is
316*fae548d3Szrj // controlled by once_pointer_control.
317*fae548d3Szrj 
318*fae548d3Szrj static void* once_arg;
319*fae548d3Szrj 
320*fae548d3Szrj // A routine passed to pthread_once which runs the Once pointer.
321*fae548d3Szrj 
322*fae548d3Szrj extern "C"
323*fae548d3Szrj {
324*fae548d3Szrj 
325*fae548d3Szrj static void
c_run_once(void)326*fae548d3Szrj c_run_once(void)
327*fae548d3Szrj {
328*fae548d3Szrj   once_pointer->internal_run(once_arg);
329*fae548d3Szrj }
330*fae548d3Szrj 
331*fae548d3Szrj }
332*fae548d3Szrj 
333*fae548d3Szrj #endif // defined(ENABLE_THREADS)
334*fae548d3Szrj 
335*fae548d3Szrj // Class Once.
336*fae548d3Szrj 
Once()337*fae548d3Szrj Once::Once()
338*fae548d3Szrj   : was_run_(false)
339*fae548d3Szrj #if defined(ENABLE_THREADS) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
340*fae548d3Szrj     , was_run_lock_(0)
341*fae548d3Szrj #endif
342*fae548d3Szrj {
343*fae548d3Szrj #ifndef ENABLE_THREADS
344*fae548d3Szrj   this->once_ = NULL;
345*fae548d3Szrj #else
346*fae548d3Szrj   this->once_ = new Once_initialize();
347*fae548d3Szrj #endif
348*fae548d3Szrj }
349*fae548d3Szrj 
350*fae548d3Szrj // Run the function once.
351*fae548d3Szrj 
352*fae548d3Szrj void
run_once(void * arg)353*fae548d3Szrj Once::run_once(void* arg)
354*fae548d3Szrj {
355*fae548d3Szrj #ifndef ENABLE_THREADS
356*fae548d3Szrj 
357*fae548d3Szrj   // If there is no threads support, we don't need to use pthread_once.
358*fae548d3Szrj   if (!this->was_run_)
359*fae548d3Szrj     this->internal_run(arg);
360*fae548d3Szrj 
361*fae548d3Szrj #else // defined(ENABLE_THREADS)
362*fae548d3Szrj 
363*fae548d3Szrj   if (parameters->options_valid() && !parameters->options().threads())
364*fae548d3Szrj     {
365*fae548d3Szrj       // If we are not using threads, we don't need to lock.
366*fae548d3Szrj       if (!this->was_run_)
367*fae548d3Szrj 	this->internal_run(arg);
368*fae548d3Szrj       return;
369*fae548d3Szrj     }
370*fae548d3Szrj 
371*fae548d3Szrj   // If we have the sync builtins, use them to skip the lock if the
372*fae548d3Szrj   // value has already been initialized.
373*fae548d3Szrj #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
374*fae548d3Szrj   while (true)
375*fae548d3Szrj     {
376*fae548d3Szrj       if (__sync_bool_compare_and_swap(&this->was_run_lock_, 0, 1))
377*fae548d3Szrj 	break;
378*fae548d3Szrj     }
379*fae548d3Szrj   bool was_run = this->was_run_;
380*fae548d3Szrj   while (true)
381*fae548d3Szrj     {
382*fae548d3Szrj       if (__sync_bool_compare_and_swap(&this->was_run_lock_, 1, 0))
383*fae548d3Szrj 	break;
384*fae548d3Szrj     }
385*fae548d3Szrj   if (was_run)
386*fae548d3Szrj     return;
387*fae548d3Szrj #endif
388*fae548d3Szrj 
389*fae548d3Szrj   // Since we can't pass parameters to routines called by
390*fae548d3Szrj   // pthread_once, we use a static variable: once_pointer.  This in
391*fae548d3Szrj   // turns means that we need to use a mutex to control access to
392*fae548d3Szrj   // once_pointer.
393*fae548d3Szrj 
394*fae548d3Szrj   int err = pthread_mutex_lock(&once_pointer_control);
395*fae548d3Szrj   if (err != 0)
396*fae548d3Szrj     gold_fatal(_("pthread_mutex_lock failed: %s"), strerror(err));
397*fae548d3Szrj 
398*fae548d3Szrj   once_pointer = this;
399*fae548d3Szrj   once_arg = arg;
400*fae548d3Szrj 
401*fae548d3Szrj   err = pthread_once(this->once_->once_control(), c_run_once);
402*fae548d3Szrj   if (err != 0)
403*fae548d3Szrj     gold_fatal(_("pthread_once failed: %s"), strerror(err));
404*fae548d3Szrj 
405*fae548d3Szrj   once_pointer = NULL;
406*fae548d3Szrj   once_arg = NULL;
407*fae548d3Szrj 
408*fae548d3Szrj   err = pthread_mutex_unlock(&once_pointer_control);
409*fae548d3Szrj   if (err != 0)
410*fae548d3Szrj     gold_fatal(_("pthread_mutex_unlock failed: %s"), strerror(err));
411*fae548d3Szrj 
412*fae548d3Szrj #endif // defined(ENABLE_THREADS)
413*fae548d3Szrj }
414*fae548d3Szrj 
415*fae548d3Szrj // Actually run the function in the child class.  This function will
416*fae548d3Szrj // be run only once.
417*fae548d3Szrj 
418*fae548d3Szrj void
internal_run(void * arg)419*fae548d3Szrj Once::internal_run(void* arg)
420*fae548d3Szrj {
421*fae548d3Szrj   this->do_run_once(arg);
422*fae548d3Szrj   this->was_run_ = true;
423*fae548d3Szrj }
424*fae548d3Szrj 
425*fae548d3Szrj // Class Initialize_lock.
426*fae548d3Szrj 
427*fae548d3Szrj // Initialize the lock.
428*fae548d3Szrj 
429*fae548d3Szrj bool
initialize()430*fae548d3Szrj Initialize_lock::initialize()
431*fae548d3Szrj {
432*fae548d3Szrj   // We can't initialize the lock until we have read the options.
433*fae548d3Szrj   if (!parameters->options_valid())
434*fae548d3Szrj     return false;
435*fae548d3Szrj   else
436*fae548d3Szrj     {
437*fae548d3Szrj       this->run_once(NULL);
438*fae548d3Szrj       return true;
439*fae548d3Szrj     }
440*fae548d3Szrj }
441*fae548d3Szrj 
442*fae548d3Szrj // Initialize the lock exactly once.
443*fae548d3Szrj 
444*fae548d3Szrj void
do_run_once(void *)445*fae548d3Szrj Initialize_lock::do_run_once(void*)
446*fae548d3Szrj {
447*fae548d3Szrj   *this->pplock_ = new Lock();
448*fae548d3Szrj }
449*fae548d3Szrj 
450*fae548d3Szrj } // End namespace gold.
451