1218885Sdim//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This file implements the llvm::sys::RWMutex class.
11218885Sdim//
12218885Sdim//===----------------------------------------------------------------------===//
13218885Sdim
14218885Sdim#include "llvm/Config/config.h"
15218885Sdim#include "llvm/Support/RWMutex.h"
16218885Sdim#include <cstring>
17218885Sdim
18218885Sdim//===----------------------------------------------------------------------===//
19218885Sdim//=== WARNING: Implementation here must contain only TRULY operating system
20218885Sdim//===          independent code.
21218885Sdim//===----------------------------------------------------------------------===//
22218885Sdim
23235633Sdim#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
24218885Sdim// Define all methods as no-ops if threading is explicitly disabled
25218885Sdimnamespace llvm {
26218885Sdimusing namespace sys;
27218885SdimRWMutexImpl::RWMutexImpl() { }
28218885SdimRWMutexImpl::~RWMutexImpl() { }
29218885Sdimbool RWMutexImpl::reader_acquire() { return true; }
30218885Sdimbool RWMutexImpl::reader_release() { return true; }
31218885Sdimbool RWMutexImpl::writer_acquire() { return true; }
32218885Sdimbool RWMutexImpl::writer_release() { return true; }
33218885Sdim}
34218885Sdim#else
35218885Sdim
36218885Sdim#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
37218885Sdim
38218885Sdim#include <cassert>
39218885Sdim#include <pthread.h>
40218885Sdim#include <stdlib.h>
41218885Sdim
42218885Sdimnamespace llvm {
43218885Sdimusing namespace sys;
44218885Sdim
45218885Sdim// Construct a RWMutex using pthread calls
46218885SdimRWMutexImpl::RWMutexImpl()
47218885Sdim  : data_(0)
48218885Sdim{
49235633Sdim  // Declare the pthread_rwlock data structures
50235633Sdim  pthread_rwlock_t* rwlock =
51235633Sdim    static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t)));
52218885Sdim
53218885Sdim#ifdef __APPLE__
54235633Sdim  // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
55235633Sdim  bzero(rwlock, sizeof(pthread_rwlock_t));
56218885Sdim#endif
57218885Sdim
58235633Sdim  // Initialize the rwlock
59235633Sdim  int errorcode = pthread_rwlock_init(rwlock, NULL);
60235633Sdim  (void)errorcode;
61235633Sdim  assert(errorcode == 0);
62218885Sdim
63235633Sdim  // Assign the data member
64235633Sdim  data_ = rwlock;
65218885Sdim}
66218885Sdim
67218885Sdim// Destruct a RWMutex
68218885SdimRWMutexImpl::~RWMutexImpl()
69218885Sdim{
70235633Sdim  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
71235633Sdim  assert(rwlock != 0);
72235633Sdim  pthread_rwlock_destroy(rwlock);
73235633Sdim  free(rwlock);
74218885Sdim}
75218885Sdim
76218885Sdimbool
77218885SdimRWMutexImpl::reader_acquire()
78218885Sdim{
79235633Sdim  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
80235633Sdim  assert(rwlock != 0);
81218885Sdim
82235633Sdim  int errorcode = pthread_rwlock_rdlock(rwlock);
83235633Sdim  return errorcode == 0;
84218885Sdim}
85218885Sdim
86218885Sdimbool
87218885SdimRWMutexImpl::reader_release()
88218885Sdim{
89235633Sdim  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
90235633Sdim  assert(rwlock != 0);
91218885Sdim
92235633Sdim  int errorcode = pthread_rwlock_unlock(rwlock);
93235633Sdim  return errorcode == 0;
94218885Sdim}
95218885Sdim
96218885Sdimbool
97218885SdimRWMutexImpl::writer_acquire()
98218885Sdim{
99235633Sdim  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
100235633Sdim  assert(rwlock != 0);
101218885Sdim
102235633Sdim  int errorcode = pthread_rwlock_wrlock(rwlock);
103235633Sdim  return errorcode == 0;
104218885Sdim}
105218885Sdim
106218885Sdimbool
107218885SdimRWMutexImpl::writer_release()
108218885Sdim{
109235633Sdim  pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
110235633Sdim  assert(rwlock != 0);
111218885Sdim
112235633Sdim  int errorcode = pthread_rwlock_unlock(rwlock);
113235633Sdim  return errorcode == 0;
114218885Sdim}
115218885Sdim
116218885Sdim}
117218885Sdim
118218885Sdim#elif defined(LLVM_ON_UNIX)
119218885Sdim#include "Unix/RWMutex.inc"
120218885Sdim#elif defined( LLVM_ON_WIN32)
121218885Sdim#include "Windows/RWMutex.inc"
122218885Sdim#else
123226890Sdim#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp
124218885Sdim#endif
125218885Sdim#endif
126