ThreadingPthreads.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
  3. * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
  4. * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  16. * its contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  20. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "config.h"
  31. #include "Threading.h"
  32. #if USE(PTHREADS)
  33. #include "CurrentTime.h"
  34. #include "DateMath.h"
  35. #include "dtoa.h"
  36. #include "dtoa/cached-powers.h"
  37. #include "HashMap.h"
  38. #include "RandomNumberSeed.h"
  39. #include "StackStats.h"
  40. #include "StdLibExtras.h"
  41. #include "ThreadFunctionInvocation.h"
  42. #include "ThreadIdentifierDataPthreads.h"
  43. #include "ThreadSpecific.h"
  44. #include <wtf/OwnPtr.h>
  45. #include <wtf/PassOwnPtr.h>
  46. #include <wtf/WTFThreadData.h>
  47. #include <errno.h>
  48. #if !COMPILER(MSVC)
  49. #include <limits.h>
  50. #include <sched.h>
  51. #include <sys/time.h>
  52. #endif
  53. #if OS(MAC_OS_X)
  54. #include <objc/objc-auto.h>
  55. #endif
  56. #if OS(ORBIS)
  57. #include <manx/System.h>
  58. #include <pthread_np.h>
  59. #endif
  60. namespace WTF {
  61. class PthreadState {
  62. WTF_MAKE_FAST_ALLOCATED;
  63. public:
  64. enum JoinableState {
  65. Joinable, // The default thread state. The thread can be joined on.
  66. Joined, // Somebody waited on this thread to exit and this thread finally exited. This state is here because there can be a
  67. // period of time between when the thread exits (which causes pthread_join to return and the remainder of waitOnThreadCompletion to run)
  68. // and when threadDidExit is called. We need threadDidExit to take charge and delete the thread data since there's
  69. // nobody else to pick up the slack in this case (since waitOnThreadCompletion has already returned).
  70. Detached // The thread has been detached and can no longer be joined on. At this point, the thread must take care of cleaning up after itself.
  71. };
  72. // Currently all threads created by WTF start out as joinable.
  73. PthreadState(pthread_t handle)
  74. : m_joinableState(Joinable)
  75. , m_didExit(false)
  76. , m_pthreadHandle(handle)
  77. {
  78. }
  79. JoinableState joinableState() { return m_joinableState; }
  80. pthread_t pthreadHandle() { return m_pthreadHandle; }
  81. void didBecomeDetached() { m_joinableState = Detached; }
  82. void didExit() { m_didExit = true; }
  83. void didJoin() { m_joinableState = Joined; }
  84. bool hasExited() { return m_didExit; }
  85. private:
  86. JoinableState m_joinableState;
  87. bool m_didExit;
  88. pthread_t m_pthreadHandle;
  89. };
  90. typedef HashMap<ThreadIdentifier, OwnPtr<PthreadState> > ThreadMap;
  91. static Mutex* atomicallyInitializedStaticMutex;
  92. void unsafeThreadWasDetached(ThreadIdentifier);
  93. void threadDidExit(ThreadIdentifier);
  94. void threadWasJoined(ThreadIdentifier);
  95. static Mutex& threadMapMutex()
  96. {
  97. DEFINE_STATIC_LOCAL(Mutex, mutex, ());
  98. return mutex;
  99. }
  100. #if OS(QNX) && CPU(ARM_THUMB2)
  101. static void enableIEEE754Denormal()
  102. {
  103. // Clear the ARM_VFP_FPSCR_FZ flag in FPSCR.
  104. unsigned fpscr;
  105. asm volatile("vmrs %0, fpscr" : "=r"(fpscr));
  106. fpscr &= ~0x01000000u;
  107. asm volatile("vmsr fpscr, %0" : : "r"(fpscr));
  108. }
  109. #endif
  110. void initializeThreading()
  111. {
  112. if (atomicallyInitializedStaticMutex)
  113. return;
  114. #if OS(QNX) && CPU(ARM_THUMB2)
  115. enableIEEE754Denormal();
  116. #endif
  117. WTF::double_conversion::initialize();
  118. // StringImpl::empty() does not construct its static string in a threadsafe fashion,
  119. // so ensure it has been initialized from here.
  120. StringImpl::empty();
  121. atomicallyInitializedStaticMutex = new Mutex;
  122. threadMapMutex();
  123. initializeRandomNumberGenerator();
  124. ThreadIdentifierData::initializeOnce();
  125. StackStats::initialize();
  126. wtfThreadData();
  127. s_dtoaP5Mutex = new Mutex;
  128. initializeDates();
  129. }
  130. void lockAtomicallyInitializedStaticMutex()
  131. {
  132. ASSERT(atomicallyInitializedStaticMutex);
  133. atomicallyInitializedStaticMutex->lock();
  134. }
  135. void unlockAtomicallyInitializedStaticMutex()
  136. {
  137. atomicallyInitializedStaticMutex->unlock();
  138. }
  139. static ThreadMap& threadMap()
  140. {
  141. DEFINE_STATIC_LOCAL(ThreadMap, map, ());
  142. return map;
  143. }
  144. static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
  145. {
  146. MutexLocker locker(threadMapMutex());
  147. ThreadMap::iterator i = threadMap().begin();
  148. for (; i != threadMap().end(); ++i) {
  149. if (pthread_equal(i->value->pthreadHandle(), pthreadHandle) && !i->value->hasExited())
  150. return i->key;
  151. }
  152. return 0;
  153. }
  154. static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
  155. {
  156. ASSERT(!identifierByPthreadHandle(pthreadHandle));
  157. MutexLocker locker(threadMapMutex());
  158. static ThreadIdentifier identifierCount = 1;
  159. threadMap().add(identifierCount, adoptPtr(new PthreadState(pthreadHandle)));
  160. return identifierCount++;
  161. }
  162. static pthread_t pthreadHandleForIdentifierWithLockAlreadyHeld(ThreadIdentifier id)
  163. {
  164. return threadMap().get(id)->pthreadHandle();
  165. }
  166. static void* wtfThreadEntryPoint(void* param)
  167. {
  168. // Balanced by .leakPtr() in createThreadInternal.
  169. OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param));
  170. invocation->function(invocation->data);
  171. return 0;
  172. }
  173. #if OS(ORBIS)
  174. static size_t stackSize(const char* name)
  175. {
  176. if (!strcmp(name, "WebCore: Worker"))
  177. return 512 * 1024;
  178. return 64 * 1024;
  179. }
  180. #endif
  181. ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* name)
  182. {
  183. OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
  184. pthread_t threadHandle;
  185. pthread_attr_t* attr = 0;
  186. #if OS(ORBIS)
  187. pthread_attr_t aAttr;
  188. attr = &aAttr;
  189. pthread_attr_init(attr);
  190. pthread_attr_setstacksize(attr, stackSize(name));
  191. #elif OS(PSP2)
  192. pthread_attr_t aAttr;
  193. if (name) {
  194. attr = &aAttr;
  195. pthread_attr_init(attr);
  196. pthread_attr_setname_sce(attr, name);
  197. }
  198. #endif
  199. if (pthread_create(&threadHandle, attr, wtfThreadEntryPoint, invocation.get())) {
  200. LOG_ERROR("Failed to create pthread at entry point %p with data %p", wtfThreadEntryPoint, invocation.get());
  201. return 0;
  202. }
  203. #if OS(ORBIS)
  204. pthread_attr_destroy(attr);
  205. pthread_setprio(threadHandle, Manx::System::defaultThreadPriority());
  206. #elif OS(PSP2)
  207. if (attr)
  208. pthread_attr_destroy(attr);
  209. #endif
  210. // Balanced by adoptPtr() in wtfThreadEntryPoint.
  211. ThreadFunctionInvocation* leakedInvocation = invocation.leakPtr();
  212. UNUSED_PARAM(leakedInvocation);
  213. return establishIdentifierForPthreadHandle(threadHandle);
  214. }
  215. void initializeCurrentThreadInternal(const char* threadName)
  216. {
  217. #if HAVE(PTHREAD_SETNAME_NP)
  218. pthread_setname_np(threadName);
  219. #elif OS(QNX)
  220. pthread_setname_np(pthread_self(), threadName);
  221. #elif OS(ORBIS)
  222. pthread_set_name_np(pthread_self(), threadName);
  223. #else
  224. UNUSED_PARAM(threadName);
  225. #endif
  226. #if OS(MAC_OS_X)
  227. // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C
  228. // garbage collector in case API implementations use garbage-collected memory.
  229. objc_registerThreadWithCollector();
  230. #endif
  231. #if OS(QNX) && CPU(ARM_THUMB2)
  232. enableIEEE754Denormal();
  233. #endif
  234. ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
  235. ASSERT(id);
  236. ThreadIdentifierData::initialize(id);
  237. }
  238. int waitForThreadCompletion(ThreadIdentifier threadID)
  239. {
  240. pthread_t pthreadHandle;
  241. ASSERT(threadID);
  242. {
  243. // We don't want to lock across the call to join, since that can block our thread and cause deadlock.
  244. MutexLocker locker(threadMapMutex());
  245. pthreadHandle = pthreadHandleForIdentifierWithLockAlreadyHeld(threadID);
  246. ASSERT(pthreadHandle);
  247. }
  248. int joinResult = pthread_join(pthreadHandle, 0);
  249. if (joinResult == EDEADLK)
  250. LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
  251. else if (joinResult)
  252. LOG_ERROR("ThreadIdentifier %u was unable to be joined.\n", threadID);
  253. MutexLocker locker(threadMapMutex());
  254. PthreadState* state = threadMap().get(threadID);
  255. ASSERT(state);
  256. ASSERT(state->joinableState() == PthreadState::Joinable);
  257. // The thread has already exited, so clean up after it.
  258. if (state->hasExited())
  259. threadMap().remove(threadID);
  260. // The thread hasn't exited yet, so don't clean anything up. Just signal that we've already joined on it so that it will clean up after itself.
  261. else
  262. state->didJoin();
  263. return joinResult;
  264. }
  265. void detachThread(ThreadIdentifier threadID)
  266. {
  267. ASSERT(threadID);
  268. MutexLocker locker(threadMapMutex());
  269. pthread_t pthreadHandle = pthreadHandleForIdentifierWithLockAlreadyHeld(threadID);
  270. ASSERT(pthreadHandle);
  271. int detachResult = pthread_detach(pthreadHandle);
  272. if (detachResult)
  273. LOG_ERROR("ThreadIdentifier %u was unable to be detached\n", threadID);
  274. PthreadState* state = threadMap().get(threadID);
  275. ASSERT(state);
  276. if (state->hasExited())
  277. threadMap().remove(threadID);
  278. else
  279. threadMap().get(threadID)->didBecomeDetached();
  280. }
  281. void threadDidExit(ThreadIdentifier threadID)
  282. {
  283. MutexLocker locker(threadMapMutex());
  284. PthreadState* state = threadMap().get(threadID);
  285. ASSERT(state);
  286. state->didExit();
  287. if (state->joinableState() != PthreadState::Joinable)
  288. threadMap().remove(threadID);
  289. }
  290. void yield()
  291. {
  292. sched_yield();
  293. }
  294. ThreadIdentifier currentThread()
  295. {
  296. ThreadIdentifier id = ThreadIdentifierData::identifier();
  297. if (id)
  298. return id;
  299. // Not a WTF-created thread, ThreadIdentifier is not established yet.
  300. id = establishIdentifierForPthreadHandle(pthread_self());
  301. ThreadIdentifierData::initialize(id);
  302. return id;
  303. }
  304. Mutex::Mutex()
  305. {
  306. pthread_mutexattr_t attr;
  307. pthread_mutexattr_init(&attr);
  308. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
  309. int result = pthread_mutex_init(&m_mutex, &attr);
  310. ASSERT_UNUSED(result, !result);
  311. pthread_mutexattr_destroy(&attr);
  312. }
  313. Mutex::~Mutex()
  314. {
  315. int result = pthread_mutex_destroy(&m_mutex);
  316. ASSERT_UNUSED(result, !result);
  317. }
  318. void Mutex::lock()
  319. {
  320. int result = pthread_mutex_lock(&m_mutex);
  321. ASSERT_UNUSED(result, !result);
  322. }
  323. bool Mutex::tryLock()
  324. {
  325. int result = pthread_mutex_trylock(&m_mutex);
  326. if (result == 0)
  327. return true;
  328. if (result == EBUSY)
  329. return false;
  330. ASSERT_NOT_REACHED();
  331. return false;
  332. }
  333. void Mutex::unlock()
  334. {
  335. int result = pthread_mutex_unlock(&m_mutex);
  336. ASSERT_UNUSED(result, !result);
  337. }
  338. #if USE(MANX_COND_INIT)
  339. ThreadCondition::ThreadCondition(Mutex& mutex)
  340. {
  341. int result = pthread_cond_init_sce(&m_condition, &mutex.impl(), NULL);
  342. ASSERT_UNUSED(result, !result);
  343. }
  344. #else
  345. ThreadCondition::ThreadCondition()
  346. {
  347. pthread_cond_init(&m_condition, NULL);
  348. }
  349. #endif
  350. ThreadCondition::~ThreadCondition()
  351. {
  352. pthread_cond_destroy(&m_condition);
  353. }
  354. void ThreadCondition::wait(Mutex& mutex)
  355. {
  356. int result = pthread_cond_wait(&m_condition, &mutex.impl());
  357. ASSERT_UNUSED(result, !result);
  358. }
  359. bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
  360. {
  361. if (absoluteTime < currentTime())
  362. return false;
  363. #if PLATFORM(MANX)
  364. if (absoluteTime > std::numeric_limits<time_t>::max()) {
  365. #else
  366. if (absoluteTime > INT_MAX) {
  367. #endif
  368. wait(mutex);
  369. return true;
  370. }
  371. #if PLATFORM(MANX)
  372. time_t timeSeconds = static_cast<time_t>(absoluteTime);
  373. long timeNanoseconds = static_cast<long>((absoluteTime - timeSeconds) * 1E9);
  374. #else
  375. int timeSeconds = static_cast<int>(absoluteTime);
  376. int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
  377. #endif
  378. timespec targetTime;
  379. targetTime.tv_sec = timeSeconds;
  380. targetTime.tv_nsec = timeNanoseconds;
  381. return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
  382. }
  383. void ThreadCondition::signal()
  384. {
  385. int result = pthread_cond_signal(&m_condition);
  386. ASSERT_UNUSED(result, !result);
  387. }
  388. void ThreadCondition::broadcast()
  389. {
  390. int result = pthread_cond_broadcast(&m_condition);
  391. ASSERT_UNUSED(result, !result);
  392. }
  393. } // namespace WTF
  394. #endif // USE(PTHREADS)