Home | History | Annotate | Download | only in Support
      1 //===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements the llvm::sys::Mutex class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/Config/config.h"
     15 #include "llvm/Support/Mutex.h"
     16 
     17 //===----------------------------------------------------------------------===//
     18 //=== WARNING: Implementation here must contain only TRULY operating system
     19 //===          independent code.
     20 //===----------------------------------------------------------------------===//
     21 
     22 #if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0
     23 // Define all methods as no-ops if threading is explicitly disabled
     24 namespace llvm {
     25 using namespace sys;
     26 MutexImpl::MutexImpl( bool recursive) { }
     27 MutexImpl::~MutexImpl() { }
     28 bool MutexImpl::acquire() { return true; }
     29 bool MutexImpl::release() { return true; }
     30 bool MutexImpl::tryacquire() { return true; }
     31 }
     32 #else
     33 
     34 #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK)
     35 
     36 #include <cassert>
     37 #include <pthread.h>
     38 #include <stdlib.h>
     39 
     40 namespace llvm {
     41 using namespace sys;
     42 
     43 
     44 // This variable is useful for situations where the pthread library has been
     45 // compiled with weak linkage for its interface symbols. This allows the
     46 // threading support to be turned off by simply not linking against -lpthread.
     47 // In that situation, the value of pthread_mutex_init will be 0 and
     48 // consequently pthread_enabled will be false. In such situations, all the
     49 // pthread operations become no-ops and the functions all return false. If
     50 // pthread_mutex_init does have an address, then mutex support is enabled.
     51 // Note: all LLVM tools will link against -lpthread if its available since it
     52 //       is configured into the LIBS variable.
     53 // Note: this line of code generates a warning if pthread_mutex_init is not
     54 //       declared with weak linkage. It's safe to ignore the warning.
     55 static const bool pthread_enabled = true;
     56 
     57 // Construct a Mutex using pthread calls
     58 MutexImpl::MutexImpl( bool recursive)
     59   : data_(0)
     60 {
     61   if (pthread_enabled)
     62   {
     63     // Declare the pthread_mutex data structures
     64     pthread_mutex_t* mutex =
     65       static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t)));
     66     pthread_mutexattr_t attr;
     67 
     68     // Initialize the mutex attributes
     69     int errorcode = pthread_mutexattr_init(&attr);
     70     assert(errorcode == 0);
     71 
     72     // Initialize the mutex as a recursive mutex, if requested, or normal
     73     // otherwise.
     74     int kind = ( recursive  ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL );
     75     errorcode = pthread_mutexattr_settype(&attr, kind);
     76     assert(errorcode == 0);
     77 
     78 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
     79     // Make it a process local mutex
     80     errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
     81     assert(errorcode == 0);
     82 #endif
     83 
     84     // Initialize the mutex
     85     errorcode = pthread_mutex_init(mutex, &attr);
     86     assert(errorcode == 0);
     87 
     88     // Destroy the attributes
     89     errorcode = pthread_mutexattr_destroy(&attr);
     90     assert(errorcode == 0);
     91 
     92     // Assign the data member
     93     data_ = mutex;
     94   }
     95 }
     96 
     97 // Destruct a Mutex
     98 MutexImpl::~MutexImpl()
     99 {
    100   if (pthread_enabled)
    101   {
    102     pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
    103     assert(mutex != 0);
    104     pthread_mutex_destroy(mutex);
    105     free(mutex);
    106   }
    107 }
    108 
    109 bool
    110 MutexImpl::acquire()
    111 {
    112   if (pthread_enabled)
    113   {
    114     pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
    115     assert(mutex != 0);
    116 
    117     int errorcode = pthread_mutex_lock(mutex);
    118     return errorcode == 0;
    119   } else return false;
    120 }
    121 
    122 bool
    123 MutexImpl::release()
    124 {
    125   if (pthread_enabled)
    126   {
    127     pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
    128     assert(mutex != 0);
    129 
    130     int errorcode = pthread_mutex_unlock(mutex);
    131     return errorcode == 0;
    132   } else return false;
    133 }
    134 
    135 bool
    136 MutexImpl::tryacquire()
    137 {
    138   if (pthread_enabled)
    139   {
    140     pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
    141     assert(mutex != 0);
    142 
    143     int errorcode = pthread_mutex_trylock(mutex);
    144     return errorcode == 0;
    145   } else return false;
    146 }
    147 
    148 }
    149 
    150 #elif defined(LLVM_ON_UNIX)
    151 #include "Unix/Mutex.inc"
    152 #elif defined( LLVM_ON_WIN32)
    153 #include "Windows/Mutex.inc"
    154 #else
    155 #warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp
    156 #endif
    157 #endif
    158