1610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* 2610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This file is part of ThreadSanitizer, a dynamic data race detector. 3610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 4610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Copyright (C) 2008-2008 Google Inc 5610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov opensource@google.com 6610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 7610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This program is free software; you can redistribute it and/or 8610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov modify it under the terms of the GNU General Public License as 9610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov published by the Free Software Foundation; either version 2 of the 10610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov License, or (at your option) any later version. 11610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 12610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This program is distributed in the hope that it will be useful, but 13610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov WITHOUT ANY WARRANTY; without even the implied warranty of 14610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov General Public License for more details. 16610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 17610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov You should have received a copy of the GNU General Public License 18610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov along with this program; if not, write to the Free Software 19610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 20610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 02111-1307, USA. 21610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 22610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov The GNU General Public License is contained in the file COPYING. 23610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/ 24610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 25610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Author: Konstantin Serebryany <opensource@google.com> 26610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 27610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Here we define few simple classes that wrap pthread primitives. 28610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 29610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We need this to create unit tests for helgrind (or similar tool) 30610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// that will work with different threading frameworks. 31610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 32610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// If one needs to test helgrind's support for another threading library, 33610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// he/she can create a copy of this file and replace pthread_ calls 34610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// with appropriate calls to his/her library. 35610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 36610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Note, that some of the methods defined here are annotated with 37610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// ANNOTATE_* macros defined in dynamic_annotations.h. 38610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 39610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// DISCLAIMER: the classes defined in this header file 40610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// are NOT intended for general use -- only for unit tests. 41610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 42610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef THREAD_WRAPPERS_WIN_H 43610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define THREAD_WRAPPERS_WIN_H 44610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 45610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define _WIN32_WINNT 0x0500 // Require Windows 2000. 46610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <windows.h> 47610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <mmsystem.h> 48610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 49610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#pragma comment(lib, "winmm.lib") 50610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 51610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define NO_BARRIER 52610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define NO_UNNAMED_SEM 53610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define TLS __declspec(thread) 54610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define NO_SPINLOCK // TODO(timurrrr): implement SpinLock 55610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define usleep(x) Sleep((x)/1000) 56610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define sleep(x) Sleep((x)*1000) 57610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define NOINLINE __declspec(noinline) 58610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define ALIGNED(x) __declspec (align(x)) 59610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 60610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GetTimeInMs() { 61610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return (int)timeGetTime(); 62610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 63610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 64610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef unsigned char uint8_t; 65610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef unsigned short uint16_t; 66610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef unsigned int uint32_t; 67610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef unsigned long long uint64_t; 68610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef long long int64_t; 69610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 70610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This constant is true if malloc() uses mutex on your platform as this may 71610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// introduce a happens-before arc for a pure happens-before race detector. 72610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic const bool kMallocUsesMutex = false; 73610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 74610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint AtomicIncrement(volatile int *value, int increment) { 75610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(value), 76610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov increment) + increment; 77610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 78610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 79610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass Mutex { 80610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov friend class CondVar; 81610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public: 82610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Mutex() { ::InitializeCriticalSection(&cs_); } 83610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ~Mutex() { ::DeleteCriticalSection(&cs_); } 84610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Lock() { ::EnterCriticalSection(&cs_);} 85610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool TryLock() { return ::TryEnterCriticalSection(&cs_); } 86610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Unlock() { 87610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_HAPPENS_BEFORE(this); 88610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov /* 89610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // TODO(timurrrr): do we need this? 90610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (signal_at_unlock_) { 91610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(0 == pthread_cond_signal(&cv_)); 92610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 93610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov */ 94610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ::LeaveCriticalSection(&cs_); 95610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 96610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void ReaderLock() { Lock(); } 97610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool ReaderTryLock() { return TryLock();} 98610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void ReaderUnlock() { Unlock(); } 99610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void LockWhen(Condition cond) { Lock(); WaitLoop(cond); } 101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void ReaderLockWhen(Condition cond) { Lock(); WaitLoop(cond); } 102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Await(Condition cond) { WaitLoop(cond); } 103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool ReaderLockWhenWithTimeout(Condition cond, int millis) 105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov { Lock(); return WaitLoopWithTimeout(cond, millis); } 106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool LockWhenWithTimeout(Condition cond, int millis) 107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov { Lock(); return WaitLoopWithTimeout(cond, millis); } 108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool AwaitWithTimeout(Condition cond, int millis) 109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov { return WaitLoopWithTimeout(cond, millis); } 110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private: 112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void WaitLoop(Condition cond) { 114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov while(cond.Eval() == false) { 115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Unlock(); 116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // TODO(timurrrr) 117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Sleep(10); 118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Lock(); 119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_HAPPENS_AFTER(this); 121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool WaitLoopWithTimeout(Condition cond, int millis) { 124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov int start_time = GetTimeInMs(); 125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov while (cond.Eval() == false && GetTimeInMs() - start_time < millis) { 127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Unlock(); 128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // TODO(timurrrr) 129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Sleep(10); 130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Lock(); 131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (cond.Eval() == 0) { 134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return false; 135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } else { 136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_HAPPENS_AFTER(this); 137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return true; 138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CRITICAL_SECTION cs_; 142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass CondVar { 145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public: 146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CondVar() { 147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov signaled_ = false; 148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov hSignal_ = CreateEvent(NULL, false, false, NULL); 149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(hSignal_ != NULL); 150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ~CondVar() { 152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CloseHandle(hSignal_); 153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Wait(Mutex *mu) { 155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov while (!signaled_) { 156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov mu->Unlock(); 157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov WaitForSingleObject(hSignal_, INFINITE); 158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov mu->Lock(); 159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov signaled_ = false; 161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_HAPPENS_AFTER(this); 162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool WaitWithTimeout(Mutex *mu, int millis) { 164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov int start_time = GetTimeInMs(); 165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov while (!signaled_ && GetTimeInMs() - start_time < millis) { 167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov int curr_time = GetTimeInMs(); 168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (curr_time - start_time >= millis) 169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov break; 170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov mu->Unlock(); 171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov WaitForSingleObject(hSignal_, start_time + millis - curr_time); 172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov mu->Lock(); 173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (signaled_) { 175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_HAPPENS_AFTER(this); 176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov signaled_ = false; 177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return true; 178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return false; 180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Signal() { 182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov signaled_ = true; 183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_HAPPENS_BEFORE(this); 184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov SetEvent(hSignal_); 185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TODO(timurrrr): this isn't used anywhere - do we need these? 187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// void SignalAll(); 188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private: 189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov HANDLE hSignal_; 190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool signaled_; 191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass MyThread { 194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public: 195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov typedef void *(*worker_t)(void*); 196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread(worker_t worker, void *arg = NULL, const char *name = NULL) 198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov :w_(worker), arg_(arg), name_(name), t_(NULL) {} 199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread(void (*worker)(void), void *arg = NULL, const char *name = NULL) 200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov :w_(reinterpret_cast<worker_t>(worker)), arg_(arg), name_(name), t_(NULL) {} 201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread(void (*worker)(void *), void *arg = NULL, const char *name = NULL) 202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov :w_(reinterpret_cast<worker_t>(worker)), arg_(arg), name_(name), t_(NULL) {} 203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ~MyThread(){ 205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CloseHandle(t_); 206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t_ = NULL; 207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Start() { 209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov DWORD thr_id; 210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t_ = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadBody, this, 0, &thr_id); 211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(t_ > 0); 212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Join() { 214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(t_ > 0); 215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(WAIT_OBJECT_0 == ::WaitForSingleObject(t_, INFINITE)); 216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov HANDLE tid() const { return t_; } 218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private: 219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov static DWORD WINAPI ThreadBody(MyThread *my_thread) { 220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (my_thread->name_) { 221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_THREAD_NAME(my_thread->name_); 222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov my_thread->w_(my_thread->arg_); 224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return 0; 225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov HANDLE t_; 227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov DWORD ret_; 228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov worker_t w_; 229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void *arg_; 230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov const char *name_; 231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // THREAD_WRAPPERS_WIN_H 233