mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-15 09:56:02 +00:00

Analysis of fails in the case of out of memory errors can be tricky on Windows. Such error emerges at the point where memory allocation function fails, but manifests itself when null pointer is used. These two points may be distant from each other. Besides, next runs may not exhibit allocation error. Usual programming practice does not require checking result of 'operator new' because it throws 'std::bad_alloc' in the case of allocation error. However, LLVM is usually built with exceptions turned off, so 'new' can return null pointer. This change installs custom new handler, which causes fatal error in the case of out of memory. The handler is installed automatically prior to call to 'main' during construction of a static object defined in 'lib/Support/ErrorHandling.cpp'. If the application does not use this file, the handler may be installed manually by a call to 'llvm::install_out_of_memory_new_handler', declared in 'include/llvm/Support/ErrorHandling.h". There are calls to C allocation functions, malloc, calloc and realloc. They are used for interoperability with C code, when allocated object has variable size and when it is necessary to avoid call of constructors. In many calls the result is not checked against null pointer. To simplify checks, new functions are defined in the namespace 'llvm' with the same names as these C function. These functions produce fatal error if allocation fails. User should use 'llvm::malloc' instead of 'std::malloc' in order to use the safe variant. This change replaces 'std::malloc' in the cases when the result of allocation function is not checked against null pointer. Finally, there are plain C code, that uses malloc and similar functions. If the result is not checked, assert statements are added. Differential Revision: https://reviews.llvm.org/D43010 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@325224 91177308-0d34-0410-b5e6-96231b3b80d8
126 lines
3.2 KiB
C++
126 lines
3.2 KiB
C++
//===- RWMutex.cpp - Reader/Writer 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::RWMutex class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Support/Allocator.h"
|
|
#include "llvm/Support/RWMutex.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
|
|
|
|
using namespace llvm;
|
|
using namespace sys;
|
|
|
|
RWMutexImpl::RWMutexImpl() = default;
|
|
RWMutexImpl::~RWMutexImpl() = default;
|
|
|
|
bool RWMutexImpl::reader_acquire() { return true; }
|
|
bool RWMutexImpl::reader_release() { return true; }
|
|
bool RWMutexImpl::writer_acquire() { return true; }
|
|
bool RWMutexImpl::writer_release() { return true; }
|
|
|
|
#else
|
|
|
|
#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
|
|
|
|
#include <cassert>
|
|
#include <cstdlib>
|
|
#include <pthread.h>
|
|
|
|
using namespace llvm;
|
|
using namespace sys;
|
|
|
|
// Construct a RWMutex using pthread calls
|
|
RWMutexImpl::RWMutexImpl()
|
|
{
|
|
// Declare the pthread_rwlock data structures
|
|
pthread_rwlock_t* rwlock =
|
|
static_cast<pthread_rwlock_t*>(llvm::malloc(sizeof(pthread_rwlock_t)));
|
|
|
|
#ifdef __APPLE__
|
|
// Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
|
|
bzero(rwlock, sizeof(pthread_rwlock_t));
|
|
#endif
|
|
|
|
// Initialize the rwlock
|
|
int errorcode = pthread_rwlock_init(rwlock, nullptr);
|
|
(void)errorcode;
|
|
assert(errorcode == 0);
|
|
|
|
// Assign the data member
|
|
data_ = rwlock;
|
|
}
|
|
|
|
// Destruct a RWMutex
|
|
RWMutexImpl::~RWMutexImpl()
|
|
{
|
|
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
|
|
assert(rwlock != nullptr);
|
|
pthread_rwlock_destroy(rwlock);
|
|
free(rwlock);
|
|
}
|
|
|
|
bool
|
|
RWMutexImpl::reader_acquire()
|
|
{
|
|
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
|
|
assert(rwlock != nullptr);
|
|
|
|
int errorcode = pthread_rwlock_rdlock(rwlock);
|
|
return errorcode == 0;
|
|
}
|
|
|
|
bool
|
|
RWMutexImpl::reader_release()
|
|
{
|
|
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
|
|
assert(rwlock != nullptr);
|
|
|
|
int errorcode = pthread_rwlock_unlock(rwlock);
|
|
return errorcode == 0;
|
|
}
|
|
|
|
bool
|
|
RWMutexImpl::writer_acquire()
|
|
{
|
|
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
|
|
assert(rwlock != nullptr);
|
|
|
|
int errorcode = pthread_rwlock_wrlock(rwlock);
|
|
return errorcode == 0;
|
|
}
|
|
|
|
bool
|
|
RWMutexImpl::writer_release()
|
|
{
|
|
pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
|
|
assert(rwlock != nullptr);
|
|
|
|
int errorcode = pthread_rwlock_unlock(rwlock);
|
|
return errorcode == 0;
|
|
}
|
|
|
|
#elif defined(LLVM_ON_UNIX)
|
|
#include "Unix/RWMutex.inc"
|
|
#elif defined( LLVM_ON_WIN32)
|
|
#include "Windows/RWMutex.inc"
|
|
#else
|
|
#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp
|
|
#endif
|
|
#endif
|