mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
7b2e05b496
Summary: Patch by Klaus Kretzschmar We would like to introduce a new type of llvm error handler for handling bad alloc fault situations. LLVM already provides a fatal error handler for serious non-recoverable error situations which by default writes some error information to stderr and calls exit(1) at the end (functions are marked as 'noreturn'). For long running processes (e.g. a server application), exiting the process is not an acceptable option, especially not when the system is in a temporary resource bottleneck with a good chance to recover from this fault situation. In such a situation you would rather throw an exception to stop the current compilation and try to overcome the resource bottleneck. The user should be aware of the problem of throwing an exception in bad alloc situations, e.g. you must not do any allocations in the unwind chain. This is especially true when adding exceptions in existing unfamiliar code (as already stated in the comment of the current fatal error handler) So the new handler can also be used to distinguish from general fatal error situations where recovering is no option. It should be used in cases where a clean unwind after the allocation is guaranteed. This patch contains: - A report_bad_alloc function which calls a user defined bad alloc error handler. If no user handler is registered the report_fatal_error function is called. This function is not marked as 'noreturn'. - A install/restore_bad_alloc_error_handler to install/restore the bad alloc handler. - An example (in Mutex.cpp) where the report_bad_alloc function is called in case of a malloc returns a nullptr. If this patch gets accepted we would create similar patches to fix corresponding malloc/calloc usages in the llvm code. Reviewers: chandlerc, greened, baldrick, rnk Reviewed By: rnk Subscribers: llvm-commits, MatzeB Differential Revision: https://reviews.llvm.org/D34753 llvm-svn: 307673
128 lines
3.3 KiB
C++
128 lines
3.3 KiB
C++
//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- 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 the llvm::sys::Mutex class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Support/Mutex.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Config/config.h"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
//=== WARNING: Implementation here must contain only TRULY operating system
|
|
//=== independent code.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
|
|
// Define all methods as no-ops if threading is explicitly disabled
|
|
namespace llvm {
|
|
using namespace sys;
|
|
MutexImpl::MutexImpl( bool recursive) { }
|
|
MutexImpl::~MutexImpl() { }
|
|
bool MutexImpl::acquire() { return true; }
|
|
bool MutexImpl::release() { return true; }
|
|
bool MutexImpl::tryacquire() { return true; }
|
|
}
|
|
#else
|
|
|
|
#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK)
|
|
|
|
#include <cassert>
|
|
#include <pthread.h>
|
|
#include <stdlib.h>
|
|
|
|
namespace llvm {
|
|
using namespace sys;
|
|
|
|
// Construct a Mutex using pthread calls
|
|
MutexImpl::MutexImpl( bool recursive)
|
|
: data_(nullptr)
|
|
{
|
|
// Declare the pthread_mutex data structures
|
|
pthread_mutex_t* mutex =
|
|
static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t)));
|
|
|
|
if (mutex == nullptr)
|
|
report_bad_alloc_error("Mutex allocation failed");
|
|
|
|
pthread_mutexattr_t attr;
|
|
|
|
// Initialize the mutex attributes
|
|
int errorcode = pthread_mutexattr_init(&attr);
|
|
assert(errorcode == 0); (void)errorcode;
|
|
|
|
// Initialize the mutex as a recursive mutex, if requested, or normal
|
|
// otherwise.
|
|
int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL );
|
|
errorcode = pthread_mutexattr_settype(&attr, kind);
|
|
assert(errorcode == 0);
|
|
|
|
// Initialize the mutex
|
|
errorcode = pthread_mutex_init(mutex, &attr);
|
|
assert(errorcode == 0);
|
|
|
|
// Destroy the attributes
|
|
errorcode = pthread_mutexattr_destroy(&attr);
|
|
assert(errorcode == 0);
|
|
|
|
// Assign the data member
|
|
data_ = mutex;
|
|
}
|
|
|
|
// Destruct a Mutex
|
|
MutexImpl::~MutexImpl()
|
|
{
|
|
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
|
|
assert(mutex != nullptr);
|
|
pthread_mutex_destroy(mutex);
|
|
free(mutex);
|
|
}
|
|
|
|
bool
|
|
MutexImpl::acquire()
|
|
{
|
|
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
|
|
assert(mutex != nullptr);
|
|
|
|
int errorcode = pthread_mutex_lock(mutex);
|
|
return errorcode == 0;
|
|
}
|
|
|
|
bool
|
|
MutexImpl::release()
|
|
{
|
|
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
|
|
assert(mutex != nullptr);
|
|
|
|
int errorcode = pthread_mutex_unlock(mutex);
|
|
return errorcode == 0;
|
|
}
|
|
|
|
bool
|
|
MutexImpl::tryacquire()
|
|
{
|
|
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
|
|
assert(mutex != nullptr);
|
|
|
|
int errorcode = pthread_mutex_trylock(mutex);
|
|
return errorcode == 0;
|
|
}
|
|
|
|
}
|
|
|
|
#elif defined(LLVM_ON_UNIX)
|
|
#include "Unix/Mutex.inc"
|
|
#elif defined( LLVM_ON_WIN32)
|
|
#include "Windows/Mutex.inc"
|
|
#else
|
|
#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp
|
|
#endif
|
|
#endif
|