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

Side by Side Diff: third_party/WebKit/Source/wtf/ThreadingWin.cpp

Issue 1611343002: wtf reformat test Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: pydent Created 4 years, 11 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * Copyright (C) 2009 Google Inc. All rights reserved.
4 * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. 4 * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 9 *
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 #include "wtf/dtoa/cached-powers.h" 101 #include "wtf/dtoa/cached-powers.h"
102 #include <errno.h> 102 #include <errno.h>
103 #include <process.h> 103 #include <process.h>
104 #include <windows.h> 104 #include <windows.h>
105 105
106 namespace WTF { 106 namespace WTF {
107 107
108 // THREADNAME_INFO comes from <http://msdn.microsoft.com/en-us/library/xcb2z8hs. aspx>. 108 // THREADNAME_INFO comes from <http://msdn.microsoft.com/en-us/library/xcb2z8hs. aspx>.
109 #pragma pack(push, 8) 109 #pragma pack(push, 8)
110 typedef struct tagTHREADNAME_INFO { 110 typedef struct tagTHREADNAME_INFO {
111 DWORD dwType; // must be 0x1000 111 DWORD dwType; // must be 0x1000
112 LPCSTR szName; // pointer to name (in user addr space) 112 LPCSTR szName; // pointer to name (in user addr space)
113 DWORD dwThreadID; // thread ID (-1=caller thread) 113 DWORD dwThreadID; // thread ID (-1=caller thread)
114 DWORD dwFlags; // reserved for future use, must be zero 114 DWORD dwFlags; // reserved for future use, must be zero
115 } THREADNAME_INFO; 115 } THREADNAME_INFO;
116 #pragma pack(pop) 116 #pragma pack(pop)
117 117
118 static Mutex* atomicallyInitializedStaticMutex; 118 static Mutex* atomicallyInitializedStaticMutex;
119 119
120 void lockAtomicallyInitializedStaticMutex() 120 void lockAtomicallyInitializedStaticMutex() {
121 { 121 ASSERT(atomicallyInitializedStaticMutex);
122 ASSERT(atomicallyInitializedStaticMutex); 122 atomicallyInitializedStaticMutex->lock();
123 atomicallyInitializedStaticMutex->lock(); 123 }
124 } 124
125 125 void unlockAtomicallyInitializedStaticMutex() {
126 void unlockAtomicallyInitializedStaticMutex() 126 atomicallyInitializedStaticMutex->unlock();
127 { 127 }
128 atomicallyInitializedStaticMutex->unlock(); 128
129 } 129 void initializeThreading() {
130 130 // This should only be called once.
131 void initializeThreading() 131 ASSERT(!atomicallyInitializedStaticMutex);
132 { 132
133 // This should only be called once. 133 // StringImpl::empty() does not construct its static string in a threadsafe fa shion,
134 ASSERT(!atomicallyInitializedStaticMutex); 134 // so ensure it has been initialized from here.
135 135 StringImpl::empty();
136 // StringImpl::empty() does not construct its static string in a threadsafe fashion, 136 StringImpl::empty16Bit();
137 // so ensure it has been initialized from here. 137 atomicallyInitializedStaticMutex = new Mutex;
138 StringImpl::empty(); 138 wtfThreadData();
139 StringImpl::empty16Bit(); 139 s_dtoaP5Mutex = new Mutex;
140 atomicallyInitializedStaticMutex = new Mutex; 140 initializeDates();
141 wtfThreadData(); 141 // Force initialization of static DoubleToStringConverter converter variable
142 s_dtoaP5Mutex = new Mutex; 142 // inside EcmaScriptConverter function while we are in single thread mode.
143 initializeDates(); 143 double_conversion::DoubleToStringConverter::EcmaScriptConverter();
144 // Force initialization of static DoubleToStringConverter converter variable 144 }
145 // inside EcmaScriptConverter function while we are in single thread mode. 145
146 double_conversion::DoubleToStringConverter::EcmaScriptConverter(); 146 ThreadIdentifier currentThread() {
147 } 147 return static_cast<ThreadIdentifier>(GetCurrentThreadId());
148 148 }
149 ThreadIdentifier currentThread() 149
150 { 150 MutexBase::MutexBase(bool recursive) {
151 return static_cast<ThreadIdentifier>(GetCurrentThreadId()); 151 m_mutex.m_recursionCount = 0;
152 } 152 InitializeCriticalSection(&m_mutex.m_internalMutex);
153 153 }
154 MutexBase::MutexBase(bool recursive) 154
155 { 155 MutexBase::~MutexBase() {
156 m_mutex.m_recursionCount = 0; 156 DeleteCriticalSection(&m_mutex.m_internalMutex);
157 InitializeCriticalSection(&m_mutex.m_internalMutex); 157 }
158 } 158
159 159 void MutexBase::lock() {
160 MutexBase::~MutexBase() 160 EnterCriticalSection(&m_mutex.m_internalMutex);
161 { 161 ++m_mutex.m_recursionCount;
162 DeleteCriticalSection(&m_mutex.m_internalMutex); 162 }
163 } 163
164 164 void MutexBase::unlock() {
165 void MutexBase::lock() 165 ASSERT(m_mutex.m_recursionCount);
166 { 166 --m_mutex.m_recursionCount;
167 EnterCriticalSection(&m_mutex.m_internalMutex); 167 LeaveCriticalSection(&m_mutex.m_internalMutex);
168 ++m_mutex.m_recursionCount; 168 }
169 } 169
170 170 bool Mutex::tryLock() {
171 void MutexBase::unlock() 171 // This method is modeled after the behavior of pthread_mutex_trylock,
172 { 172 // which will return an error if the lock is already owned by the
173 ASSERT(m_mutex.m_recursionCount); 173 // current thread. Since the primitive Win32 'TryEnterCriticalSection'
174 --m_mutex.m_recursionCount; 174 // treats this as a successful case, it changes the behavior of several
175 LeaveCriticalSection(&m_mutex.m_internalMutex); 175 // tests in WebKit that check to see if the current thread already
176 } 176 // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord)
177 177 DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex);
178 bool Mutex::tryLock() 178
179 { 179 if (result != 0) { // We got the lock
180 // This method is modeled after the behavior of pthread_mutex_trylock, 180 // If this thread already had the lock, we must unlock and return
181 // which will return an error if the lock is already owned by the 181 // false since this is a non-recursive mutex. This is to mimic the
182 // current thread. Since the primitive Win32 'TryEnterCriticalSection' 182 // behavior of POSIX's pthread_mutex_trylock. We don't do this
183 // treats this as a successful case, it changes the behavior of several 183 // check in the lock method (presumably due to performance?). This
184 // tests in WebKit that check to see if the current thread already 184 // means lock() will succeed even if the current thread has already
185 // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord) 185 // entered the critical section.
186 DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex); 186 if (m_mutex.m_recursionCount > 0) {
187 187 LeaveCriticalSection(&m_mutex.m_internalMutex);
188 if (result != 0) { // We got the lock 188 return false;
189 // If this thread already had the lock, we must unlock and return
190 // false since this is a non-recursive mutex. This is to mimic the
191 // behavior of POSIX's pthread_mutex_trylock. We don't do this
192 // check in the lock method (presumably due to performance?). This
193 // means lock() will succeed even if the current thread has already
194 // entered the critical section.
195 if (m_mutex.m_recursionCount > 0) {
196 LeaveCriticalSection(&m_mutex.m_internalMutex);
197 return false;
198 }
199 ++m_mutex.m_recursionCount;
200 return true;
201 }
202
203 return false;
204 }
205
206 bool RecursiveMutex::tryLock()
207 {
208 // CRITICAL_SECTION is recursive/reentrant so TryEnterCriticalSection will
209 // succeed if the current thread is already in the critical section.
210 DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex);
211 if (result == 0) { // We didn't get the lock.
212 return false;
213 } 189 }
214 ++m_mutex.m_recursionCount; 190 ++m_mutex.m_recursionCount;
215 return true; 191 return true;
216 } 192 }
217 193
218 bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon ds) 194 return false;
219 { 195 }
220 // Enter the wait state. 196
221 DWORD res = WaitForSingleObject(m_blockLock, INFINITE); 197 bool RecursiveMutex::tryLock() {
198 // CRITICAL_SECTION is recursive/reentrant so TryEnterCriticalSection will
199 // succeed if the current thread is already in the critical section.
200 DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex);
201 if (result == 0) { // We didn't get the lock.
202 return false;
203 }
204 ++m_mutex.m_recursionCount;
205 return true;
206 }
207
208 bool PlatformCondition::timedWait(PlatformMutex& mutex,
209 DWORD durationMilliseconds) {
210 // Enter the wait state.
211 DWORD res = WaitForSingleObject(m_blockLock, INFINITE);
212 ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
213 ++m_waitersBlocked;
214 res = ReleaseSemaphore(m_blockLock, 1, 0);
215 ASSERT_UNUSED(res, res);
216
217 --mutex.m_recursionCount;
218 LeaveCriticalSection(&mutex.m_internalMutex);
219
220 // Main wait - use timeout.
221 bool timedOut =
222 (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT);
223
224 res = WaitForSingleObject(m_unblockLock, INFINITE);
225 ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
226
227 int signalsLeft = m_waitersToUnblock;
228
229 if (m_waitersToUnblock) {
230 --m_waitersToUnblock;
231 } else if (++m_waitersGone == (INT_MAX / 2)) {
232 // timeout/canceled or spurious semaphore timeout or spurious wakeup
233 // occured, normalize the m_waitersGone count this may occur if many
234 // calls to wait with a timeout are made and no call to notify_* is made
235 res = WaitForSingleObject(m_blockLock, INFINITE);
222 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); 236 ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
223 ++m_waitersBlocked; 237 m_waitersBlocked -= m_waitersGone;
224 res = ReleaseSemaphore(m_blockLock, 1, 0); 238 res = ReleaseSemaphore(m_blockLock, 1, 0);
225 ASSERT_UNUSED(res, res); 239 ASSERT_UNUSED(res, res);
226 240 m_waitersGone = 0;
227 --mutex.m_recursionCount; 241 }
228 LeaveCriticalSection(&mutex.m_internalMutex); 242
229 243 res = ReleaseMutex(m_unblockLock);
230 // Main wait - use timeout. 244 ASSERT_UNUSED(res, res);
231 bool timedOut = (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT); 245
232 246 if (signalsLeft == 1) {
233 res = WaitForSingleObject(m_unblockLock, INFINITE); 247 res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate.
248 ASSERT_UNUSED(res, res);
249 }
250
251 EnterCriticalSection(&mutex.m_internalMutex);
252 ++mutex.m_recursionCount;
253
254 return !timedOut;
255 }
256
257 void PlatformCondition::signal(bool unblockAll) {
258 unsigned signalsToIssue = 0;
259
260 DWORD res = WaitForSingleObject(m_unblockLock, INFINITE);
261 ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
262
263 if (m_waitersToUnblock) { // the gate is already closed
264 if (!m_waitersBlocked) { // no-op
265 res = ReleaseMutex(m_unblockLock);
266 ASSERT_UNUSED(res, res);
267 return;
268 }
269
270 if (unblockAll) {
271 signalsToIssue = m_waitersBlocked;
272 m_waitersToUnblock += m_waitersBlocked;
273 m_waitersBlocked = 0;
274 } else {
275 signalsToIssue = 1;
276 ++m_waitersToUnblock;
277 --m_waitersBlocked;
278 }
279 } else if (m_waitersBlocked > m_waitersGone) {
280 res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate.
234 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); 281 ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
235 282 if (m_waitersGone != 0) {
236 int signalsLeft = m_waitersToUnblock; 283 m_waitersBlocked -= m_waitersGone;
237 284 m_waitersGone = 0;
238 if (m_waitersToUnblock) { 285 }
239 --m_waitersToUnblock; 286 if (unblockAll) {
240 } else if (++m_waitersGone == (INT_MAX / 2)) { 287 signalsToIssue = m_waitersBlocked;
241 // timeout/canceled or spurious semaphore timeout or spurious wakeup 288 m_waitersToUnblock = m_waitersBlocked;
242 // occured, normalize the m_waitersGone count this may occur if many 289 m_waitersBlocked = 0;
243 // calls to wait with a timeout are made and no call to notify_* is made 290 } else {
244 res = WaitForSingleObject(m_blockLock, INFINITE); 291 signalsToIssue = 1;
245 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); 292 m_waitersToUnblock = 1;
246 m_waitersBlocked -= m_waitersGone; 293 --m_waitersBlocked;
247 res = ReleaseSemaphore(m_blockLock, 1, 0); 294 }
248 ASSERT_UNUSED(res, res); 295 } else { // No-op.
249 m_waitersGone = 0;
250 }
251
252 res = ReleaseMutex(m_unblockLock); 296 res = ReleaseMutex(m_unblockLock);
253 ASSERT_UNUSED(res, res); 297 ASSERT_UNUSED(res, res);
254 298 return;
255 if (signalsLeft == 1) { 299 }
256 res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate. 300
257 ASSERT_UNUSED(res, res); 301 res = ReleaseMutex(m_unblockLock);
258 } 302 ASSERT_UNUSED(res, res);
259 303
260 EnterCriticalSection(&mutex.m_internalMutex); 304 if (signalsToIssue) {
261 ++mutex.m_recursionCount; 305 res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0);
262 306 ASSERT_UNUSED(res, res);
263 return !timedOut; 307 }
264 }
265
266 void PlatformCondition::signal(bool unblockAll)
267 {
268 unsigned signalsToIssue = 0;
269
270 DWORD res = WaitForSingleObject(m_unblockLock, INFINITE);
271 ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
272
273 if (m_waitersToUnblock) { // the gate is already closed
274 if (!m_waitersBlocked) { // no-op
275 res = ReleaseMutex(m_unblockLock);
276 ASSERT_UNUSED(res, res);
277 return;
278 }
279
280 if (unblockAll) {
281 signalsToIssue = m_waitersBlocked;
282 m_waitersToUnblock += m_waitersBlocked;
283 m_waitersBlocked = 0;
284 } else {
285 signalsToIssue = 1;
286 ++m_waitersToUnblock;
287 --m_waitersBlocked;
288 }
289 } else if (m_waitersBlocked > m_waitersGone) {
290 res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate.
291 ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
292 if (m_waitersGone != 0) {
293 m_waitersBlocked -= m_waitersGone;
294 m_waitersGone = 0;
295 }
296 if (unblockAll) {
297 signalsToIssue = m_waitersBlocked;
298 m_waitersToUnblock = m_waitersBlocked;
299 m_waitersBlocked = 0;
300 } else {
301 signalsToIssue = 1;
302 m_waitersToUnblock = 1;
303 --m_waitersBlocked;
304 }
305 } else { // No-op.
306 res = ReleaseMutex(m_unblockLock);
307 ASSERT_UNUSED(res, res);
308 return;
309 }
310
311 res = ReleaseMutex(m_unblockLock);
312 ASSERT_UNUSED(res, res);
313
314 if (signalsToIssue) {
315 res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0);
316 ASSERT_UNUSED(res, res);
317 }
318 } 308 }
319 309
320 static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); 310 static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1);
321 311
322 ThreadCondition::ThreadCondition() 312 ThreadCondition::ThreadCondition() {
323 { 313 m_condition.m_waitersGone = 0;
324 m_condition.m_waitersGone = 0; 314 m_condition.m_waitersBlocked = 0;
325 m_condition.m_waitersBlocked = 0; 315 m_condition.m_waitersToUnblock = 0;
326 m_condition.m_waitersToUnblock = 0; 316 m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0);
327 m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0); 317 m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0);
328 m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0); 318 m_condition.m_unblockLock = CreateMutex(0, 0, 0);
329 m_condition.m_unblockLock = CreateMutex(0, 0, 0); 319
330 320 if (!m_condition.m_blockLock || !m_condition.m_blockQueue ||
331 if (!m_condition.m_blockLock || !m_condition.m_blockQueue || !m_condition.m_ unblockLock) { 321 !m_condition.m_unblockLock) {
332 if (m_condition.m_blockLock) 322 if (m_condition.m_blockLock)
333 CloseHandle(m_condition.m_blockLock); 323 CloseHandle(m_condition.m_blockLock);
334 if (m_condition.m_blockQueue) 324 if (m_condition.m_blockQueue)
335 CloseHandle(m_condition.m_blockQueue); 325 CloseHandle(m_condition.m_blockQueue);
336 if (m_condition.m_unblockLock) 326 if (m_condition.m_unblockLock)
337 CloseHandle(m_condition.m_unblockLock); 327 CloseHandle(m_condition.m_unblockLock);
338 } 328 }
339 } 329 }
340 330
341 ThreadCondition::~ThreadCondition() 331 ThreadCondition::~ThreadCondition() {
342 { 332 CloseHandle(m_condition.m_blockLock);
343 CloseHandle(m_condition.m_blockLock); 333 CloseHandle(m_condition.m_blockQueue);
344 CloseHandle(m_condition.m_blockQueue); 334 CloseHandle(m_condition.m_unblockLock);
345 CloseHandle(m_condition.m_unblockLock); 335 }
346 } 336
347 337 void ThreadCondition::wait(MutexBase& mutex) {
348 void ThreadCondition::wait(MutexBase& mutex) 338 m_condition.timedWait(mutex.impl(), INFINITE);
349 { 339 }
350 m_condition.timedWait(mutex.impl(), INFINITE); 340
351 } 341 bool ThreadCondition::timedWait(MutexBase& mutex, double absoluteTime) {
352 342 DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime);
353 bool ThreadCondition::timedWait(MutexBase& mutex, double absoluteTime) 343
354 { 344 if (!interval) {
355 DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime); 345 // Consider the wait to have timed out, even if our condition has already be en signaled, to
356 346 // match the pthreads implementation.
357 if (!interval) { 347 return false;
358 // Consider the wait to have timed out, even if our condition has alread y been signaled, to 348 }
359 // match the pthreads implementation. 349
360 return false; 350 return m_condition.timedWait(mutex.impl(), interval);
361 } 351 }
362 352
363 return m_condition.timedWait(mutex.impl(), interval); 353 void ThreadCondition::signal() {
364 } 354 m_condition.signal(false); // Unblock only 1 thread.
365 355 }
366 void ThreadCondition::signal() 356
367 { 357 void ThreadCondition::broadcast() {
368 m_condition.signal(false); // Unblock only 1 thread. 358 m_condition.signal(true); // Unblock all threads.
369 } 359 }
370 360
371 void ThreadCondition::broadcast() 361 DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime) {
372 { 362 double currentTime = WTF::currentTime();
373 m_condition.signal(true); // Unblock all threads. 363
374 } 364 // Time is in the past - return immediately.
375 365 if (absoluteTime < currentTime)
376 DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime) 366 return 0;
377 { 367
378 double currentTime = WTF::currentTime(); 368 // Time is too far in the future (and would overflow unsigned long) - wait for ever.
379 369 if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0)
380 // Time is in the past - return immediately. 370 return INFINITE;
381 if (absoluteTime < currentTime) 371
382 return 0; 372 return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0);
383
384 // Time is too far in the future (and would overflow unsigned long) - wait f orever.
385 if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0)
386 return INFINITE;
387
388 return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0);
389 } 373 }
390 374
391 #if ENABLE(ASSERT) 375 #if ENABLE(ASSERT)
392 static bool s_threadCreated = false; 376 static bool s_threadCreated = false;
393 377
394 bool isAtomicallyInitializedStaticMutexLockHeld() 378 bool isAtomicallyInitializedStaticMutexLockHeld() {
395 { 379 return atomicallyInitializedStaticMutex &&
396 return atomicallyInitializedStaticMutex && atomicallyInitializedStaticMutex- >locked(); 380 atomicallyInitializedStaticMutex->locked();
397 } 381 }
398 382
399 bool isBeforeThreadCreated() 383 bool isBeforeThreadCreated() {
400 { 384 return !s_threadCreated;
401 return !s_threadCreated; 385 }
402 } 386
403 387 void willCreateThread() {
404 void willCreateThread() 388 s_threadCreated = true;
405 {
406 s_threadCreated = true;
407 } 389 }
408 #endif 390 #endif
409 391
410 } // namespace WTF 392 } // namespace WTF
411 393
412 #endif // OS(WIN) 394 #endif // OS(WIN)
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/ThreadingPthreads.cpp ('k') | third_party/WebKit/Source/wtf/TreeNode.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698