Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: runtime/vm/os_thread_win.cc

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/os_thread_win.h ('k') | runtime/vm/os_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" // NOLINT 5 #include "platform/globals.h" // NOLINT
6 #if defined(HOST_OS_WINDOWS) 6 #if defined(HOST_OS_WINDOWS)
7 7
8 #include "vm/growable_array.h" 8 #include "vm/growable_array.h"
9 #include "vm/lockers.h" 9 #include "vm/lockers.h"
10 #include "vm/os_thread.h" 10 #include "vm/os_thread.h"
(...skipping 20 matching lines...) Expand all
31 uword parameter() const { return parameter_; } 31 uword parameter() const { return parameter_; }
32 32
33 private: 33 private:
34 const char* name_; 34 const char* name_;
35 OSThread::ThreadStartFunction function_; 35 OSThread::ThreadStartFunction function_;
36 uword parameter_; 36 uword parameter_;
37 37
38 DISALLOW_COPY_AND_ASSIGN(ThreadStartData); 38 DISALLOW_COPY_AND_ASSIGN(ThreadStartData);
39 }; 39 };
40 40
41
42 // Dispatch to the thread start function provided by the caller. This trampoline 41 // Dispatch to the thread start function provided by the caller. This trampoline
43 // is used to ensure that the thread is properly destroyed if the thread just 42 // is used to ensure that the thread is properly destroyed if the thread just
44 // exits. 43 // exits.
45 static unsigned int __stdcall ThreadEntry(void* data_ptr) { 44 static unsigned int __stdcall ThreadEntry(void* data_ptr) {
46 ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr); 45 ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr);
47 46
48 const char* name = data->name(); 47 const char* name = data->name();
49 OSThread::ThreadStartFunction function = data->function(); 48 OSThread::ThreadStartFunction function = data->function();
50 uword parameter = data->parameter(); 49 uword parameter = data->parameter();
51 delete data; 50 delete data;
52 51
53 MonitorData::GetMonitorWaitDataForThread(); 52 MonitorData::GetMonitorWaitDataForThread();
54 53
55 // Create new OSThread object and set as TLS for new thread. 54 // Create new OSThread object and set as TLS for new thread.
56 OSThread* thread = OSThread::CreateOSThread(); 55 OSThread* thread = OSThread::CreateOSThread();
57 if (thread != NULL) { 56 if (thread != NULL) {
58 OSThread::SetCurrent(thread); 57 OSThread::SetCurrent(thread);
59 thread->set_name(name); 58 thread->set_name(name);
60 59
61 // Call the supplied thread start function handing it its parameters. 60 // Call the supplied thread start function handing it its parameters.
62 function(parameter); 61 function(parameter);
63 } 62 }
64 63
65 // Clean up the monitor wait data for this thread. 64 // Clean up the monitor wait data for this thread.
66 MonitorWaitData::ThreadExit(); 65 MonitorWaitData::ThreadExit();
67 66
68 return 0; 67 return 0;
69 } 68 }
70 69
71
72 int OSThread::Start(const char* name, 70 int OSThread::Start(const char* name,
73 ThreadStartFunction function, 71 ThreadStartFunction function,
74 uword parameter) { 72 uword parameter) {
75 ThreadStartData* start_data = new ThreadStartData(name, function, parameter); 73 ThreadStartData* start_data = new ThreadStartData(name, function, parameter);
76 uint32_t tid; 74 uint32_t tid;
77 uintptr_t thread = _beginthreadex(NULL, OSThread::GetMaxStackSize(), 75 uintptr_t thread = _beginthreadex(NULL, OSThread::GetMaxStackSize(),
78 ThreadEntry, start_data, 0, &tid); 76 ThreadEntry, start_data, 0, &tid);
79 if (thread == -1L || thread == 0) { 77 if (thread == -1L || thread == 0) {
80 #ifdef DEBUG 78 #ifdef DEBUG
81 fprintf(stderr, "_beginthreadex error: %d (%s)\n", errno, strerror(errno)); 79 fprintf(stderr, "_beginthreadex error: %d (%s)\n", errno, strerror(errno));
82 #endif 80 #endif
83 return errno; 81 return errno;
84 } 82 }
85 83
86 // Close the handle, so we don't leak the thread object. 84 // Close the handle, so we don't leak the thread object.
87 CloseHandle(reinterpret_cast<HANDLE>(thread)); 85 CloseHandle(reinterpret_cast<HANDLE>(thread));
88 86
89 return 0; 87 return 0;
90 } 88 }
91 89
92
93 const ThreadId OSThread::kInvalidThreadId = 0; 90 const ThreadId OSThread::kInvalidThreadId = 0;
94 const ThreadJoinId OSThread::kInvalidThreadJoinId = NULL; 91 const ThreadJoinId OSThread::kInvalidThreadJoinId = NULL;
95 92
96
97 ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor destructor) { 93 ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor destructor) {
98 ThreadLocalKey key = TlsAlloc(); 94 ThreadLocalKey key = TlsAlloc();
99 if (key == kUnsetThreadLocalKey) { 95 if (key == kUnsetThreadLocalKey) {
100 FATAL1("TlsAlloc failed %d", GetLastError()); 96 FATAL1("TlsAlloc failed %d", GetLastError());
101 } 97 }
102 ThreadLocalData::AddThreadLocal(key, destructor); 98 ThreadLocalData::AddThreadLocal(key, destructor);
103 return key; 99 return key;
104 } 100 }
105 101
106
107 void OSThread::DeleteThreadLocal(ThreadLocalKey key) { 102 void OSThread::DeleteThreadLocal(ThreadLocalKey key) {
108 ASSERT(key != kUnsetThreadLocalKey); 103 ASSERT(key != kUnsetThreadLocalKey);
109 BOOL result = TlsFree(key); 104 BOOL result = TlsFree(key);
110 if (!result) { 105 if (!result) {
111 FATAL1("TlsFree failed %d", GetLastError()); 106 FATAL1("TlsFree failed %d", GetLastError());
112 } 107 }
113 ThreadLocalData::RemoveThreadLocal(key); 108 ThreadLocalData::RemoveThreadLocal(key);
114 } 109 }
115 110
116
117 intptr_t OSThread::GetMaxStackSize() { 111 intptr_t OSThread::GetMaxStackSize() {
118 const int kStackSize = (128 * kWordSize * KB); 112 const int kStackSize = (128 * kWordSize * KB);
119 return kStackSize; 113 return kStackSize;
120 } 114 }
121 115
122
123 ThreadId OSThread::GetCurrentThreadId() { 116 ThreadId OSThread::GetCurrentThreadId() {
124 return ::GetCurrentThreadId(); 117 return ::GetCurrentThreadId();
125 } 118 }
126 119
127
128 #ifndef PRODUCT 120 #ifndef PRODUCT
129 ThreadId OSThread::GetCurrentThreadTraceId() { 121 ThreadId OSThread::GetCurrentThreadTraceId() {
130 return ::GetCurrentThreadId(); 122 return ::GetCurrentThreadId();
131 } 123 }
132 #endif // PRODUCT 124 #endif // PRODUCT
133 125
134
135 ThreadJoinId OSThread::GetCurrentThreadJoinId(OSThread* thread) { 126 ThreadJoinId OSThread::GetCurrentThreadJoinId(OSThread* thread) {
136 ASSERT(thread != NULL); 127 ASSERT(thread != NULL);
137 // Make sure we're filling in the join id for the current thread. 128 // Make sure we're filling in the join id for the current thread.
138 ThreadId id = GetCurrentThreadId(); 129 ThreadId id = GetCurrentThreadId();
139 ASSERT(thread->id() == id); 130 ASSERT(thread->id() == id);
140 // Make sure the join_id_ hasn't been set, yet. 131 // Make sure the join_id_ hasn't been set, yet.
141 DEBUG_ASSERT(thread->join_id_ == kInvalidThreadJoinId); 132 DEBUG_ASSERT(thread->join_id_ == kInvalidThreadJoinId);
142 HANDLE handle = OpenThread(SYNCHRONIZE, false, id); 133 HANDLE handle = OpenThread(SYNCHRONIZE, false, id);
143 ASSERT(handle != NULL); 134 ASSERT(handle != NULL);
144 #if defined(DEBUG) 135 #if defined(DEBUG)
145 thread->join_id_ = handle; 136 thread->join_id_ = handle;
146 #endif 137 #endif
147 return handle; 138 return handle;
148 } 139 }
149 140
150
151 void OSThread::Join(ThreadJoinId id) { 141 void OSThread::Join(ThreadJoinId id) {
152 HANDLE handle = static_cast<HANDLE>(id); 142 HANDLE handle = static_cast<HANDLE>(id);
153 ASSERT(handle != NULL); 143 ASSERT(handle != NULL);
154 DWORD res = WaitForSingleObject(handle, INFINITE); 144 DWORD res = WaitForSingleObject(handle, INFINITE);
155 CloseHandle(handle); 145 CloseHandle(handle);
156 ASSERT(res == WAIT_OBJECT_0); 146 ASSERT(res == WAIT_OBJECT_0);
157 } 147 }
158 148
159
160 intptr_t OSThread::ThreadIdToIntPtr(ThreadId id) { 149 intptr_t OSThread::ThreadIdToIntPtr(ThreadId id) {
161 ASSERT(sizeof(id) <= sizeof(intptr_t)); 150 ASSERT(sizeof(id) <= sizeof(intptr_t));
162 return static_cast<intptr_t>(id); 151 return static_cast<intptr_t>(id);
163 } 152 }
164 153
165
166 ThreadId OSThread::ThreadIdFromIntPtr(intptr_t id) { 154 ThreadId OSThread::ThreadIdFromIntPtr(intptr_t id) {
167 return static_cast<ThreadId>(id); 155 return static_cast<ThreadId>(id);
168 } 156 }
169 157
170
171 bool OSThread::Compare(ThreadId a, ThreadId b) { 158 bool OSThread::Compare(ThreadId a, ThreadId b) {
172 return a == b; 159 return a == b;
173 } 160 }
174 161
175
176 bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) { 162 bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
177 // On Windows stack limits for the current thread are available in 163 // On Windows stack limits for the current thread are available in
178 // the thread information block (TIB). Its fields can be accessed through 164 // the thread information block (TIB). Its fields can be accessed through
179 // FS segment register on x86 and GS segment register on x86_64. 165 // FS segment register on x86 and GS segment register on x86_64.
180 #ifdef _WIN64 166 #ifdef _WIN64
181 *upper = static_cast<uword>(__readgsqword(offsetof(NT_TIB64, StackBase))); 167 *upper = static_cast<uword>(__readgsqword(offsetof(NT_TIB64, StackBase)));
182 *lower = static_cast<uword>(__readgsqword(offsetof(NT_TIB64, StackLimit))); 168 *lower = static_cast<uword>(__readgsqword(offsetof(NT_TIB64, StackLimit)));
183 #else 169 #else
184 *upper = static_cast<uword>(__readfsdword(offsetof(NT_TIB, StackBase))); 170 *upper = static_cast<uword>(__readfsdword(offsetof(NT_TIB, StackBase)));
185 *lower = static_cast<uword>(__readfsdword(offsetof(NT_TIB, StackLimit))); 171 *lower = static_cast<uword>(__readfsdword(offsetof(NT_TIB, StackLimit)));
186 #endif 172 #endif
187 return true; 173 return true;
188 } 174 }
189 175
190
191 void OSThread::SetThreadLocal(ThreadLocalKey key, uword value) { 176 void OSThread::SetThreadLocal(ThreadLocalKey key, uword value) {
192 ASSERT(key != kUnsetThreadLocalKey); 177 ASSERT(key != kUnsetThreadLocalKey);
193 BOOL result = TlsSetValue(key, reinterpret_cast<void*>(value)); 178 BOOL result = TlsSetValue(key, reinterpret_cast<void*>(value));
194 if (!result) { 179 if (!result) {
195 FATAL1("TlsSetValue failed %d", GetLastError()); 180 FATAL1("TlsSetValue failed %d", GetLastError());
196 } 181 }
197 } 182 }
198 183
199
200 Mutex::Mutex() { 184 Mutex::Mutex() {
201 // Allocate unnamed semaphore with initial count 1 and max count 1. 185 // Allocate unnamed semaphore with initial count 1 and max count 1.
202 data_.semaphore_ = CreateSemaphore(NULL, 1, 1, NULL); 186 data_.semaphore_ = CreateSemaphore(NULL, 1, 1, NULL);
203 if (data_.semaphore_ == NULL) { 187 if (data_.semaphore_ == NULL) {
204 FATAL1("Mutex allocation failed %d", GetLastError()); 188 FATAL1("Mutex allocation failed %d", GetLastError());
205 } 189 }
206 #if defined(DEBUG) 190 #if defined(DEBUG)
207 // When running with assertions enabled we do track the owner. 191 // When running with assertions enabled we do track the owner.
208 owner_ = OSThread::kInvalidThreadId; 192 owner_ = OSThread::kInvalidThreadId;
209 #endif // defined(DEBUG) 193 #endif // defined(DEBUG)
210 } 194 }
211 195
212
213 Mutex::~Mutex() { 196 Mutex::~Mutex() {
214 CloseHandle(data_.semaphore_); 197 CloseHandle(data_.semaphore_);
215 #if defined(DEBUG) 198 #if defined(DEBUG)
216 // When running with assertions enabled we do track the owner. 199 // When running with assertions enabled we do track the owner.
217 ASSERT(owner_ == OSThread::kInvalidThreadId); 200 ASSERT(owner_ == OSThread::kInvalidThreadId);
218 #endif // defined(DEBUG) 201 #endif // defined(DEBUG)
219 } 202 }
220 203
221
222 void Mutex::Lock() { 204 void Mutex::Lock() {
223 DWORD result = WaitForSingleObject(data_.semaphore_, INFINITE); 205 DWORD result = WaitForSingleObject(data_.semaphore_, INFINITE);
224 if (result != WAIT_OBJECT_0) { 206 if (result != WAIT_OBJECT_0) {
225 FATAL1("Mutex lock failed %d", GetLastError()); 207 FATAL1("Mutex lock failed %d", GetLastError());
226 } 208 }
227 #if defined(DEBUG) 209 #if defined(DEBUG)
228 // When running with assertions enabled we do track the owner. 210 // When running with assertions enabled we do track the owner.
229 owner_ = OSThread::GetCurrentThreadId(); 211 owner_ = OSThread::GetCurrentThreadId();
230 #endif // defined(DEBUG) 212 #endif // defined(DEBUG)
231 } 213 }
232 214
233
234 bool Mutex::TryLock() { 215 bool Mutex::TryLock() {
235 // Attempt to pass the semaphore but return immediately. 216 // Attempt to pass the semaphore but return immediately.
236 DWORD result = WaitForSingleObject(data_.semaphore_, 0); 217 DWORD result = WaitForSingleObject(data_.semaphore_, 0);
237 if (result == WAIT_OBJECT_0) { 218 if (result == WAIT_OBJECT_0) {
238 #if defined(DEBUG) 219 #if defined(DEBUG)
239 // When running with assertions enabled we do track the owner. 220 // When running with assertions enabled we do track the owner.
240 owner_ = OSThread::GetCurrentThreadId(); 221 owner_ = OSThread::GetCurrentThreadId();
241 #endif // defined(DEBUG) 222 #endif // defined(DEBUG)
242 return true; 223 return true;
243 } 224 }
244 if (result == WAIT_ABANDONED || result == WAIT_FAILED) { 225 if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
245 FATAL1("Mutex try lock failed %d", GetLastError()); 226 FATAL1("Mutex try lock failed %d", GetLastError());
246 } 227 }
247 ASSERT(result == WAIT_TIMEOUT); 228 ASSERT(result == WAIT_TIMEOUT);
248 return false; 229 return false;
249 } 230 }
250 231
251
252 void Mutex::Unlock() { 232 void Mutex::Unlock() {
253 #if defined(DEBUG) 233 #if defined(DEBUG)
254 // When running with assertions enabled we do track the owner. 234 // When running with assertions enabled we do track the owner.
255 ASSERT(IsOwnedByCurrentThread()); 235 ASSERT(IsOwnedByCurrentThread());
256 owner_ = OSThread::kInvalidThreadId; 236 owner_ = OSThread::kInvalidThreadId;
257 #endif // defined(DEBUG) 237 #endif // defined(DEBUG)
258 BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL); 238 BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL);
259 if (result == 0) { 239 if (result == 0) {
260 FATAL1("Mutex unlock failed %d", GetLastError()); 240 FATAL1("Mutex unlock failed %d", GetLastError());
261 } 241 }
262 } 242 }
263 243
264
265 ThreadLocalKey MonitorWaitData::monitor_wait_data_key_ = kUnsetThreadLocalKey; 244 ThreadLocalKey MonitorWaitData::monitor_wait_data_key_ = kUnsetThreadLocalKey;
266 245
267
268 Monitor::Monitor() { 246 Monitor::Monitor() {
269 InitializeCriticalSection(&data_.cs_); 247 InitializeCriticalSection(&data_.cs_);
270 InitializeCriticalSection(&data_.waiters_cs_); 248 InitializeCriticalSection(&data_.waiters_cs_);
271 data_.waiters_head_ = NULL; 249 data_.waiters_head_ = NULL;
272 data_.waiters_tail_ = NULL; 250 data_.waiters_tail_ = NULL;
273 251
274 #if defined(DEBUG) 252 #if defined(DEBUG)
275 // When running with assertions enabled we track the owner. 253 // When running with assertions enabled we track the owner.
276 owner_ = OSThread::kInvalidThreadId; 254 owner_ = OSThread::kInvalidThreadId;
277 #endif // defined(DEBUG) 255 #endif // defined(DEBUG)
278 } 256 }
279 257
280
281 Monitor::~Monitor() { 258 Monitor::~Monitor() {
282 #if defined(DEBUG) 259 #if defined(DEBUG)
283 // When running with assertions enabled we track the owner. 260 // When running with assertions enabled we track the owner.
284 ASSERT(owner_ == OSThread::kInvalidThreadId); 261 ASSERT(owner_ == OSThread::kInvalidThreadId);
285 #endif // defined(DEBUG) 262 #endif // defined(DEBUG)
286 263
287 DeleteCriticalSection(&data_.cs_); 264 DeleteCriticalSection(&data_.cs_);
288 DeleteCriticalSection(&data_.waiters_cs_); 265 DeleteCriticalSection(&data_.waiters_cs_);
289 } 266 }
290 267
291
292 bool Monitor::TryEnter() { 268 bool Monitor::TryEnter() {
293 // Attempt to pass the semaphore but return immediately. 269 // Attempt to pass the semaphore but return immediately.
294 BOOL result = TryEnterCriticalSection(&data_.cs_); 270 BOOL result = TryEnterCriticalSection(&data_.cs_);
295 if (!result) { 271 if (!result) {
296 return false; 272 return false;
297 } 273 }
298 #if defined(DEBUG) 274 #if defined(DEBUG)
299 // When running with assertions enabled we do track the owner. 275 // When running with assertions enabled we do track the owner.
300 ASSERT(owner_ == OSThread::kInvalidThreadId); 276 ASSERT(owner_ == OSThread::kInvalidThreadId);
301 owner_ = OSThread::GetCurrentThreadId(); 277 owner_ = OSThread::GetCurrentThreadId();
302 #endif // defined(DEBUG) 278 #endif // defined(DEBUG)
303 return true; 279 return true;
304 } 280 }
305 281
306
307 void Monitor::Enter() { 282 void Monitor::Enter() {
308 EnterCriticalSection(&data_.cs_); 283 EnterCriticalSection(&data_.cs_);
309 284
310 #if defined(DEBUG) 285 #if defined(DEBUG)
311 // When running with assertions enabled we track the owner. 286 // When running with assertions enabled we track the owner.
312 ASSERT(owner_ == OSThread::kInvalidThreadId); 287 ASSERT(owner_ == OSThread::kInvalidThreadId);
313 owner_ = OSThread::GetCurrentThreadId(); 288 owner_ = OSThread::GetCurrentThreadId();
314 #endif // defined(DEBUG) 289 #endif // defined(DEBUG)
315 } 290 }
316 291
317
318 void Monitor::Exit() { 292 void Monitor::Exit() {
319 #if defined(DEBUG) 293 #if defined(DEBUG)
320 // When running with assertions enabled we track the owner. 294 // When running with assertions enabled we track the owner.
321 ASSERT(IsOwnedByCurrentThread()); 295 ASSERT(IsOwnedByCurrentThread());
322 owner_ = OSThread::kInvalidThreadId; 296 owner_ = OSThread::kInvalidThreadId;
323 #endif // defined(DEBUG) 297 #endif // defined(DEBUG)
324 298
325 LeaveCriticalSection(&data_.cs_); 299 LeaveCriticalSection(&data_.cs_);
326 } 300 }
327 301
328
329 void MonitorWaitData::ThreadExit() { 302 void MonitorWaitData::ThreadExit() {
330 if (MonitorWaitData::monitor_wait_data_key_ != kUnsetThreadLocalKey) { 303 if (MonitorWaitData::monitor_wait_data_key_ != kUnsetThreadLocalKey) {
331 uword raw_wait_data = 304 uword raw_wait_data =
332 OSThread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_); 305 OSThread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_);
333 // Clear in case this is called a second time. 306 // Clear in case this is called a second time.
334 OSThread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_, 0); 307 OSThread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_, 0);
335 if (raw_wait_data != 0) { 308 if (raw_wait_data != 0) {
336 MonitorWaitData* wait_data = 309 MonitorWaitData* wait_data =
337 reinterpret_cast<MonitorWaitData*>(raw_wait_data); 310 reinterpret_cast<MonitorWaitData*>(raw_wait_data);
338 delete wait_data; 311 delete wait_data;
339 } 312 }
340 } 313 }
341 } 314 }
342 315
343
344 void MonitorData::AddWaiter(MonitorWaitData* wait_data) { 316 void MonitorData::AddWaiter(MonitorWaitData* wait_data) {
345 // Add the MonitorWaitData object to the list of objects waiting for 317 // Add the MonitorWaitData object to the list of objects waiting for
346 // this monitor. 318 // this monitor.
347 EnterCriticalSection(&waiters_cs_); 319 EnterCriticalSection(&waiters_cs_);
348 if (waiters_tail_ == NULL) { 320 if (waiters_tail_ == NULL) {
349 ASSERT(waiters_head_ == NULL); 321 ASSERT(waiters_head_ == NULL);
350 waiters_head_ = waiters_tail_ = wait_data; 322 waiters_head_ = waiters_tail_ = wait_data;
351 } else { 323 } else {
352 waiters_tail_->next_ = wait_data; 324 waiters_tail_->next_ = wait_data;
353 waiters_tail_ = wait_data; 325 waiters_tail_ = wait_data;
354 } 326 }
355 LeaveCriticalSection(&waiters_cs_); 327 LeaveCriticalSection(&waiters_cs_);
356 } 328 }
357 329
358
359 void MonitorData::RemoveWaiter(MonitorWaitData* wait_data) { 330 void MonitorData::RemoveWaiter(MonitorWaitData* wait_data) {
360 // Remove the MonitorWaitData object from the list of objects 331 // Remove the MonitorWaitData object from the list of objects
361 // waiting for this monitor. 332 // waiting for this monitor.
362 EnterCriticalSection(&waiters_cs_); 333 EnterCriticalSection(&waiters_cs_);
363 MonitorWaitData* previous = NULL; 334 MonitorWaitData* previous = NULL;
364 MonitorWaitData* current = waiters_head_; 335 MonitorWaitData* current = waiters_head_;
365 while (current != NULL) { 336 while (current != NULL) {
366 if (current == wait_data) { 337 if (current == wait_data) {
367 if (waiters_head_ == waiters_tail_) { 338 if (waiters_head_ == waiters_tail_) {
368 waiters_head_ = waiters_tail_ = NULL; 339 waiters_head_ = waiters_tail_ = NULL;
(...skipping 10 matching lines...) Expand all
379 // Clear next. 350 // Clear next.
380 wait_data->next_ = NULL; 351 wait_data->next_ = NULL;
381 break; 352 break;
382 } 353 }
383 previous = current; 354 previous = current;
384 current = current->next_; 355 current = current->next_;
385 } 356 }
386 LeaveCriticalSection(&waiters_cs_); 357 LeaveCriticalSection(&waiters_cs_);
387 } 358 }
388 359
389
390 void MonitorData::SignalAndRemoveFirstWaiter() { 360 void MonitorData::SignalAndRemoveFirstWaiter() {
391 EnterCriticalSection(&waiters_cs_); 361 EnterCriticalSection(&waiters_cs_);
392 MonitorWaitData* first = waiters_head_; 362 MonitorWaitData* first = waiters_head_;
393 if (first != NULL) { 363 if (first != NULL) {
394 // Remove from list. 364 // Remove from list.
395 if (waiters_head_ == waiters_tail_) { 365 if (waiters_head_ == waiters_tail_) {
396 waiters_tail_ = waiters_head_ = NULL; 366 waiters_tail_ = waiters_head_ = NULL;
397 } else { 367 } else {
398 waiters_head_ = waiters_head_->next_; 368 waiters_head_ = waiters_head_->next_;
399 } 369 }
400 // Clear next. 370 // Clear next.
401 first->next_ = NULL; 371 first->next_ = NULL;
402 // Signal event. 372 // Signal event.
403 BOOL result = SetEvent(first->event_); 373 BOOL result = SetEvent(first->event_);
404 if (result == 0) { 374 if (result == 0) {
405 FATAL1("Monitor::Notify failed to signal event %d", GetLastError()); 375 FATAL1("Monitor::Notify failed to signal event %d", GetLastError());
406 } 376 }
407 } 377 }
408 LeaveCriticalSection(&waiters_cs_); 378 LeaveCriticalSection(&waiters_cs_);
409 } 379 }
410 380
411
412 void MonitorData::SignalAndRemoveAllWaiters() { 381 void MonitorData::SignalAndRemoveAllWaiters() {
413 EnterCriticalSection(&waiters_cs_); 382 EnterCriticalSection(&waiters_cs_);
414 // Extract list to signal. 383 // Extract list to signal.
415 MonitorWaitData* current = waiters_head_; 384 MonitorWaitData* current = waiters_head_;
416 // Clear list. 385 // Clear list.
417 waiters_head_ = waiters_tail_ = NULL; 386 waiters_head_ = waiters_tail_ = NULL;
418 // Iterate and signal all events. 387 // Iterate and signal all events.
419 while (current != NULL) { 388 while (current != NULL) {
420 // Copy next. 389 // Copy next.
421 MonitorWaitData* next = current->next_; 390 MonitorWaitData* next = current->next_;
422 // Clear next. 391 // Clear next.
423 current->next_ = NULL; 392 current->next_ = NULL;
424 // Signal event. 393 // Signal event.
425 BOOL result = SetEvent(current->event_); 394 BOOL result = SetEvent(current->event_);
426 if (result == 0) { 395 if (result == 0) {
427 FATAL1("Failed to set event for NotifyAll %d", GetLastError()); 396 FATAL1("Failed to set event for NotifyAll %d", GetLastError());
428 } 397 }
429 current = next; 398 current = next;
430 } 399 }
431 LeaveCriticalSection(&waiters_cs_); 400 LeaveCriticalSection(&waiters_cs_);
432 } 401 }
433 402
434
435 MonitorWaitData* MonitorData::GetMonitorWaitDataForThread() { 403 MonitorWaitData* MonitorData::GetMonitorWaitDataForThread() {
436 // Ensure that the thread local key for monitor wait data objects is 404 // Ensure that the thread local key for monitor wait data objects is
437 // initialized. 405 // initialized.
438 ASSERT(MonitorWaitData::monitor_wait_data_key_ != kUnsetThreadLocalKey); 406 ASSERT(MonitorWaitData::monitor_wait_data_key_ != kUnsetThreadLocalKey);
439 407
440 // Get the MonitorWaitData object containing the event for this 408 // Get the MonitorWaitData object containing the event for this
441 // thread from thread local storage. Create it if it does not exist. 409 // thread from thread local storage. Create it if it does not exist.
442 uword raw_wait_data = 410 uword raw_wait_data =
443 OSThread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_); 411 OSThread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_);
444 MonitorWaitData* wait_data = NULL; 412 MonitorWaitData* wait_data = NULL;
445 if (raw_wait_data == 0) { 413 if (raw_wait_data == 0) {
446 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL); 414 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
447 wait_data = new MonitorWaitData(event); 415 wait_data = new MonitorWaitData(event);
448 OSThread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_, 416 OSThread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_,
449 reinterpret_cast<uword>(wait_data)); 417 reinterpret_cast<uword>(wait_data));
450 } else { 418 } else {
451 wait_data = reinterpret_cast<MonitorWaitData*>(raw_wait_data); 419 wait_data = reinterpret_cast<MonitorWaitData*>(raw_wait_data);
452 wait_data->next_ = NULL; 420 wait_data->next_ = NULL;
453 } 421 }
454 return wait_data; 422 return wait_data;
455 } 423 }
456 424
457
458 Monitor::WaitResult Monitor::Wait(int64_t millis) { 425 Monitor::WaitResult Monitor::Wait(int64_t millis) {
459 #if defined(DEBUG) 426 #if defined(DEBUG)
460 // When running with assertions enabled we track the owner. 427 // When running with assertions enabled we track the owner.
461 ASSERT(IsOwnedByCurrentThread()); 428 ASSERT(IsOwnedByCurrentThread());
462 ThreadId saved_owner = owner_; 429 ThreadId saved_owner = owner_;
463 owner_ = OSThread::kInvalidThreadId; 430 owner_ = OSThread::kInvalidThreadId;
464 #endif // defined(DEBUG) 431 #endif // defined(DEBUG)
465 432
466 Monitor::WaitResult retval = kNotified; 433 Monitor::WaitResult retval = kNotified;
467 434
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 469
503 #if defined(DEBUG) 470 #if defined(DEBUG)
504 // When running with assertions enabled we track the owner. 471 // When running with assertions enabled we track the owner.
505 ASSERT(owner_ == OSThread::kInvalidThreadId); 472 ASSERT(owner_ == OSThread::kInvalidThreadId);
506 owner_ = OSThread::GetCurrentThreadId(); 473 owner_ = OSThread::GetCurrentThreadId();
507 ASSERT(owner_ == saved_owner); 474 ASSERT(owner_ == saved_owner);
508 #endif // defined(DEBUG) 475 #endif // defined(DEBUG)
509 return retval; 476 return retval;
510 } 477 }
511 478
512
513 Monitor::WaitResult Monitor::WaitMicros(int64_t micros) { 479 Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
514 // TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows. 480 // TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows.
515 int64_t millis = micros / kMicrosecondsPerMillisecond; 481 int64_t millis = micros / kMicrosecondsPerMillisecond;
516 if ((millis * kMicrosecondsPerMillisecond) < micros) { 482 if ((millis * kMicrosecondsPerMillisecond) < micros) {
517 // We've been asked to sleep for a fraction of a millisecond, 483 // We've been asked to sleep for a fraction of a millisecond,
518 // this isn't supported on Windows. Bumps milliseconds up by one 484 // this isn't supported on Windows. Bumps milliseconds up by one
519 // so that we never return too early. We likely return late though. 485 // so that we never return too early. We likely return late though.
520 millis += 1; 486 millis += 1;
521 } 487 }
522 return Wait(millis); 488 return Wait(millis);
523 } 489 }
524 490
525
526 void Monitor::Notify() { 491 void Monitor::Notify() {
527 // When running with assertions enabled we track the owner. 492 // When running with assertions enabled we track the owner.
528 ASSERT(IsOwnedByCurrentThread()); 493 ASSERT(IsOwnedByCurrentThread());
529 data_.SignalAndRemoveFirstWaiter(); 494 data_.SignalAndRemoveFirstWaiter();
530 } 495 }
531 496
532
533 void Monitor::NotifyAll() { 497 void Monitor::NotifyAll() {
534 // When running with assertions enabled we track the owner. 498 // When running with assertions enabled we track the owner.
535 ASSERT(IsOwnedByCurrentThread()); 499 ASSERT(IsOwnedByCurrentThread());
536 // If one of the objects in the list of waiters wakes because of a 500 // If one of the objects in the list of waiters wakes because of a
537 // timeout before we signal it, that object will get an extra 501 // timeout before we signal it, that object will get an extra
538 // signal. This will be treated as a spurious wake-up and is OK 502 // signal. This will be treated as a spurious wake-up and is OK
539 // since all uses of monitors should recheck the condition after a 503 // since all uses of monitors should recheck the condition after a
540 // Wait. 504 // Wait.
541 data_.SignalAndRemoveAllWaiters(); 505 data_.SignalAndRemoveAllWaiters();
542 } 506 }
543 507
544
545 void ThreadLocalData::AddThreadLocal(ThreadLocalKey key, 508 void ThreadLocalData::AddThreadLocal(ThreadLocalKey key,
546 ThreadDestructor destructor) { 509 ThreadDestructor destructor) {
547 ASSERT(thread_locals_ != NULL); 510 ASSERT(thread_locals_ != NULL);
548 if (destructor == NULL) { 511 if (destructor == NULL) {
549 // We only care about thread locals with destructors. 512 // We only care about thread locals with destructors.
550 return; 513 return;
551 } 514 }
552 MutexLocker ml(mutex_, false); 515 MutexLocker ml(mutex_, false);
553 #if defined(DEBUG) 516 #if defined(DEBUG)
554 // Verify that we aren't added twice. 517 // Verify that we aren't added twice.
555 for (intptr_t i = 0; i < thread_locals_->length(); i++) { 518 for (intptr_t i = 0; i < thread_locals_->length(); i++) {
556 const ThreadLocalEntry& entry = thread_locals_->At(i); 519 const ThreadLocalEntry& entry = thread_locals_->At(i);
557 ASSERT(entry.key() != key); 520 ASSERT(entry.key() != key);
558 } 521 }
559 #endif 522 #endif
560 // Add to list. 523 // Add to list.
561 thread_locals_->Add(ThreadLocalEntry(key, destructor)); 524 thread_locals_->Add(ThreadLocalEntry(key, destructor));
562 } 525 }
563 526
564
565 void ThreadLocalData::RemoveThreadLocal(ThreadLocalKey key) { 527 void ThreadLocalData::RemoveThreadLocal(ThreadLocalKey key) {
566 ASSERT(thread_locals_ != NULL); 528 ASSERT(thread_locals_ != NULL);
567 MutexLocker ml(mutex_, false); 529 MutexLocker ml(mutex_, false);
568 intptr_t i = 0; 530 intptr_t i = 0;
569 for (; i < thread_locals_->length(); i++) { 531 for (; i < thread_locals_->length(); i++) {
570 const ThreadLocalEntry& entry = thread_locals_->At(i); 532 const ThreadLocalEntry& entry = thread_locals_->At(i);
571 if (entry.key() == key) { 533 if (entry.key() == key) {
572 break; 534 break;
573 } 535 }
574 } 536 }
575 if (i == thread_locals_->length()) { 537 if (i == thread_locals_->length()) {
576 // Not found. 538 // Not found.
577 return; 539 return;
578 } 540 }
579 thread_locals_->RemoveAt(i); 541 thread_locals_->RemoveAt(i);
580 } 542 }
581 543
582
583 // This function is executed on the thread that is exiting. It is invoked 544 // This function is executed on the thread that is exiting. It is invoked
584 // by |OnDartThreadExit| (see below for notes on TLS destructors on Windows). 545 // by |OnDartThreadExit| (see below for notes on TLS destructors on Windows).
585 void ThreadLocalData::RunDestructors() { 546 void ThreadLocalData::RunDestructors() {
586 ASSERT(thread_locals_ != NULL); 547 ASSERT(thread_locals_ != NULL);
587 ASSERT(mutex_ != NULL); 548 ASSERT(mutex_ != NULL);
588 MutexLocker ml(mutex_, false); 549 MutexLocker ml(mutex_, false);
589 for (intptr_t i = 0; i < thread_locals_->length(); i++) { 550 for (intptr_t i = 0; i < thread_locals_->length(); i++) {
590 const ThreadLocalEntry& entry = thread_locals_->At(i); 551 const ThreadLocalEntry& entry = thread_locals_->At(i);
591 // We access the exiting thread's TLS variable here. 552 // We access the exiting thread's TLS variable here.
592 void* p = reinterpret_cast<void*>(OSThread::GetThreadLocal(entry.key())); 553 void* p = reinterpret_cast<void*>(OSThread::GetThreadLocal(entry.key()));
593 // We invoke the constructor here. 554 // We invoke the constructor here.
594 entry.destructor()(p); 555 entry.destructor()(p);
595 } 556 }
596 } 557 }
597 558
598
599 Mutex* ThreadLocalData::mutex_ = NULL; 559 Mutex* ThreadLocalData::mutex_ = NULL;
600 MallocGrowableArray<ThreadLocalEntry>* ThreadLocalData::thread_locals_ = NULL; 560 MallocGrowableArray<ThreadLocalEntry>* ThreadLocalData::thread_locals_ = NULL;
601 561
602
603 void ThreadLocalData::InitOnce() { 562 void ThreadLocalData::InitOnce() {
604 mutex_ = new Mutex(); 563 mutex_ = new Mutex();
605 thread_locals_ = new MallocGrowableArray<ThreadLocalEntry>(); 564 thread_locals_ = new MallocGrowableArray<ThreadLocalEntry>();
606 } 565 }
607 566
608
609 void ThreadLocalData::Shutdown() { 567 void ThreadLocalData::Shutdown() {
610 if (mutex_ != NULL) { 568 if (mutex_ != NULL) {
611 delete mutex_; 569 delete mutex_;
612 mutex_ = NULL; 570 mutex_ = NULL;
613 } 571 }
614 if (thread_locals_ != NULL) { 572 if (thread_locals_ != NULL) {
615 delete thread_locals_; 573 delete thread_locals_;
616 thread_locals_ = NULL; 574 thread_locals_ = NULL;
617 } 575 }
618 } 576 }
619 577
620
621 } // namespace dart 578 } // namespace dart
622 579
623 // The following was adapted from Chromium: 580 // The following was adapted from Chromium:
624 // src/base/threading/thread_local_storage_win.cc 581 // src/base/threading/thread_local_storage_win.cc
625 582
626 // Thread Termination Callbacks. 583 // Thread Termination Callbacks.
627 // Windows doesn't support a per-thread destructor with its 584 // Windows doesn't support a per-thread destructor with its
628 // TLS primitives. So, we build it manually by inserting a 585 // TLS primitives. So, we build it manually by inserting a
629 // function to be called on each thread's exit. 586 // function to be called on each thread's exit.
630 // This magic is from http://www.codeproject.com/threads/tls.asp 587 // This magic is from http://www.codeproject.com/threads/tls.asp
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 #pragma data_seg(".CRT$XLB") 651 #pragma data_seg(".CRT$XLB")
695 PIMAGE_TLS_CALLBACK p_thread_callback_dart = OnDartThreadExit; 652 PIMAGE_TLS_CALLBACK p_thread_callback_dart = OnDartThreadExit;
696 653
697 // Reset the default section. 654 // Reset the default section.
698 #pragma data_seg() 655 #pragma data_seg()
699 656
700 #endif // _WIN64 657 #endif // _WIN64
701 } // extern "C" 658 } // extern "C"
702 659
703 #endif // defined(HOST_OS_WINDOWS) 660 #endif // defined(HOST_OS_WINDOWS)
OLDNEW
« no previous file with comments | « runtime/vm/os_thread_win.h ('k') | runtime/vm/os_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698