mirror of
https://github.com/RPCS3/llvm.git
synced 2025-04-06 15:21:37 +00:00

Summary: This will be used by ThinLTO to set the amount of backend parallelism, which performs better when restricted to the number of physical cores (on X86 at least, where getHostNumPhysicalCores is currently defined). If not available this falls back to thread::hardware_concurrency. Note I didn't add to the thread class since that is a typedef to std::thread where available. Reviewers: mehdi_amini Subscribers: beanz, llvm-commits, mgorny Differential Revision: https://reviews.llvm.org/D25585 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284180 91177308-0d34-0410-b5e6-96231b3b80d8
127 lines
3.5 KiB
C++
127 lines
3.5 KiB
C++
//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines helper functions for running LLVM in a multi-threaded
|
|
// environment.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Support/Threading.h"
|
|
#include "llvm/Config/config.h"
|
|
#include "llvm/Support/Atomic.h"
|
|
#include "llvm/Support/Host.h"
|
|
#include "llvm/Support/Mutex.h"
|
|
#include "llvm/Support/thread.h"
|
|
#include <cassert>
|
|
|
|
using namespace llvm;
|
|
|
|
bool llvm::llvm_is_multithreaded() {
|
|
#if LLVM_ENABLE_THREADS != 0
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
|
|
#include <pthread.h>
|
|
|
|
struct ThreadInfo {
|
|
void (*UserFn)(void *);
|
|
void *UserData;
|
|
};
|
|
static void *ExecuteOnThread_Dispatch(void *Arg) {
|
|
ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
|
|
TI->UserFn(TI->UserData);
|
|
return nullptr;
|
|
}
|
|
|
|
void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
|
|
unsigned RequestedStackSize) {
|
|
ThreadInfo Info = { Fn, UserData };
|
|
pthread_attr_t Attr;
|
|
pthread_t Thread;
|
|
|
|
// Construct the attributes object.
|
|
if (::pthread_attr_init(&Attr) != 0)
|
|
return;
|
|
|
|
// Set the requested stack size, if given.
|
|
if (RequestedStackSize != 0) {
|
|
if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
|
|
goto error;
|
|
}
|
|
|
|
// Construct and execute the thread.
|
|
if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
|
|
goto error;
|
|
|
|
// Wait for the thread and clean up.
|
|
::pthread_join(Thread, nullptr);
|
|
|
|
error:
|
|
::pthread_attr_destroy(&Attr);
|
|
}
|
|
#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32)
|
|
#include "Windows/WindowsSupport.h"
|
|
#include <process.h>
|
|
|
|
// Windows will at times define MemoryFence.
|
|
#ifdef MemoryFence
|
|
#undef MemoryFence
|
|
#endif
|
|
|
|
struct ThreadInfo {
|
|
void (*func)(void*);
|
|
void *param;
|
|
};
|
|
|
|
static unsigned __stdcall ThreadCallback(void *param) {
|
|
struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
|
|
info->func(info->param);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
|
|
unsigned RequestedStackSize) {
|
|
struct ThreadInfo param = { Fn, UserData };
|
|
|
|
HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
|
|
RequestedStackSize, ThreadCallback,
|
|
¶m, 0, NULL);
|
|
|
|
if (hThread) {
|
|
// We actually don't care whether the wait succeeds or fails, in
|
|
// the same way we don't care whether the pthread_join call succeeds
|
|
// or fails. There's not much we could do if this were to fail. But
|
|
// on success, this call will wait until the thread finishes executing
|
|
// before returning.
|
|
(void)::WaitForSingleObject(hThread, INFINITE);
|
|
::CloseHandle(hThread);
|
|
}
|
|
}
|
|
#else
|
|
// Support for non-Win32, non-pthread implementation.
|
|
void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
|
|
unsigned RequestedStackSize) {
|
|
(void) RequestedStackSize;
|
|
Fn(UserData);
|
|
}
|
|
|
|
#endif
|
|
|
|
unsigned llvm::hardware_physical_concurrency() {
|
|
int NumPhysical = sys::getHostNumPhysicalCores();
|
|
if (NumPhysical == -1)
|
|
return thread::hardware_concurrency();
|
|
return NumPhysical;
|
|
}
|