1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This file is part of Valgrind, a dynamic binary instrumentation
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  framework.
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Copyright (C) 2008-2008 Google Inc
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     opensource@google.com
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is free software; you can redistribute it and/or
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  modify it under the terms of the GNU General Public License as
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  published by the Free Software Foundation; either version 2 of the
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  License, or (at your option) any later version.
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is distributed in the hope that it will be useful, but
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WITHOUT ANY WARRANTY; without even the implied warranty of
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  General Public License for more details.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  You should have received a copy of the GNU General Public License
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  along with this program; if not, write to the Free Software
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  02111-1307, USA.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The GNU General Public License is contained in the file COPYING.
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Author: Konstantin Serebryany <opensource@google.com>
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we define few simple classes that wrap pthread primitives.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We need this to create unit tests for helgrind (or similar tool)
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// that will work with different threading frameworks.
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// If one needs to test helgrind's support for another threading library,
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// he/she can create a copy of this file and replace pthread_ calls
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// with appropriate calls to his/her library.
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note, that some of the methods defined here are annotated with
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ANNOTATE_* macros defined in dynamic_annotations.h.
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// DISCLAIMER: the classes defined in this header file
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// are NOT intended for general use -- only for unit tests.
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef THREAD_WRAPPERS_PTHREAD_H
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define THREAD_WRAPPERS_PTHREAD_H
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h>
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <semaphore.h>
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h>
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <queue>
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <limits.h>   // INT_MAX
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef VGO_darwin
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <libkern/OSAtomic.h>
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NO_BARRIER
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NO_TLS
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <string>
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownusing namespace std;
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/time.h>
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <time.h>
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "../../drd/drd.h"
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ANNOTATE_NO_OP(arg) do { } while(0)
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ANNOTATE_EXPECT_RACE(addr, descr)                \
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_BENIGN_RACE_SIZED(addr, 4, "expected race")
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline bool RunningOnValgrind() { return RUNNING_ON_VALGRIND; }
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef NDEBUG
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Pleeease, do not define NDEBUG"
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CHECK assert
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Set this to true if malloc() uses mutex on your platform as this may
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// introduce a happens-before arc for a pure happens-before race detector.
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst bool kMallocUsesMutex = false;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Current time in milliseconds.
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline int64_t GetCurrentTimeMillis() {
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  struct timeval now;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  gettimeofday(&now, NULL);
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return now.tv_sec * 1000 + now.tv_usec / 1000;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Copy tv to ts adding offset in milliseconds.
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void timeval2timespec(timeval *const tv,
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     timespec *ts,
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     int64_t offset_milli) {
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const int64_t ten_9 = 1000000000LL;
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const int64_t ten_6 = 1000000LL;
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const int64_t ten_3 = 1000LL;
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int64_t now_nsec = (int64_t)tv->tv_sec * ten_9;
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  now_nsec += (int64_t)tv->tv_usec * ten_3;
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int64_t then_nsec = now_nsec + offset_milli * ten_6;
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ts->tv_sec  = then_nsec / ten_9;
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ts->tv_nsec = then_nsec % ten_9;
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass CondVar;
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_SPINLOCK
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// helgrind does not (yet) support spin locks, so we annotate them.
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef VGO_darwin
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass SpinLock {
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  SpinLock() {
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_spin_init(&mu_, 0));
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_RWLOCK_CREATE((void*)&mu_);
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~SpinLock() {
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_RWLOCK_DESTROY((void*)&mu_);
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_spin_destroy(&mu_));
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Lock() {
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_spin_lock(&mu_));
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_RWLOCK_ACQUIRED((void*)&mu_, 1);
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Unlock() {
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_RWLOCK_RELEASED((void*)&mu_, 1);
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_spin_unlock(&mu_));
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_spinlock_t mu_;
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass SpinLock {
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Mac OS X version.
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  SpinLock() : mu_(OS_SPINLOCK_INIT) {
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_RWLOCK_CREATE((void*)&mu_);
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~SpinLock() {
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_RWLOCK_DESTROY((void*)&mu_);
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Lock() {
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    OSSpinLockLock(&mu_);
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_RWLOCK_ACQUIRED((void*)&mu_, 1);
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Unlock() {
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_RWLOCK_RELEASED((void*)&mu_, 1);
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    OSSpinLockUnlock(&mu_);
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  OSSpinLock mu_;
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif // VGO_darwin
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_SPINLOCK
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Just a boolean condition. Used by Mutex::LockWhen and similar.
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass Condition {
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  typedef bool (*func_t)(void*);
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  template <typename T>
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Condition(bool (*func)(T*), T* arg)
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  : func_(reinterpret_cast<func_t>(func)), arg_(arg) {}
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Condition(bool (*func)())
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  : func_(reinterpret_cast<func_t>(func)), arg_(NULL) {}
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool Eval() { return func_(arg_); }
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  func_t func_;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void *arg_;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Wrapper for pthread_mutex_t.
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown///
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// pthread_mutex_t is *not* a reader-writer lock,
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// so the methods like ReaderLock() aren't really reader locks.
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// We can not use pthread_rwlock_t because it
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// does not work with pthread_cond_t.
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown///
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// TODO: We still need to test reader locks with this class.
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Implement a mode where pthread_rwlock_t will be used
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// instead of pthread_mutex_t (only when not used with CondVar or LockWhen).
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown///
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass Mutex {
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  friend class CondVar;
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Mutex() {
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_mutex_init(&mu_, NULL));
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_cond_init(&cv_, NULL));
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    signal_at_unlock_ = true;  // Always signal at Unlock to make
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               // Mutex more friendly to hybrid detectors.
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~Mutex() {
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_cond_destroy(&cv_));
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_mutex_destroy(&mu_));
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Lock()          { CHECK(0 == pthread_mutex_lock(&mu_));}
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool TryLock()       { return (0 == pthread_mutex_trylock(&mu_));}
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Unlock() {
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (signal_at_unlock_) {
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(0 == pthread_cond_signal(&cv_));
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(0 == pthread_mutex_unlock(&mu_));
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void ReaderLock()    { Lock(); }
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool ReaderTryLock() { return TryLock();}
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void ReaderUnlock()  { Unlock(); }
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void LockWhen(Condition cond)            { Lock(); WaitLoop(cond); }
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void ReaderLockWhen(Condition cond)      { Lock(); WaitLoop(cond); }
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Await(Condition cond)               { WaitLoop(cond); }
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool ReaderLockWhenWithTimeout(Condition cond, int millis)
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { Lock(); return WaitLoopWithTimeout(cond, millis); }
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool LockWhenWithTimeout(Condition cond, int millis)
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { Lock(); return WaitLoopWithTimeout(cond, millis); }
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool AwaitWithTimeout(Condition cond, int millis)
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    { return WaitLoopWithTimeout(cond, millis); }
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void WaitLoop(Condition cond) {
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    signal_at_unlock_ = true;
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while(cond.Eval() == false) {
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pthread_cond_wait(&cv_, &mu_);
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_CONDVAR_LOCK_WAIT(&cv_, &mu_);
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool WaitLoopWithTimeout(Condition cond, int millis) {
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct timeval now;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct timespec timeout;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int retcode = 0;
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gettimeofday(&now, NULL);
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    timeval2timespec(&now, &timeout, millis);
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    signal_at_unlock_ = true;
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (cond.Eval() == false && retcode == 0) {
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      retcode = pthread_cond_timedwait(&cv_, &mu_, &timeout);
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if(retcode == 0) {
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_CONDVAR_LOCK_WAIT(&cv_, &mu_);
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return cond.Eval();
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // A hack. cv_ should be the first data member so that
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // ANNOTATE_CONDVAR_WAIT(&MU, &MU) and ANNOTATE_CONDVAR_SIGNAL(&MU) works.
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // (See also racecheck_unittest.cc)
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_cond_t  cv_;
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutex_t mu_;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool            signal_at_unlock_;  // Set to true if Wait was called.
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass MutexLock {  // Scoped Mutex Locker/Unlocker
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock(Mutex *mu)
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    : mu_(mu) {
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_->Lock();
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~MutexLock() {
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_->Unlock();
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Mutex *mu_;
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Wrapper for pthread_cond_t.
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass CondVar {
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CondVar()   { CHECK(0 == pthread_cond_init(&cv_, NULL)); }
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~CondVar()  { CHECK(0 == pthread_cond_destroy(&cv_)); }
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Wait(Mutex *mu) { CHECK(0 == pthread_cond_wait(&cv_, &mu->mu_)); }
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool WaitWithTimeout(Mutex *mu, int millis) {
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct timeval now;
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct timespec timeout;
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    gettimeofday(&now, NULL);
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    timeval2timespec(&now, &timeout, millis);
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return 0 != pthread_cond_timedwait(&cv_, &mu->mu_, &timeout);
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Signal() { CHECK(0 == pthread_cond_signal(&cv_)); }
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void SignalAll() { CHECK(0 == pthread_cond_broadcast(&cv_)); }
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_cond_t cv_;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pthreads do not allow to use condvar with rwlock so we can't make
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ReaderLock method of Mutex to be the real rw-lock.
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// So, we need a special lock class to test reader locks.
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NEEDS_SEPERATE_RW_LOCK
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass RWLock {
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  RWLock() { CHECK(0 == pthread_rwlock_init(&mu_, NULL)); }
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~RWLock() { CHECK(0 == pthread_rwlock_destroy(&mu_)); }
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Lock() { CHECK(0 == pthread_rwlock_wrlock(&mu_)); }
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void ReaderLock() { CHECK(0 == pthread_rwlock_rdlock(&mu_)); }
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Unlock() { CHECK(0 == pthread_rwlock_unlock(&mu_)); }
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void ReaderUnlock() { CHECK(0 == pthread_rwlock_unlock(&mu_)); }
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_cond_t dummy; // Damn, this requires some redesign...
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_rwlock_t mu_;
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass ReaderLockScoped {  // Scoped RWLock Locker/Unlocker
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ReaderLockScoped(RWLock *mu)
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    : mu_(mu) {
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_->ReaderLock();
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~ReaderLockScoped() {
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_->ReaderUnlock();
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  RWLock *mu_;
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass WriterLockScoped {  // Scoped RWLock Locker/Unlocker
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WriterLockScoped(RWLock *mu)
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    : mu_(mu) {
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_->Lock();
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~WriterLockScoped() {
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_->Unlock();
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  RWLock *mu_;
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Wrapper for pthread_create()/pthread_join().
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass MyThread {
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  typedef void *(*worker_t)(void*);
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread(worker_t worker, void *arg = NULL, const char *name = NULL)
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      :w_(worker), arg_(arg), name_(name) {}
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread(void (*worker)(void), void *arg = NULL, const char *name = NULL)
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      :w_(reinterpret_cast<worker_t>(worker)), arg_(arg), name_(name) {}
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread(void (*worker)(void *), void *arg = NULL, const char *name = NULL)
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      :w_(reinterpret_cast<worker_t>(worker)), arg_(arg), name_(name) {}
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~MyThread(){ w_ = NULL; arg_ = NULL;}
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Start() { CHECK(0 == pthread_create(&t_, NULL, (worker_t)ThreadBody, this));}
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Join()  { CHECK(0 == pthread_join(t_, NULL));}
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_t tid() const { return t_; }
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static void ThreadBody(MyThread *my_thread) {
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (my_thread->name_) {
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_THREAD_NAME(my_thread->name_);
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    my_thread->w_(my_thread->arg_);
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_t t_;
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  worker_t  w_;
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void     *arg_;
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const char *name_;
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Just a message queue.
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass ProducerConsumerQueue {
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ProducerConsumerQueue(int unused) {
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //ANNOTATE_PCQ_CREATE(this);
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~ProducerConsumerQueue() {
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(q_.empty());
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //ANNOTATE_PCQ_DESTROY(this);
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Put.
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Put(void *item) {
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_.Lock();
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      q_.push(item);
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_CONDVAR_SIGNAL(&mu_); // LockWhen in Get()
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //ANNOTATE_PCQ_PUT(this);
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_.Unlock();
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Get.
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Blocks if the queue is empty.
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void *Get() {
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_.LockWhen(Condition(IsQueueNotEmpty, &q_));
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      void * item = NULL;
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bool ok = TryGetInternal(&item);
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(ok);
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_.Unlock();
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return item;
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // If queue is not empty,
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // remove an element from queue, put it into *res and return true.
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Otherwise return false.
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool TryGet(void **res) {
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_.Lock();
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bool ok = TryGetInternal(res);
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_.Unlock();
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return ok;
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Mutex mu_;
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  std::queue<void*> q_; // protected by mu_
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Requires mu_
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool TryGetInternal(void ** item_ptr) {
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (q_.empty())
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return false;
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *item_ptr = q_.front();
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    q_.pop();
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    //ANNOTATE_PCQ_GET(this);
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return true;
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static bool IsQueueNotEmpty(std::queue<void*> * queue) {
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return !queue->empty();
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Function pointer with zero, one or two parameters.
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct Closure {
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  typedef void (*F0)();
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  typedef void (*F1)(void *arg1);
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  typedef void (*F2)(void *arg1, void *arg2);
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int  n_params;
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void *f;
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void *param1;
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void *param2;
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Execute() {
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (n_params == 0) {
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (F0(f))();
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else if (n_params == 1) {
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (F1(f))(param1);
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    } else {
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(n_params == 2);
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (F2(f))(param1, param2);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    delete this;
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownClosure *NewCallback(void (*f)()) {
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Closure *res = new Closure;
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->n_params = 0;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->f = (void*)(f);
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->param1 = NULL;
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->param2 = NULL;
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return res;
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntemplate <class P1>
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownClosure *NewCallback(void (*f)(P1), P1 p1) {
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(sizeof(P1) <= sizeof(void*));
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Closure *res = new Closure;
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->n_params = 1;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->f = (void*)(f);
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->param1 = (void*)p1;
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->param2 = NULL;
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return res;
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntemplate <class T, class P1, class P2>
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownClosure *NewCallback(void (*f)(P1, P2), P1 p1, P2 p2) {
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(sizeof(P1) <= sizeof(void*));
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Closure *res = new Closure;
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->n_params = 2;
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->f = (void*)(f);
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->param1 = (void*)p1;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res->param2 = (void*)p2;
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return res;
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*! A thread pool that uses ProducerConsumerQueue.
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Usage:
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool pool(n_workers);
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.StartWorkers();
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.Add(NewCallback(func_with_no_args));
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.Add(NewCallback(func_with_one_arg, arg));
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.Add(NewCallback(func_with_two_args, arg1, arg2));
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ... // more calls to pool.Add()
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // the ~ThreadPool() is called: we wait workers to finish
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // and then join all threads in the pool.
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass ThreadPool {
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //! Create n_threads threads, but do not start.
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  explicit ThreadPool(int n_threads)
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    : queue_(INT_MAX) {
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < n_threads; i++) {
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MyThread *thread = new MyThread(&ThreadPool::Worker, this);
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      workers_.push_back(thread);
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //! Start all threads.
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void StartWorkers() {
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (size_t i = 0; i < workers_.size(); i++) {
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      workers_[i]->Start();
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //! Add a closure.
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Add(Closure *closure) {
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    queue_.Put(closure);
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int num_threads() { return workers_.size();}
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //! Wait workers to finish, then join all threads.
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~ThreadPool() {
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (size_t i = 0; i < workers_.size(); i++) {
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Add(NULL);
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (size_t i = 0; i < workers_.size(); i++) {
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      workers_[i]->Join();
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete workers_[i];
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  std::vector<MyThread*>   workers_;
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ProducerConsumerQueue  queue_;
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static void *Worker(void *p) {
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool *pool = reinterpret_cast<ThreadPool*>(p);
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (true) {
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Closure *closure = reinterpret_cast<Closure*>(pool->queue_.Get());
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(closure == NULL) {
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return NULL;
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      closure->Execute();
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/// Wrapper for pthread_barrier_t.
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass Barrier{
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  explicit Barrier(int n_threads) {CHECK(0 == pthread_barrier_init(&b_, 0, n_threads));}
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~Barrier()                      {CHECK(0 == pthread_barrier_destroy(&b_));}
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Block() {
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // helgrind 3.3.0 does not have an interceptor for barrier.
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // but our current local version does.
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // ANNOTATE_CONDVAR_SIGNAL(this);
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pthread_barrier_wait(&b_);
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // ANNOTATE_CONDVAR_WAIT(this, this);
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_barrier_t b_;
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass BlockingCounter {
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  explicit BlockingCounter(int initial_count) :
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    count_(initial_count) {}
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool DecrementCount() {
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MutexLock lock(&mu_);
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    count_--;
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return count_ == 0;
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Wait() {
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_.LockWhen(Condition(&IsZero, &count_));
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_.Unlock();
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static bool IsZero(int *arg) { return *arg == 0; }
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Mutex mu_;
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int count_;
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint AtomicIncrement(volatile int *value, int increment);
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef VGO_darwin
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline int AtomicIncrement(volatile int *value, int increment) {
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return __sync_add_and_fetch(value, increment);
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Mac OS X version.
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline int AtomicIncrement(volatile int *value, int increment) {
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return OSAtomicAdd32(increment, value);
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TODO(timurrrr) this is a hack
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define memalign(A,B) malloc(B)
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TODO(timurrrr) this is a hack
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint posix_memalign(void **out, size_t al, size_t size) {
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *out = memalign(al, size);
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return (*out == 0);
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif // VGO_darwin
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // THREAD_WRAPPERS_PTHREAD_H
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
615