1/*
2  This file is part of ThreadSanitizer, a dynamic data race detector.
3
4  Copyright (C) 2008-2008 Google Inc
5     opensource@google.com
6
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of the
10  License, or (at your option) any later version.
11
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  General Public License for more details.
16
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  02111-1307, USA.
21
22  The GNU General Public License is contained in the file COPYING.
23*/
24
25// Author: Konstantin Serebryany <opensource@google.com>
26//
27// Here we define few simple classes that wrap pthread primitives.
28//
29// We need this to create unit tests for helgrind (or similar tool)
30// that will work with different threading frameworks.
31//
32// If one needs to test helgrind's support for another threading library,
33// he/she can create a copy of this file and replace pthread_ calls
34// with appropriate calls to his/her library.
35//
36// Note, that some of the methods defined here are annotated with
37// ANNOTATE_* macros defined in dynamic_annotations.h.
38//
39// DISCLAIMER: the classes defined in this header file
40// are NOT intended for general use -- only for unit tests.
41//
42#ifndef THREAD_WRAPPERS_WIN_H
43#define THREAD_WRAPPERS_WIN_H
44
45#define _WIN32_WINNT 0x0500 // Require Windows 2000.
46#include <windows.h>
47#include <mmsystem.h>
48
49#pragma comment(lib, "winmm.lib")
50
51#define NO_BARRIER
52#define NO_UNNAMED_SEM
53#define TLS __declspec(thread)
54#define NO_SPINLOCK // TODO(timurrrr): implement SpinLock
55#define usleep(x) Sleep((x)/1000)
56#define sleep(x) Sleep((x)*1000)
57#define NOINLINE __declspec(noinline)
58#define ALIGNED(x) __declspec (align(x))
59
60int GetTimeInMs() {
61  return (int)timeGetTime();
62}
63
64typedef unsigned char  uint8_t;
65typedef unsigned short uint16_t;
66typedef unsigned int   uint32_t;
67typedef unsigned long long uint64_t;
68typedef long long int64_t;
69
70// This constant is true if malloc() uses mutex on your platform as this may
71// introduce a happens-before arc for a pure happens-before race detector.
72static const bool kMallocUsesMutex = false;
73
74int AtomicIncrement(volatile int *value, int increment) {
75  return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(value),
76                                increment) + increment;
77}
78
79class Mutex {
80  friend class CondVar;
81 public:
82  Mutex()  { ::InitializeCriticalSection(&cs_); }
83  ~Mutex() { ::DeleteCriticalSection(&cs_); }
84  void Lock()          { ::EnterCriticalSection(&cs_);}
85  bool TryLock()       { return ::TryEnterCriticalSection(&cs_); }
86  void Unlock() {
87    ANNOTATE_HAPPENS_BEFORE(this);
88    /*
89    // TODO(timurrrr): do we need this?
90    if (signal_at_unlock_) {
91      CHECK(0 == pthread_cond_signal(&cv_));
92    }
93    */
94    ::LeaveCriticalSection(&cs_);
95  }
96  void ReaderLock()    { Lock(); }
97  bool ReaderTryLock() { return TryLock();}
98  void ReaderUnlock()  { Unlock(); }
99
100  void LockWhen(Condition cond)            { Lock(); WaitLoop(cond); }
101  void ReaderLockWhen(Condition cond)      { Lock(); WaitLoop(cond); }
102  void Await(Condition cond)               { WaitLoop(cond); }
103
104  bool ReaderLockWhenWithTimeout(Condition cond, int millis)
105    { Lock(); return WaitLoopWithTimeout(cond, millis); }
106  bool LockWhenWithTimeout(Condition cond, int millis)
107    { Lock(); return WaitLoopWithTimeout(cond, millis); }
108  bool AwaitWithTimeout(Condition cond, int millis)
109    { return WaitLoopWithTimeout(cond, millis); }
110
111 private:
112
113  void WaitLoop(Condition cond) {
114    while(cond.Eval() == false) {
115      Unlock();
116      // TODO(timurrrr)
117      Sleep(10);
118      Lock();
119    }
120    ANNOTATE_HAPPENS_AFTER(this);
121  }
122
123  bool WaitLoopWithTimeout(Condition cond, int millis) {
124    int start_time = GetTimeInMs();
125
126    while (cond.Eval() == false && GetTimeInMs() - start_time < millis) {
127      Unlock();
128      // TODO(timurrrr)
129      Sleep(10);
130      Lock();
131    }
132
133    if (cond.Eval() == 0) {
134      return false;
135    } else {
136      ANNOTATE_HAPPENS_AFTER(this);
137      return true;
138    }
139  }
140
141  CRITICAL_SECTION cs_;
142};
143
144class CondVar {
145 public:
146  CondVar()   {
147    signaled_ = false;
148    hSignal_  = CreateEvent(NULL, false, false, NULL);
149    CHECK(hSignal_ != NULL);
150  }
151  ~CondVar()  {
152    CloseHandle(hSignal_);
153  }
154  void Wait(Mutex *mu) {
155    while (!signaled_) {
156      mu->Unlock();
157      WaitForSingleObject(hSignal_, INFINITE);
158      mu->Lock();
159    }
160    signaled_ = false;
161    ANNOTATE_HAPPENS_AFTER(this);
162  }
163  bool WaitWithTimeout(Mutex *mu, int millis) {
164    int start_time = GetTimeInMs();
165
166    while (!signaled_ && GetTimeInMs() - start_time < millis) {
167      int curr_time = GetTimeInMs();
168      if (curr_time - start_time >= millis)
169        break;
170      mu->Unlock();
171      WaitForSingleObject(hSignal_, start_time + millis - curr_time);
172      mu->Lock();
173    }
174    if (signaled_) {
175      ANNOTATE_HAPPENS_AFTER(this);
176      signaled_ = false;
177      return true;
178    }
179    return false;
180  }
181  void Signal() {
182    signaled_ = true;
183    ANNOTATE_HAPPENS_BEFORE(this);
184    SetEvent(hSignal_);
185  }
186// TODO(timurrrr): this isn't used anywhere - do we need these?
187//  void SignalAll();
188 private:
189  HANDLE hSignal_;
190  bool signaled_;
191};
192
193class MyThread {
194 public:
195  typedef void *(*worker_t)(void*);
196
197  MyThread(worker_t worker, void *arg = NULL, const char *name = NULL)
198      :w_(worker), arg_(arg), name_(name), t_(NULL) {}
199  MyThread(void (*worker)(void), void *arg = NULL, const char *name = NULL)
200      :w_(reinterpret_cast<worker_t>(worker)), arg_(arg), name_(name), t_(NULL) {}
201  MyThread(void (*worker)(void *), void *arg = NULL, const char *name = NULL)
202      :w_(reinterpret_cast<worker_t>(worker)), arg_(arg), name_(name), t_(NULL) {}
203
204  ~MyThread(){
205    CloseHandle(t_);
206    t_ = NULL;
207  }
208  void Start() {
209    DWORD thr_id;
210    t_ = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadBody, this, 0, &thr_id);
211    CHECK(t_ > 0);
212  }
213  void Join() {
214    CHECK(t_ > 0);
215    CHECK(WAIT_OBJECT_0 == ::WaitForSingleObject(t_, INFINITE));
216  }
217  HANDLE tid() const { return t_; }
218 private:
219  static DWORD WINAPI ThreadBody(MyThread *my_thread) {
220    if (my_thread->name_) {
221      ANNOTATE_THREAD_NAME(my_thread->name_);
222    }
223    my_thread->w_(my_thread->arg_);
224    return 0;
225  }
226  HANDLE t_;
227  DWORD ret_;
228  worker_t  w_;
229  void     *arg_;
230  const char *name_;
231};
232#endif  // THREAD_WRAPPERS_WIN_H
233