/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingPthreads.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 393 lines · 288 code · 75 blank · 30 comment · 38 complexity · fdc7d2806b4a9fcc8165d408cd9bc892 MD5 · raw file

  1. /*
  2. * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
  3. * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
  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. #if USE(PTHREADS)
  32. #include "CurrentTime.h"
  33. #include "HashMap.h"
  34. #include "MainThread.h"
  35. #include "RandomNumberSeed.h"
  36. #include "StdLibExtras.h"
  37. #include "ThreadIdentifierDataPthreads.h"
  38. #include "ThreadSpecific.h"
  39. #include "UnusedParam.h"
  40. #include <errno.h>
  41. #if !COMPILER(MSVC)
  42. #include <limits.h>
  43. #include <sys/time.h>
  44. #endif
  45. #if OS(ANDROID)
  46. #include "jni_utility.h"
  47. #endif
  48. namespace WTF {
  49. typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
  50. static Mutex* atomicallyInitializedStaticMutex;
  51. #if !OS(DARWIN) || PLATFORM(CHROMIUM) || USE(WEB_THREAD)
  52. static pthread_t mainThread; // The thread that was the first to call initializeThreading(), which must be the main thread.
  53. #endif
  54. void clearPthreadHandleForIdentifier(ThreadIdentifier);
  55. static Mutex& threadMapMutex()
  56. {
  57. DEFINE_STATIC_LOCAL(Mutex, mutex, ());
  58. return mutex;
  59. }
  60. void initializeThreading()
  61. {
  62. if (!atomicallyInitializedStaticMutex) {
  63. atomicallyInitializedStaticMutex = new Mutex;
  64. threadMapMutex();
  65. initializeRandomNumberGenerator();
  66. #if !OS(DARWIN) || PLATFORM(CHROMIUM) || USE(WEB_THREAD)
  67. mainThread = pthread_self();
  68. #endif
  69. initializeMainThread();
  70. }
  71. }
  72. void lockAtomicallyInitializedStaticMutex()
  73. {
  74. ASSERT(atomicallyInitializedStaticMutex);
  75. atomicallyInitializedStaticMutex->lock();
  76. }
  77. void unlockAtomicallyInitializedStaticMutex()
  78. {
  79. atomicallyInitializedStaticMutex->unlock();
  80. }
  81. static ThreadMap& threadMap()
  82. {
  83. DEFINE_STATIC_LOCAL(ThreadMap, map, ());
  84. return map;
  85. }
  86. static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
  87. {
  88. MutexLocker locker(threadMapMutex());
  89. ThreadMap::iterator i = threadMap().begin();
  90. for (; i != threadMap().end(); ++i) {
  91. if (pthread_equal(i->second, pthreadHandle))
  92. return i->first;
  93. }
  94. return 0;
  95. }
  96. static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
  97. {
  98. ASSERT(!identifierByPthreadHandle(pthreadHandle));
  99. MutexLocker locker(threadMapMutex());
  100. static ThreadIdentifier identifierCount = 1;
  101. threadMap().add(identifierCount, pthreadHandle);
  102. return identifierCount++;
  103. }
  104. static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
  105. {
  106. MutexLocker locker(threadMapMutex());
  107. return threadMap().get(id);
  108. }
  109. void clearPthreadHandleForIdentifier(ThreadIdentifier id)
  110. {
  111. MutexLocker locker(threadMapMutex());
  112. ASSERT(threadMap().contains(id));
  113. threadMap().remove(id);
  114. }
  115. #if OS(ANDROID)
  116. // On the Android platform, threads must be registered with the VM before they run.
  117. struct ThreadData {
  118. ThreadFunction entryPoint;
  119. void* arg;
  120. };
  121. static void* runThreadWithRegistration(void* arg)
  122. {
  123. ThreadData* data = static_cast<ThreadData*>(arg);
  124. JavaVM* vm = JSC::Bindings::getJavaVM();
  125. JNIEnv* env;
  126. void* ret = 0;
  127. if (vm->AttachCurrentThread(&env, 0) == JNI_OK) {
  128. ret = data->entryPoint(data->arg);
  129. vm->DetachCurrentThread();
  130. }
  131. delete data;
  132. return ret;
  133. }
  134. ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
  135. {
  136. pthread_t threadHandle;
  137. ThreadData* threadData = new ThreadData();
  138. threadData->entryPoint = entryPoint;
  139. threadData->arg = data;
  140. if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) {
  141. LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
  142. delete threadData;
  143. return 0;
  144. }
  145. return establishIdentifierForPthreadHandle(threadHandle);
  146. }
  147. #else
  148. ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
  149. {
  150. pthread_t threadHandle;
  151. if (pthread_create(&threadHandle, 0, entryPoint, data)) {
  152. LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
  153. return 0;
  154. }
  155. return establishIdentifierForPthreadHandle(threadHandle);
  156. }
  157. #endif
  158. void initializeCurrentThreadInternal(const char* threadName)
  159. {
  160. #if HAVE(PTHREAD_SETNAME_NP)
  161. pthread_setname_np(threadName);
  162. #else
  163. UNUSED_PARAM(threadName);
  164. #endif
  165. ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
  166. ASSERT(id);
  167. ThreadIdentifierData::initialize(id);
  168. }
  169. int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
  170. {
  171. ASSERT(threadID);
  172. pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
  173. if (!pthreadHandle)
  174. return 0;
  175. int joinResult = pthread_join(pthreadHandle, result);
  176. if (joinResult == EDEADLK)
  177. LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
  178. return joinResult;
  179. }
  180. void detachThread(ThreadIdentifier threadID)
  181. {
  182. ASSERT(threadID);
  183. pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
  184. if (!pthreadHandle)
  185. return;
  186. pthread_detach(pthreadHandle);
  187. }
  188. ThreadIdentifier currentThread()
  189. {
  190. ThreadIdentifier id = ThreadIdentifierData::identifier();
  191. if (id)
  192. return id;
  193. // Not a WTF-created thread, ThreadIdentifier is not established yet.
  194. id = establishIdentifierForPthreadHandle(pthread_self());
  195. ThreadIdentifierData::initialize(id);
  196. return id;
  197. }
  198. bool isMainThread()
  199. {
  200. #if OS(DARWIN) && !PLATFORM(CHROMIUM) && !USE(WEB_THREAD)
  201. return pthread_main_np();
  202. #else
  203. return pthread_equal(pthread_self(), mainThread);
  204. #endif
  205. }
  206. Mutex::Mutex()
  207. {
  208. pthread_mutex_init(&m_mutex, NULL);
  209. }
  210. Mutex::~Mutex()
  211. {
  212. pthread_mutex_destroy(&m_mutex);
  213. }
  214. void Mutex::lock()
  215. {
  216. int result = pthread_mutex_lock(&m_mutex);
  217. ASSERT_UNUSED(result, !result);
  218. }
  219. bool Mutex::tryLock()
  220. {
  221. int result = pthread_mutex_trylock(&m_mutex);
  222. if (result == 0)
  223. return true;
  224. if (result == EBUSY)
  225. return false;
  226. ASSERT_NOT_REACHED();
  227. return false;
  228. }
  229. void Mutex::unlock()
  230. {
  231. int result = pthread_mutex_unlock(&m_mutex);
  232. ASSERT_UNUSED(result, !result);
  233. }
  234. #if HAVE(PTHREAD_RWLOCK)
  235. ReadWriteLock::ReadWriteLock()
  236. {
  237. pthread_rwlock_init(&m_readWriteLock, NULL);
  238. }
  239. ReadWriteLock::~ReadWriteLock()
  240. {
  241. pthread_rwlock_destroy(&m_readWriteLock);
  242. }
  243. void ReadWriteLock::readLock()
  244. {
  245. int result = pthread_rwlock_rdlock(&m_readWriteLock);
  246. ASSERT_UNUSED(result, !result);
  247. }
  248. bool ReadWriteLock::tryReadLock()
  249. {
  250. int result = pthread_rwlock_tryrdlock(&m_readWriteLock);
  251. if (result == 0)
  252. return true;
  253. if (result == EBUSY || result == EAGAIN)
  254. return false;
  255. ASSERT_NOT_REACHED();
  256. return false;
  257. }
  258. void ReadWriteLock::writeLock()
  259. {
  260. int result = pthread_rwlock_wrlock(&m_readWriteLock);
  261. ASSERT_UNUSED(result, !result);
  262. }
  263. bool ReadWriteLock::tryWriteLock()
  264. {
  265. int result = pthread_rwlock_trywrlock(&m_readWriteLock);
  266. if (result == 0)
  267. return true;
  268. if (result == EBUSY || result == EAGAIN)
  269. return false;
  270. ASSERT_NOT_REACHED();
  271. return false;
  272. }
  273. void ReadWriteLock::unlock()
  274. {
  275. int result = pthread_rwlock_unlock(&m_readWriteLock);
  276. ASSERT_UNUSED(result, !result);
  277. }
  278. #endif // HAVE(PTHREAD_RWLOCK)
  279. ThreadCondition::ThreadCondition()
  280. {
  281. pthread_cond_init(&m_condition, NULL);
  282. }
  283. ThreadCondition::~ThreadCondition()
  284. {
  285. pthread_cond_destroy(&m_condition);
  286. }
  287. void ThreadCondition::wait(Mutex& mutex)
  288. {
  289. int result = pthread_cond_wait(&m_condition, &mutex.impl());
  290. ASSERT_UNUSED(result, !result);
  291. }
  292. bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
  293. {
  294. if (absoluteTime < currentTime())
  295. return false;
  296. if (absoluteTime > INT_MAX) {
  297. wait(mutex);
  298. return true;
  299. }
  300. int timeSeconds = static_cast<int>(absoluteTime);
  301. int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
  302. timespec targetTime;
  303. targetTime.tv_sec = timeSeconds;
  304. targetTime.tv_nsec = timeNanoseconds;
  305. return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
  306. }
  307. void ThreadCondition::signal()
  308. {
  309. int result = pthread_cond_signal(&m_condition);
  310. ASSERT_UNUSED(result, !result);
  311. }
  312. void ThreadCondition::broadcast()
  313. {
  314. int result = pthread_cond_broadcast(&m_condition);
  315. ASSERT_UNUSED(result, !result);
  316. }
  317. } // namespace WTF
  318. #endif // USE(PTHREADS)