aboutsummaryrefslogtreecommitdiffstats
path: root/lib/System/Mutex.cpp
blob: 0b7c5b57459730d23ea9800e18a5dfeb53b74e78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//===- 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/Config/config.h"
#include "llvm/System/Mutex.h"
#include "llvm/System/IncludeFile.h"

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0
// Define all methods as no-ops if threading is explicitly disabled
namespace llvm {
using namespace sys;
Mutex::Mutex( bool recursive) { }
Mutex::~Mutex() { }
bool Mutex::acquire() { return true; }
bool Mutex::release() { return true; }
bool Mutex::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;


// This variable is useful for situations where the pthread library has been
// compiled with weak linkage for its interface symbols. This allows the
// threading support to be turned off by simply not linking against -lpthread.
// In that situation, the value of pthread_mutex_init will be 0 and
// consequently pthread_enabled will be false. In such situations, all the
// pthread operations become no-ops and the functions all return false. If
// pthread_mutex_init does have an address, then mutex support is enabled.
// Note: all LLVM tools will link against -lpthread if its available since it
//       is configured into the LIBS variable.
// Note: this line of code generates a warning if pthread_mutex_init is not
//       declared with weak linkage. It's safe to ignore the warning.
static const bool pthread_enabled = true;

// Construct a Mutex using pthread calls
Mutex::Mutex( bool recursive)
  : data_(0)
{
  if (pthread_enabled)
  {
    // Declare the pthread_mutex data structures
    pthread_mutex_t* mutex =
      static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t)));
    pthread_mutexattr_t attr;

    // Initialize the mutex attributes
    int errorcode = pthread_mutexattr_init(&attr);
    assert(errorcode == 0);

    // 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);

#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
    // Make it a process local mutex
    errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
#endif

    // 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
Mutex::~Mutex()
{
  if (pthread_enabled)
  {
    pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>(data_);
    assert(mutex != 0);
    pthread_mutex_destroy(mutex);
    assert(mutex != 0);
  }
}

bool
Mutex::acquire()
{
  if (pthread_enabled)
  {
    pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>(data_);
    assert(mutex != 0);

    int errorcode = pthread_mutex_lock(mutex);
    return errorcode == 0;
  }
  return false;
}

bool
Mutex::release()
{
  if (pthread_enabled)
  {
    pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>(data_);
    assert(mutex != 0);

    int errorcode = pthread_mutex_unlock(mutex);
    return errorcode == 0;
  }
  return false;
}

bool
Mutex::tryacquire()
{
  if (pthread_enabled)
  {
    pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>(data_);
    assert(mutex != 0);

    int errorcode = pthread_mutex_trylock(mutex);
    return errorcode == 0;
  }
  return false;
}

}

#elif defined(LLVM_ON_UNIX)
#include "Unix/Mutex.inc"
#elif defined( LLVM_ON_WIN32)
#include "Win32/Mutex.inc"
#else
#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp
#endif
#endif