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