1//===- RWMutex.cpp - Reader/Writer 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::RWMutex class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Config/config.h"
15#include "llvm/Support/RWMutex.h"
16#include <cstring>
17
18//===----------------------------------------------------------------------===//
19//=== WARNING: Implementation here must contain only TRULY operating system
20//===          independent code.
21//===----------------------------------------------------------------------===//
22
23#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
24// Define all methods as no-ops if threading is explicitly disabled
25namespace llvm {
26using namespace sys;
27RWMutexImpl::RWMutexImpl() { }
28RWMutexImpl::~RWMutexImpl() { }
29bool RWMutexImpl::reader_acquire() { return true; }
30bool RWMutexImpl::reader_release() { return true; }
31bool RWMutexImpl::writer_acquire() { return true; }
32bool RWMutexImpl::writer_release() { return true; }
33}
34#else
35
36#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
37
38#include <cassert>
39#include <pthread.h>
40#include <stdlib.h>
41
42namespace llvm {
43using namespace sys;
44
45// Construct a RWMutex using pthread calls
46RWMutexImpl::RWMutexImpl()
47  : data_(nullptr)
48{
49  // Declare the pthread_rwlock data structures
50  pthread_rwlock_t* rwlock =
51    static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t)));
52
53#ifdef __APPLE__
54  // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
55  bzero(rwlock, sizeof(pthread_rwlock_t));
56#endif
57
58  // Initialize the rwlock
59  int errorcode = pthread_rwlock_init(rwlock, nullptr);
60  (void)errorcode;
61  assert(errorcode == 0);
62
63  // Assign the data member
64  data_ = rwlock;
65}
66
67// Destruct a RWMutex
68RWMutexImpl::~RWMutexImpl()
69{
70  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
71  assert(rwlock != nullptr);
72  pthread_rwlock_destroy(rwlock);
73  free(rwlock);
74}
75
76bool
77RWMutexImpl::reader_acquire()
78{
79  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
80  assert(rwlock != nullptr);
81
82  int errorcode = pthread_rwlock_rdlock(rwlock);
83  return errorcode == 0;
84}
85
86bool
87RWMutexImpl::reader_release()
88{
89  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
90  assert(rwlock != nullptr);
91
92  int errorcode = pthread_rwlock_unlock(rwlock);
93  return errorcode == 0;
94}
95
96bool
97RWMutexImpl::writer_acquire()
98{
99  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
100  assert(rwlock != nullptr);
101
102  int errorcode = pthread_rwlock_wrlock(rwlock);
103  return errorcode == 0;
104}
105
106bool
107RWMutexImpl::writer_release()
108{
109  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
110  assert(rwlock != nullptr);
111
112  int errorcode = pthread_rwlock_unlock(rwlock);
113  return errorcode == 0;
114}
115
116}
117
118#elif defined(LLVM_ON_UNIX)
119#include "Unix/RWMutex.inc"
120#elif defined( LLVM_ON_WIN32)
121#include "Windows/RWMutex.inc"
122#else
123#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp
124#endif
125#endif
126