ProcControl/Windows: pc_launch passes. Many others fail/assert/hang.
[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         return ::ReleaseMutex(mutex);
57 }
58
59 CondVar::CondVar(Mutex *m) :
60         numWaiting(0),
61         was_broadcast(false),
62         mutex(m),
63         created_mutex(false)
64 {
65         if(mutex == NULL)
66         {
67                 mutex = new Mutex();
68                 created_mutex = true;
69         }
70         wait_sema = ::CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
71         ::InitializeCriticalSection(&numWaitingLock);
72         wait_done = ::CreateEvent(NULL, false, false, NULL);
73 }
74 CondVar::~CondVar()
75 {
76         if(created_mutex)
77         {
78                 delete mutex;
79         }
80         ::CloseHandle(wait_sema);
81         ::CloseHandle(wait_done);
82         ::DeleteCriticalSection(&numWaitingLock);
83 }
84
85 bool CondVar::unlock()
86 {
87         bool ret = mutex->unlock();
88         return ret;
89 }
90 bool CondVar::lock()
91 {
92         bool ret = mutex->lock();
93         return ret;     
94 }
95 bool CondVar::signal()
96 {
97         ::EnterCriticalSection(&numWaitingLock);
98         bool waitingThreads = (numWaiting > 0);
99         ::LeaveCriticalSection(&numWaitingLock);
100         if(waitingThreads)
101         {
102                 long prev_count;
103                 ::ReleaseSemaphore(wait_sema, 1, &prev_count);
104 //              fprintf(stderr, "[%d]: CondVar::signal() signaled 0x%lx, prev_count = %d\n", ::GetCurrentThreadId(), wait_sema, prev_count);
105         }
106         return true;
107 }
108 bool CondVar::broadcast()
109 {
110         ::EnterCriticalSection(&numWaitingLock);
111         bool waitingThreads = (numWaiting > 0);
112         was_broadcast = true;
113         if(waitingThreads)
114         {
115                 long prev_count;
116                 ::ReleaseSemaphore(wait_sema, 1, &prev_count);
117 //              fprintf(stderr, "[%d]: CondVar::broadcast() signaled 0x%lx, prev_count = %d\n", ::GetCurrentThreadId(), wait_sema, prev_count);
118                 ::LeaveCriticalSection(&numWaitingLock);
119                 ::WaitForSingleObject(wait_done, INFINITE);
120                 was_broadcast = false;
121         }
122         else
123         {
124                 ::LeaveCriticalSection(&numWaitingLock);
125         }
126         return true;
127 }
128 bool CondVar::wait()
129 {
130         ::EnterCriticalSection(&numWaitingLock);
131         numWaiting++;
132         ::LeaveCriticalSection(&numWaitingLock);
133 //      fprintf(stderr, "[%d]: CondVar::wait() signalling for 0x%lx, waiting for 0x%lx\n", ::GetCurrentThreadId(), mutex->mutex, wait_sema);
134         unsigned long result = ::SignalObjectAndWait(mutex->mutex, wait_sema, INFINITE, FALSE);
135         assert(result != WAIT_TIMEOUT);
136         ::EnterCriticalSection(&numWaitingLock);
137         numWaiting--;
138         bool last_waiter = (was_broadcast && (numWaiting == 0));
139         ::LeaveCriticalSection(&numWaitingLock);
140         if(last_waiter)
141         {
142 //              fprintf(stderr, "[%d]: CondVar::wait() waiting for 0x%lx, signaling 0x%lx\n", ::GetCurrentThreadId(), mutex->mutex, wait_done);
143                 result = ::SignalObjectAndWait(wait_done, mutex->mutex, INFINITE, FALSE);
144                 assert(result != WAIT_TIMEOUT);
145         }
146         else
147         {
148                 ::WaitForSingleObject(mutex->mutex, INFINITE);
149         }
150         return true;
151 }