llvm-project/llvm/lib/Support/Mutex.cpp

128 lines
3.3 KiB
C++
Raw Normal View History

//===- 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"
[Support] - Add bad alloc error handler for handling allocation malfunctions 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
2017-07-12 00:45:30 +08:00
#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)
{
2012-01-15 09:09:13 +08:00
// Declare the pthread_mutex data structures
pthread_mutex_t* mutex =
static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t)));
[Support] - Add bad alloc error handler for handling allocation malfunctions 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
2017-07-12 00:45:30 +08:00
if (mutex == nullptr)
report_bad_alloc_error("Mutex allocation failed");
2012-01-15 09:09:13 +08:00
pthread_mutexattr_t attr;
// Initialize the mutex attributes
int errorcode = pthread_mutexattr_init(&attr);
assert(errorcode == 0); (void)errorcode;
2012-01-15 09:09:13 +08:00
// 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);
2012-01-15 09:09:13 +08:00
// Initialize the mutex
errorcode = pthread_mutex_init(mutex, &attr);
assert(errorcode == 0);
2012-01-15 09:09:13 +08:00
// Destroy the attributes
errorcode = pthread_mutexattr_destroy(&attr);
assert(errorcode == 0);
2012-01-15 09:09:13 +08:00
// Assign the data member
data_ = mutex;
}
// Destruct a Mutex
MutexImpl::~MutexImpl()
{
2012-01-15 09:09:13 +08:00
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
assert(mutex != nullptr);
2012-01-15 09:09:13 +08:00
pthread_mutex_destroy(mutex);
free(mutex);
}
bool
MutexImpl::acquire()
{
2012-01-15 09:09:13 +08:00
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
assert(mutex != nullptr);
2012-01-15 09:09:13 +08:00
int errorcode = pthread_mutex_lock(mutex);
return errorcode == 0;
}
bool
MutexImpl::release()
{
2012-01-15 09:09:13 +08:00
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
assert(mutex != nullptr);
2012-01-15 09:09:13 +08:00
int errorcode = pthread_mutex_unlock(mutex);
return errorcode == 0;
}
bool
MutexImpl::tryacquire()
{
2012-01-15 09:09:13 +08:00
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
assert(mutex != nullptr);
2012-01-15 09:09:13 +08:00
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