+#ifndef ENABLE_THREADS
+
+ // If there is no threads support, we don't need to use pthread_once.
+ if (!this->was_run_)
+ this->internal_run(arg);
+
+#else // defined(ENABLE_THREADS)
+
+ if (parameters->options_valid() && !parameters->options().threads())
+ {
+ // If we are not using threads, we don't need to lock.
+ if (!this->was_run_)
+ this->internal_run(arg);
+ return;
+ }
+
+ // If we have the sync builtins, use them to skip the lock if the
+ // value has already been initialized.
+#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+ while (true)
+ {
+ if (__sync_bool_compare_and_swap(&this->was_run_lock_, 0, 1))
+ break;
+ }
+ bool was_run = this->was_run_;
+ while (true)
+ {
+ if (__sync_bool_compare_and_swap(&this->was_run_lock_, 1, 0))
+ break;
+ }
+ if (was_run)
+ return;
+#endif
+
+ // Since we can't pass parameters to routines called by
+ // pthread_once, we use a static variable: once_pointer. This in
+ // turns means that we need to use a mutex to control access to
+ // once_pointer.
+
+ int err = pthread_mutex_lock(&once_pointer_control);
+ if (err != 0)
+ gold_fatal(_("pthread_mutex_lock failed: %s"), strerror(err));
+
+ once_pointer = this;
+ once_arg = arg;
+
+ err = pthread_once(this->once_->once_control(), c_run_once);
+ if (err != 0)
+ gold_fatal(_("pthread_once failed: %s"), strerror(err));
+
+ once_pointer = NULL;
+ once_arg = NULL;
+
+ err = pthread_mutex_unlock(&once_pointer_control);
+ if (err != 0)
+ gold_fatal(_("pthread_mutex_unlock failed: %s"), strerror(err));
+
+#endif // defined(ENABLE_THREADS)