1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "crazy_linker_globals.h"
6
7 #include <new>
8
9 #include <pthread.h>
10
11 namespace crazy {
12
13 namespace {
14
15 // Implement lazy-initialized static variable without a C++ constructor.
16 // Note that this is leaky, i.e. the instance is never destroyed, but
17 // this was also the case with the previous heap-based implementation.
18 pthread_once_t s_once = PTHREAD_ONCE_INIT;
19
20 union Storage {
21 char dummy;
22 Globals globals;
23
Storage()24 Storage() {}
~Storage()25 ~Storage() {}
26 };
27
28 Storage s_storage;
29
InitGlobals()30 void InitGlobals() {
31 new (&s_storage.globals) Globals();
32 }
33
34 } // namespace
35
Globals()36 Globals::Globals() {
37 // IMPORTANT: The global mutex must be recursive to allow for recursive
38 // dlopen() calls. See http://crbug.com/843804.
39 pthread_mutexattr_t attr;
40 pthread_mutexattr_init(&attr);
41 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
42 pthread_mutex_init(&lock_, &attr);
43 pthread_mutexattr_destroy(&attr);
44
45 search_paths_.ResetFromEnv("LD_LIBRARY_PATH");
46 }
47
~Globals()48 Globals::~Globals() {
49 pthread_mutex_destroy(&lock_);
50 }
51
Lock()52 void Globals::Lock() {
53 pthread_mutex_lock(&lock_);
54 }
55
Unlock()56 void Globals::Unlock() {
57 pthread_mutex_unlock(&lock_);
58 }
59
60 // static
Get()61 Globals* Globals::Get() {
62 pthread_once(&s_once, InitGlobals);
63 return &s_storage.globals;
64 }
65
66 // TECHNICAL NOTE: The mutex below does not have to be recursive, unlike the
67 // other one, because it should be only operated on during the following
68 // operations:
69 //
70 // - Acquired before, and released after, calling one of the system linker's
71 // functions that may modify the global link-map. Note that these should
72 // never call back into the crazy linker.
73 //
74 // - Acquired and released when modifying the global link-map in
75 // crazy::RDebug::AddEntryImpl() and crazy::RDebug::DelEntryImpl(). These
76 // do not call the system linker, or make any kind of recursive calls.
77
78 // static
79 pthread_mutex_t ScopedLinkMapLocker::s_lock_ = PTHREAD_MUTEX_INITIALIZER;
80
81 } // namespace crazy
82