mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
a490793037
Sooooo many of these had incorrect or strange main module includes. I have manually inspected all of these, and fixed the main module include to be the nearest plausible thing I could find. If you own or care about any of these source files, I encourage you to take some time and check that these edits were sensible. I can't have broken anything (I strictly added headers, and reordered them, never removed), but they may not be the headers you'd really like to identify as containing the API being implemented. Many forward declarations and missing includes were added to a header files to allow them to parse cleanly when included first. The main module rule does in fact have its merits. =] llvm-svn: 169131
148 lines
4.0 KiB
C++
148 lines
4.0 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 implements llvm_start_multithreaded() and friends.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Support/Threading.h"
|
|
#include "llvm/Config/config.h"
|
|
#include "llvm/Support/Atomic.h"
|
|
#include "llvm/Support/Mutex.h"
|
|
#include <cassert>
|
|
|
|
using namespace llvm;
|
|
|
|
static bool multithreaded_mode = false;
|
|
|
|
static sys::Mutex* global_lock = 0;
|
|
|
|
bool llvm::llvm_start_multithreaded() {
|
|
#if LLVM_ENABLE_THREADS != 0
|
|
assert(!multithreaded_mode && "Already multithreaded!");
|
|
multithreaded_mode = true;
|
|
global_lock = new sys::Mutex(true);
|
|
|
|
// We fence here to ensure that all initialization is complete BEFORE we
|
|
// return from llvm_start_multithreaded().
|
|
sys::MemoryFence();
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void llvm::llvm_stop_multithreaded() {
|
|
#if LLVM_ENABLE_THREADS != 0
|
|
assert(multithreaded_mode && "Not currently multithreaded!");
|
|
|
|
// We fence here to insure that all threaded operations are complete BEFORE we
|
|
// return from llvm_stop_multithreaded().
|
|
sys::MemoryFence();
|
|
|
|
multithreaded_mode = false;
|
|
delete global_lock;
|
|
#endif
|
|
}
|
|
|
|
bool llvm::llvm_is_multithreaded() {
|
|
return multithreaded_mode;
|
|
}
|
|
|
|
void llvm::llvm_acquire_global_lock() {
|
|
if (multithreaded_mode) global_lock->acquire();
|
|
}
|
|
|
|
void llvm::llvm_release_global_lock() {
|
|
if (multithreaded_mode) global_lock->release();
|
|
}
|
|
|
|
#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 0;
|
|
}
|
|
|
|
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, 0);
|
|
|
|
error:
|
|
::pthread_attr_destroy(&Attr);
|
|
}
|
|
#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32)
|
|
#include "Windows/Windows.h"
|
|
#include <process.h>
|
|
|
|
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
|