Merge c:/dyninst/pc_bluegene/dyninst into dyn_pc_integration
[dyninst.git] / common / dthread-win.C
1 #include "common/h/dthread.h"
2 #include <assert.h>
3
4 DThread::DThread()
5 {
6 }
7
8 DThread::~DThread()
9 {
10 }
11
12 long DThread::self()
13 {
14         return ::GetCurrentThreadId();
15 }
16 bool DThread::spawn(DThread::initial_func_t func, void *param)
17 {
18         thrd = ::CreateThread(NULL, 0, func, param, 0, &tid);
19         live = (thrd != INVALID_HANDLE_VALUE);
20         return live;
21 }
22 bool DThread::join()
23 {
24         assert(live && self() != id());
25         ::WaitForSingleObject(thrd, INFINITE);
26         return true;
27 }
28
29 long DThread::id()
30 {
31         return tid;
32 }
33
34
35 Mutex::Mutex(bool recursive)
36 {
37         mutex = ::CreateMutex(NULL, false, NULL);
38 }
39
40 Mutex::~Mutex()
41 {
42         ::CloseHandle(mutex);
43 }
44
45 bool Mutex::lock()
46 {
47 //      fprintf(stderr, "[%d]: Mutex::lock() waiting for 0x%lx\n", ::GetCurrentThreadId(), mutex);
48         bool ok = (::WaitForSingleObject(mutex, INFINITE) == WAIT_OBJECT_0);
49 //      fprintf(stderr, "[%d]: Mutex::lock() holding 0x%lx\n", ::GetCurrentThreadId(), mutex);
50         return ok;
51 }
52
53 bool Mutex::unlock()
54 {
55 //      fprintf(stderr, "[%d]: Mutex::unlock() for 0x%lx\n", ::GetCurrentThreadId(), mutex);
56         bool ok = ::ReleaseMutex(mutex);
57         if(!ok) {
58                 fprintf(stderr, "Failed to release mutex: %d\n", ::GetLastError());
59         }
60         return ok;
61 }
62
63 CondVar::CondVar(Mutex *m) :
64         numWaiting(0),
65         was_broadcast(false),
66         mutex(m),
67         created_mutex(false)
68 {
69         if(mutex == NULL)
70         {
71                 mutex = new Mutex();
72                 created_mutex = true;
73         }
74         wait_sema = ::CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
75         ::InitializeCriticalSection(&numWaitingLock);
76         wait_done = ::CreateEvent(NULL, false, false, NULL);
77 }
78 CondVar::~CondVar()
79 {
80         if(created_mutex)
81         {
82                 delete mutex;
83         }
84         ::CloseHandle(wait_sema);
85         ::CloseHandle(wait_done);
86         ::DeleteCriticalSection(&numWaitingLock);
87 }
88
89 bool CondVar::unlock()
90 {
91         bool ret = mutex->unlock();
92         return ret;
93 }
94 bool CondVar::lock()
95 {
96         bool ret = mutex->lock();
97         return ret;     
98 }
99 bool CondVar::signal()
100 {
101         ::EnterCriticalSection(&numWaitingLock);
102         bool waitingThreads = (numWaiting > 0);
103         ::LeaveCriticalSection(&numWaitingLock);
104         if(waitingThreads)
105         {
106                 long prev_count;
107                 ::ReleaseSemaphore(wait_sema, 1, &prev_count);
108 //              fprintf(stderr, "[%d]: CondVar::signal() signaled 0x%lx, prev_count = %d\n", ::GetCurrentThreadId(), wait_sema, prev_count);
109         }
110         return true;
111 }
112 bool CondVar::broadcast()
113 {
114         ::EnterCriticalSection(&numWaitingLock);
115         bool waitingThreads = (numWaiting > 0);
116         was_broadcast = true;
117         if(waitingThreads)
118         {
119                 long prev_count;
120                 ::ReleaseSemaphore(wait_sema, 1, &prev_count);
121 //              fprintf(stderr, "[%d]: CondVar::broadcast() signaled 0x%lx, prev_count = %d\n", ::GetCurrentThreadId(), wait_sema, prev_count);
122                 ::LeaveCriticalSection(&numWaitingLock);
123                 ::WaitForSingleObject(wait_done, INFINITE);
124                 was_broadcast = false;
125         }
126         else
127         {
128                 ::LeaveCriticalSection(&numWaitingLock);
129         }
130         return true;
131 }
132 bool CondVar::wait()
133 {
134         ::EnterCriticalSection(&numWaitingLock);
135         numWaiting++;
136         ::LeaveCriticalSection(&numWaitingLock);
137 //      fprintf(stderr, "[%d]: CondVar::wait() signalling for 0x%lx, waiting for 0x%lx\n", ::GetCurrentThreadId(), mutex->mutex, wait_sema);
138         unsigned long result = ::SignalObjectAndWait(mutex->mutex, wait_sema, INFINITE, FALSE);
139         assert(result != WAIT_TIMEOUT);
140         ::EnterCriticalSection(&numWaitingLock);
141         numWaiting--;
142         bool last_waiter = (was_broadcast && (numWaiting == 0));
143         ::LeaveCriticalSection(&numWaitingLock);
144         if(last_waiter)
145         {
146 //              fprintf(stderr, "[%d]: CondVar::wait() waiting for 0x%lx, signaling 0x%lx\n", ::GetCurrentThreadId(), mutex->mutex, wait_done);
147                 result = ::SignalObjectAndWait(wait_done, mutex->mutex, INFINITE, FALSE);
148                 assert(result != WAIT_TIMEOUT);
149         }
150         else
151         {
152                 ::WaitForSingleObject(mutex->mutex, INFINITE);
153         }
154         return true;
155 }