annotate agent/src/os/win32/Monitor.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved.
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 #include <stdio.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
26 #include <assert.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
27 #include "Monitor.hpp"
a61af66fc99e Initial load
duke
parents:
diff changeset
28
a61af66fc99e Initial load
duke
parents:
diff changeset
29 Monitor::Monitor() {
a61af66fc99e Initial load
duke
parents:
diff changeset
30 _lock_count = -1; // No threads have entered the critical section
a61af66fc99e Initial load
duke
parents:
diff changeset
31 _owner = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
32 _lock_event = CreateEvent(NULL, false, false, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
33 _wait_event = CreateEvent(NULL, true, false, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
34 _counter = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
35 _tickets = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
36 _waiters = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
37 }
a61af66fc99e Initial load
duke
parents:
diff changeset
38
a61af66fc99e Initial load
duke
parents:
diff changeset
39 Monitor::~Monitor() {
a61af66fc99e Initial load
duke
parents:
diff changeset
40 assert(_owner == NULL); // Otherwise, owned monitor being deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
41 assert(_lock_count == -1); // Otherwise, monitor being deleted with non -1 lock count
a61af66fc99e Initial load
duke
parents:
diff changeset
42 CloseHandle(_lock_event);
a61af66fc99e Initial load
duke
parents:
diff changeset
43 CloseHandle(_wait_event);
a61af66fc99e Initial load
duke
parents:
diff changeset
44 }
a61af66fc99e Initial load
duke
parents:
diff changeset
45
a61af66fc99e Initial load
duke
parents:
diff changeset
46 void
a61af66fc99e Initial load
duke
parents:
diff changeset
47 Monitor::lock() {
a61af66fc99e Initial load
duke
parents:
diff changeset
48 if (InterlockedIncrement(&_lock_count) == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
49 // Success, we now own the lock
a61af66fc99e Initial load
duke
parents:
diff changeset
50 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
51 DWORD dwRet = WaitForSingleObject((HANDLE)_lock_event, INFINITE);
a61af66fc99e Initial load
duke
parents:
diff changeset
52 assert(dwRet == WAIT_OBJECT_0); // Unexpected return value from WaitForSingleObject
a61af66fc99e Initial load
duke
parents:
diff changeset
53 }
a61af66fc99e Initial load
duke
parents:
diff changeset
54 assert(owner() == NULL); // Otherwise, lock count and owner are inconsistent
a61af66fc99e Initial load
duke
parents:
diff changeset
55 setOwner(GetCurrentThread());
a61af66fc99e Initial load
duke
parents:
diff changeset
56 }
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 void
a61af66fc99e Initial load
duke
parents:
diff changeset
59 Monitor::unlock() {
a61af66fc99e Initial load
duke
parents:
diff changeset
60 setOwner(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
61 if (InterlockedDecrement(&_lock_count) >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // Wake a waiting thread up
a61af66fc99e Initial load
duke
parents:
diff changeset
63 DWORD dwRet = SetEvent(_lock_event);
a61af66fc99e Initial load
duke
parents:
diff changeset
64 assert(dwRet != 0); // Unexpected return value from SetEvent
a61af66fc99e Initial load
duke
parents:
diff changeset
65 }
a61af66fc99e Initial load
duke
parents:
diff changeset
66 }
a61af66fc99e Initial load
duke
parents:
diff changeset
67
a61af66fc99e Initial load
duke
parents:
diff changeset
68 bool
a61af66fc99e Initial load
duke
parents:
diff changeset
69 Monitor::wait(long timeout) {
a61af66fc99e Initial load
duke
parents:
diff changeset
70 assert(owner() != NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
71 assert(owner() == GetCurrentThread());
a61af66fc99e Initial load
duke
parents:
diff changeset
72
a61af66fc99e Initial load
duke
parents:
diff changeset
73 // 0 means forever. Convert to Windows specific code.
a61af66fc99e Initial load
duke
parents:
diff changeset
74 DWORD timeout_value = (timeout == 0) ? INFINITE : timeout;
a61af66fc99e Initial load
duke
parents:
diff changeset
75 DWORD which;
a61af66fc99e Initial load
duke
parents:
diff changeset
76
a61af66fc99e Initial load
duke
parents:
diff changeset
77 long c = _counter;
a61af66fc99e Initial load
duke
parents:
diff changeset
78 bool retry = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 _waiters++;
a61af66fc99e Initial load
duke
parents:
diff changeset
81 // Loop until condition variable is signaled. The event object is
a61af66fc99e Initial load
duke
parents:
diff changeset
82 // set whenever the condition variable is signaled, and tickets will
a61af66fc99e Initial load
duke
parents:
diff changeset
83 // reflect the number of threads which have been notified. The counter
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // field is used to make sure we don't respond to notifications that
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // have occurred *before* we started waiting, and is incremented each
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // time the condition variable is signaled.
a61af66fc99e Initial load
duke
parents:
diff changeset
87
a61af66fc99e Initial load
duke
parents:
diff changeset
88 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
89
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // Leave critical region
a61af66fc99e Initial load
duke
parents:
diff changeset
91 unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
92
a61af66fc99e Initial load
duke
parents:
diff changeset
93 // If this is a retry, let other low-priority threads have a chance
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // to run. Make sure that we sleep outside of the critical section.
a61af66fc99e Initial load
duke
parents:
diff changeset
95 if (retry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
96 Sleep(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
97 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
98 retry = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
99 }
a61af66fc99e Initial load
duke
parents:
diff changeset
100
a61af66fc99e Initial load
duke
parents:
diff changeset
101 which = WaitForSingleObject(_wait_event, timeout_value);
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // Enter critical section
a61af66fc99e Initial load
duke
parents:
diff changeset
103 lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
104
a61af66fc99e Initial load
duke
parents:
diff changeset
105 if (_tickets != 0 && _counter != c) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
106
a61af66fc99e Initial load
duke
parents:
diff changeset
107 if (which == WAIT_TIMEOUT) {
a61af66fc99e Initial load
duke
parents:
diff changeset
108 --_waiters;
a61af66fc99e Initial load
duke
parents:
diff changeset
109 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
110 }
a61af66fc99e Initial load
duke
parents:
diff changeset
111 }
a61af66fc99e Initial load
duke
parents:
diff changeset
112 _waiters--;
a61af66fc99e Initial load
duke
parents:
diff changeset
113
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // If this was the last thread to be notified, then we need to reset
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // the event object.
a61af66fc99e Initial load
duke
parents:
diff changeset
116 if (--_tickets == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
117 ResetEvent(_wait_event);
a61af66fc99e Initial load
duke
parents:
diff changeset
118 }
a61af66fc99e Initial load
duke
parents:
diff changeset
119
a61af66fc99e Initial load
duke
parents:
diff changeset
120 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
122
a61af66fc99e Initial load
duke
parents:
diff changeset
123 // Notify a single thread waiting on this monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
124 bool
a61af66fc99e Initial load
duke
parents:
diff changeset
125 Monitor::notify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 assert(ownedBySelf()); // Otherwise, notify on unknown thread
a61af66fc99e Initial load
duke
parents:
diff changeset
127
a61af66fc99e Initial load
duke
parents:
diff changeset
128 if (_waiters > _tickets) {
a61af66fc99e Initial load
duke
parents:
diff changeset
129 if (!SetEvent(_wait_event)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
131 }
a61af66fc99e Initial load
duke
parents:
diff changeset
132 _tickets++;
a61af66fc99e Initial load
duke
parents:
diff changeset
133 _counter++;
a61af66fc99e Initial load
duke
parents:
diff changeset
134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
135
a61af66fc99e Initial load
duke
parents:
diff changeset
136 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
138
a61af66fc99e Initial load
duke
parents:
diff changeset
139 // Notify all threads waiting on this monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
140 bool
a61af66fc99e Initial load
duke
parents:
diff changeset
141 Monitor::notifyAll() {
a61af66fc99e Initial load
duke
parents:
diff changeset
142 assert(ownedBySelf()); // Otherwise, notifyAll on unknown thread
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144 if (_waiters > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
145 if (!SetEvent(_wait_event)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
146 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
148 _tickets = _waiters;
a61af66fc99e Initial load
duke
parents:
diff changeset
149 _counter++;
a61af66fc99e Initial load
duke
parents:
diff changeset
150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
151
a61af66fc99e Initial load
duke
parents:
diff changeset
152 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154
a61af66fc99e Initial load
duke
parents:
diff changeset
155 HANDLE
a61af66fc99e Initial load
duke
parents:
diff changeset
156 Monitor::owner() {
a61af66fc99e Initial load
duke
parents:
diff changeset
157 return _owner;
a61af66fc99e Initial load
duke
parents:
diff changeset
158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
159
a61af66fc99e Initial load
duke
parents:
diff changeset
160 void
a61af66fc99e Initial load
duke
parents:
diff changeset
161 Monitor::setOwner(HANDLE owner) {
a61af66fc99e Initial load
duke
parents:
diff changeset
162 if (owner != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
163 assert(_owner == NULL); // Setting owner thread of already owned monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
164 assert(owner == GetCurrentThread()); // Else should not be doing this
a61af66fc99e Initial load
duke
parents:
diff changeset
165 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
166 HANDLE oldOwner = _owner;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 assert(oldOwner != NULL); // Removing the owner thread of an unowned mutex
a61af66fc99e Initial load
duke
parents:
diff changeset
168 assert(oldOwner == GetCurrentThread());
a61af66fc99e Initial load
duke
parents:
diff changeset
169 }
a61af66fc99e Initial load
duke
parents:
diff changeset
170 _owner = owner;
a61af66fc99e Initial load
duke
parents:
diff changeset
171 }
a61af66fc99e Initial load
duke
parents:
diff changeset
172
a61af66fc99e Initial load
duke
parents:
diff changeset
173 bool
a61af66fc99e Initial load
duke
parents:
diff changeset
174 Monitor::ownedBySelf() {
a61af66fc99e Initial load
duke
parents:
diff changeset
175 return (_owner == GetCurrentThread());
a61af66fc99e Initial load
duke
parents:
diff changeset
176 }