153ca1f3190680f3e86aebe0f72f7918d63f71e0dCharles Davis//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==// 24c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// 34c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// The LLVM Compiler Infrastructure 44c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// 54c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// This file is distributed under the University of Illinois Open Source 64c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// License. See LICENSE.TXT for details. 74c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// 84c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//===----------------------------------------------------------------------===// 94c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// 10c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines// This file defines helper functions for running LLVM in a multi-threaded 11c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines// environment. 124c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// 134c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//===----------------------------------------------------------------------===// 144c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson 151f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Threading.h" 16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Config/config.h" 171f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Atomic.h" 181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h" 19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/thread.h" 204c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson#include <cassert> 21643dda1d625d286dc53283d22152ba56926a1f25Owen Anderson 224c7ac18fc9e9af51ea6362871589c13263526d7aOwen Andersonusing namespace llvm; 234c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson 24c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesbool llvm::llvm_is_multithreaded() { 2508b73a30bbb6407c7b48a734a29f65f4c8ddd782Dylan Noblesmith#if LLVM_ENABLE_THREADS != 0 264c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson return true; 274c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson#else 284c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson return false; 294c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson#endif 304c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson} 314c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson 3208b73a30bbb6407c7b48a734a29f65f4c8ddd782Dylan Noblesmith#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) 33ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar#include <pthread.h> 34ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 35ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbarstruct ThreadInfo { 36ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar void (*UserFn)(void *); 37ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar void *UserData; 38ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar}; 39ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbarstatic void *ExecuteOnThread_Dispatch(void *Arg) { 40ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg); 41ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar TI->UserFn(TI->UserData); 42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 43ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar} 44ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 45ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbarvoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 46ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar unsigned RequestedStackSize) { 47ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar ThreadInfo Info = { Fn, UserData }; 48ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar pthread_attr_t Attr; 49ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar pthread_t Thread; 50ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 51ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar // Construct the attributes object. 52ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar if (::pthread_attr_init(&Attr) != 0) 53ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar return; 54ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 55ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar // Set the requested stack size, if given. 56ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar if (RequestedStackSize != 0) { 57ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0) 58ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar goto error; 59ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar } 60ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 61ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar // Construct and execute the thread. 62ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0) 63ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar goto error; 64ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 65ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar // Wait for the thread and clean up. 66dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ::pthread_join(Thread, nullptr); 671f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer 68ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar error: 69ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar ::pthread_attr_destroy(&Attr); 70ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar} 7108b73a30bbb6407c7b48a734a29f65f4c8ddd782Dylan Noblesmith#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32) 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "Windows/WindowsSupport.h" 7392ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi#include <process.h> 74ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Windows will at times define MemoryFence. 76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#ifdef MemoryFence 77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#undef MemoryFence 78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#endif 79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 8092ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumistruct ThreadInfo { 8192ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi void (*func)(void*); 8292ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi void *param; 8392ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi}; 84ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 8592ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumistatic unsigned __stdcall ThreadCallback(void *param) { 8692ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param); 8792ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi info->func(info->param); 8892ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi 8992ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi return 0; 9092ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi} 91ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 92ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbarvoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 93ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar unsigned RequestedStackSize) { 9492ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi struct ThreadInfo param = { Fn, UserData }; 9592ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi 9692ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi HANDLE hThread = (HANDLE)::_beginthreadex(NULL, 9792ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi RequestedStackSize, ThreadCallback, 9892ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi ¶m, 0, NULL); 9992ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi 10092ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi if (hThread) { 10192ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi // We actually don't care whether the wait succeeds or fails, in 10292ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi // the same way we don't care whether the pthread_join call succeeds 10392ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi // or fails. There's not much we could do if this were to fail. But 10492ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi // on success, this call will wait until the thread finishes executing 10592ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi // before returning. 10692ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi (void)::WaitForSingleObject(hThread, INFINITE); 10792ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi ::CloseHandle(hThread); 10892ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi } 10992ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi} 11092ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi#else 11192ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi// Support for non-Win32, non-pthread implementation. 11292ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumivoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 11392ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi unsigned RequestedStackSize) { 114ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar (void) RequestedStackSize; 115ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar Fn(UserData); 116ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar} 117ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar 118ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar#endif 119