| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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) |
| OLD | NEW |