aboutsummaryrefslogtreecommitdiff
path: root/lib/asan/asan_lock.h
blob: 030fae613c2394c2bf537388f0013e4e19e5b207 (plain) (blame)
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
//===-- asan_lock.h ---------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// A wrapper for a simple lock.
//===----------------------------------------------------------------------===//
#ifndef ASAN_LOCK_H
#define ASAN_LOCK_H

#include "asan_internal.h"

// The locks in ASan are global objects and they are never destroyed to avoid
// at-exit races (that is, a lock is being used by other threads while the main
// thread is doing atexit destructors).

#ifdef __APPLE__
#include <pthread.h>

#include <libkern/OSAtomic.h>
namespace __asan {
class AsanLock {
 public:
  explicit AsanLock(LinkerInitialized) :
    mu_(OS_SPINLOCK_INIT),
    owner_(0),
    is_locked_(false) {}

  void Lock() {
    CHECK(owner_ != pthread_self());
    OSSpinLockLock(&mu_);
    is_locked_ = true;
    owner_ = pthread_self();
  }
  void Unlock() {
    owner_ = 0;
    is_locked_ = false;
    OSSpinLockUnlock(&mu_);
  }

  bool IsLocked() {
    // This is not atomic, e.g. one thread may get different values if another
    // one is about to release the lock.
    return is_locked_;
  }
 private:
  OSSpinLock mu_;
  volatile pthread_t owner_;  // for debugging purposes
  bool is_locked_;  // for silly malloc_introspection_t interface
};
}  // namespace __asan

#else  // assume linux
#include <pthread.h>
namespace __asan {
class AsanLock {
 public:
  explicit AsanLock(LinkerInitialized) {
    // We assume that pthread_mutex_t initialized to all zeroes is a valid
    // unlocked mutex. We can not use PTHREAD_MUTEX_INITIALIZER as it triggers
    // a gcc warning:
    // extended initializer lists only available with -std=c++0x or -std=gnu++0x
  }
  void Lock() {
    pthread_mutex_lock(&mu_);
    // pthread_spin_lock(&mu_);
  }
  void Unlock() {
    pthread_mutex_unlock(&mu_);
    // pthread_spin_unlock(&mu_);
  }
 private:
  pthread_mutex_t mu_;
  // pthread_spinlock_t mu_;
};
}  // namespace __asan
#endif

namespace __asan {
class ScopedLock {
 public:
  explicit ScopedLock(AsanLock *mu) : mu_(mu) {
    mu_->Lock();
  }
  ~ScopedLock() {
    mu_->Unlock();
  }
 private:
  AsanLock *mu_;
};

}  // namespace __asan

#endif  // ASAN_LOCK_H