source: webkit/trunk/JavaScriptCore/wtf/ThreadingPthreads.cpp@ 38975

Last change on this file since 38975 was 38411, checked in by [email protected], 17 years ago

Reviewed by Darin Alder.

https://bugs.webkit.org/show_bug.cgi?id=21810
Remove use of static C++ objects that are destroyed at exit time (destructors)

Create DEFINE_STATIC_LOCAL macro. Change static local objects to leak to avoid
exit-time destructor. Update code that was changed to fix this issue that ran
into a gcc bug (<rdar://problem/6354696> Codegen issue with C++ static reference
in gcc build 5465). Also typdefs for template types needed to be added in some
cases so the type could make it through the macro successfully.

Basically code of the form:
static T m;
becomes:
DEFINE_STATIC_LOCAL(T, m, ());

Also any code of the form:
static T& m = *new T;
also becomes:
DEFINE_STATIC_LOCAL(T, m, ());

  • Property svn:eol-style set to native
File size: 7.3 KB
Line 
1/*
2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Justin Haygood ([email protected])
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#include "config.h"
30#include "Threading.h"
31
32#include "StdLibExtras.h"
33
34#if USE(PTHREADS)
35
36#include "HashMap.h"
37#include "MainThread.h"
38#include "MathExtras.h"
39
40#include <errno.h>
41#include <sys/time.h>
42
43namespace WTF {
44
45typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
46
47static Mutex* atomicallyInitializedStaticMutex;
48
49#if !PLATFORM(DARWIN)
50static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread.
51#endif
52
53static Mutex& threadMapMutex()
54{
55 DEFINE_STATIC_LOCAL(Mutex, mutex, ());
56 return mutex;
57}
58
59void initializeThreading()
60{
61 if (!atomicallyInitializedStaticMutex) {
62 atomicallyInitializedStaticMutex = new Mutex;
63 threadMapMutex();
64 wtf_random_init();
65#if !PLATFORM(DARWIN)
66 mainThreadIdentifier = currentThread();
67#endif
68 initializeMainThread();
69 }
70}
71
72void lockAtomicallyInitializedStaticMutex()
73{
74 ASSERT(atomicallyInitializedStaticMutex);
75 atomicallyInitializedStaticMutex->lock();
76}
77
78void unlockAtomicallyInitializedStaticMutex()
79{
80 atomicallyInitializedStaticMutex->unlock();
81}
82
83static ThreadMap& threadMap()
84{
85 DEFINE_STATIC_LOCAL(ThreadMap, map, ());
86 return map;
87}
88
89static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle)
90{
91 MutexLocker locker(threadMapMutex());
92
93 static ThreadIdentifier identifierCount = 1;
94
95 threadMap().add(identifierCount, pthreadHandle);
96
97 return identifierCount++;
98}
99
100static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
101{
102 MutexLocker locker(threadMapMutex());
103
104 ThreadMap::iterator i = threadMap().begin();
105 for (; i != threadMap().end(); ++i) {
106 if (pthread_equal(i->second, pthreadHandle))
107 return i->first;
108 }
109
110 return 0;
111}
112
113static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
114{
115 MutexLocker locker(threadMapMutex());
116
117 return threadMap().get(id);
118}
119
120static void clearPthreadHandleForIdentifier(ThreadIdentifier id)
121{
122 MutexLocker locker(threadMapMutex());
123
124 ASSERT(threadMap().contains(id));
125
126 threadMap().remove(id);
127}
128
129ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
130{
131 pthread_t threadHandle;
132 if (pthread_create(&threadHandle, NULL, entryPoint, data)) {
133 LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
134 return 0;
135 }
136
137 ThreadIdentifier threadID = establishIdentifierForPthreadHandle(threadHandle);
138 return threadID;
139}
140
141#if PLATFORM(MAC)
142// This function is deprecated but needs to be kept around for backward
143// compatibility. Use the 3-argument version of createThread above instead.
144ThreadIdentifier createThread(ThreadFunction entryPoint, void* data)
145{
146 return createThread(entryPoint, data, 0);
147}
148#endif
149
150int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
151{
152 ASSERT(threadID);
153
154 pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
155
156 int joinResult = pthread_join(pthreadHandle, result);
157 if (joinResult == EDEADLK)
158 LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
159
160 clearPthreadHandleForIdentifier(threadID);
161 return joinResult;
162}
163
164void detachThread(ThreadIdentifier threadID)
165{
166 ASSERT(threadID);
167
168 pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
169
170 pthread_detach(pthreadHandle);
171
172 clearPthreadHandleForIdentifier(threadID);
173}
174
175ThreadIdentifier currentThread()
176{
177 pthread_t currentThread = pthread_self();
178 if (ThreadIdentifier id = identifierByPthreadHandle(currentThread))
179 return id;
180 return establishIdentifierForPthreadHandle(currentThread);
181}
182
183bool isMainThread()
184{
185#if PLATFORM(DARWIN)
186 return pthread_main_np();
187#else
188 return currentThread() == mainThreadIdentifier;
189#endif
190}
191
192Mutex::Mutex()
193{
194 pthread_mutex_init(&m_mutex, NULL);
195}
196
197Mutex::~Mutex()
198{
199 pthread_mutex_destroy(&m_mutex);
200}
201
202void Mutex::lock()
203{
204 if (pthread_mutex_lock(&m_mutex) != 0)
205 ASSERT(false);
206}
207
208bool Mutex::tryLock()
209{
210 int result = pthread_mutex_trylock(&m_mutex);
211
212 if (result == 0)
213 return true;
214 else if (result == EBUSY)
215 return false;
216
217 ASSERT(false);
218 return false;
219}
220
221void Mutex::unlock()
222{
223 if (pthread_mutex_unlock(&m_mutex) != 0)
224 ASSERT(false);
225}
226
227ThreadCondition::ThreadCondition()
228{
229 pthread_cond_init(&m_condition, NULL);
230}
231
232ThreadCondition::~ThreadCondition()
233{
234 pthread_cond_destroy(&m_condition);
235}
236
237void ThreadCondition::wait(Mutex& mutex)
238{
239 if (pthread_cond_wait(&m_condition, &mutex.impl()) != 0)
240 ASSERT(false);
241}
242
243bool ThreadCondition::timedWait(Mutex& mutex, double secondsToWait)
244{
245 if (secondsToWait < 0.0) {
246 wait(mutex);
247 return true;
248 }
249
250 int intervalSeconds = static_cast<int>(secondsToWait);
251 int intervalMicroseconds = static_cast<int>((secondsToWait - intervalSeconds) * 1000000.0);
252
253 // Current time comes in sec/microsec
254 timeval currentTime;
255 gettimeofday(&currentTime, NULL);
256
257 // Target time comes in sec/nanosec
258 timespec targetTime;
259 targetTime.tv_sec = currentTime.tv_sec + intervalSeconds;
260 targetTime.tv_nsec = (currentTime.tv_usec + intervalMicroseconds) * 1000;
261 if (targetTime.tv_nsec > 1000000000) {
262 targetTime.tv_nsec -= 1000000000;
263 targetTime.tv_sec++;
264 }
265
266 return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
267}
268
269void ThreadCondition::signal()
270{
271 if (pthread_cond_signal(&m_condition) != 0)
272 ASSERT(false);
273}
274
275void ThreadCondition::broadcast()
276{
277 if (pthread_cond_broadcast(&m_condition) != 0)
278 ASSERT(false);
279}
280
281} // namespace WTF
282
283#endif // USE(PTHREADS)
Note: See TracBrowser for help on using the repository browser.