[WTF] Drop Thread::create(obsolete things) API since we can use lambda
[WebKit-https.git] / Source / WTF / wtf / ThreadingWin.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2015 Apple Inc. All rights reserved.
3  * Copyright (C) 2009 Google Inc. All rights reserved.
4  * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer. 
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution. 
15  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission. 
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /*
32  * There are numerous academic and practical works on how to implement pthread_cond_wait/pthread_cond_signal/pthread_cond_broadcast
33  * functions on Win32. Here is one example: http://www.cs.wustl.edu/~schmidt/win32-cv-1.html which is widely credited as a 'starting point'
34  * of modern attempts. There are several more or less proven implementations, one in Boost C++ library (http://www.boost.org) and another
35  * in pthreads-win32 (http://sourceware.org/pthreads-win32/).
36  *
37  * The number of articles and discussions is the evidence of significant difficulties in implementing these primitives correctly.
38  * The brief search of revisions, ChangeLog entries, discussions in comp.programming.threads and other places clearly documents
39  * numerous pitfalls and performance problems the authors had to overcome to arrive to the suitable implementations.
40  * Optimally, WebKit would use one of those supported/tested libraries directly. To roll out our own implementation is impractical,
41  * if even for the lack of sufficient testing. However, a faithful reproduction of the code from one of the popular supported
42  * libraries seems to be a good compromise.
43  *
44  * The early Boost implementation (http://www.boxbackup.org/trac/browser/box/nick/win/lib/win32/boost_1_32_0/libs/thread/src/condition.cpp?rev=30)
45  * is identical to pthreads-win32 (http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32).
46  * Current Boost uses yet another (although seemingly equivalent) algorithm which came from their 'thread rewrite' effort.
47  *
48  * This file includes timedWait/signal/broadcast implementations translated to WebKit coding style from the latest algorithm by
49  * Alexander Terekhov and Louis Thomas, as captured here: http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32
50  * It replaces the implementation of their previous algorithm, also documented in the same source above.
51  * The naming and comments are left very close to original to enable easy cross-check.
52  *
53  * The corresponding Pthreads-win32 License is included below, and CONTRIBUTORS file which it refers to is added to
54  * source directory (as CONTRIBUTORS.pthreads-win32).
55  */
56
57 /*
58  *      Pthreads-win32 - POSIX Threads Library for Win32
59  *      Copyright(C) 1998 John E. Bossom
60  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
61  *
62  *      Contact Email: rpj@callisto.canberra.edu.au
63  *
64  *      The current list of contributors is contained
65  *      in the file CONTRIBUTORS included with the source
66  *      code distribution. The list can also be seen at the
67  *      following World Wide Web location:
68  *      http://sources.redhat.com/pthreads-win32/contributors.html
69  *
70  *      This library is free software; you can redistribute it and/or
71  *      modify it under the terms of the GNU Lesser General Public
72  *      License as published by the Free Software Foundation; either
73  *      version 2 of the License, or (at your option) any later version.
74  *
75  *      This library is distributed in the hope that it will be useful,
76  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
77  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
78  *      Lesser General Public License for more details.
79  *
80  *      You should have received a copy of the GNU Lesser General Public
81  *      License along with this library in the file COPYING.LIB;
82  *      if not, write to the Free Software Foundation, Inc.,
83  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
84  */
85
86 #include "config.h"
87 #include "Threading.h"
88
89 #if OS(WINDOWS)
90
91 #include <process.h>
92 #include <windows.h>
93 #include <wtf/CurrentTime.h>
94 #include <wtf/MainThread.h>
95 #include <wtf/MathExtras.h>
96 #include <wtf/NeverDestroyed.h>
97 #include <wtf/ThreadFunctionInvocation.h>
98 #include <wtf/ThreadHolder.h>
99 #include <wtf/ThreadingPrimitives.h>
100
101 #if HAVE(ERRNO_H)
102 #include <errno.h>
103 #endif
104
105 namespace WTF {
106
107 Thread::Thread()
108 {
109 }
110
111 Thread::~Thread()
112 {
113     // It is OK because FLSAlloc's callback will be called even before there are some open handles.
114     // This easily ensures that all the thread resources are automatically closed.
115     if (m_handle != INVALID_HANDLE_VALUE)
116         CloseHandle(m_handle);
117 }
118
119 // MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadNameInternal all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
120 static const DWORD MS_VC_EXCEPTION = 0x406D1388;
121
122 #pragma pack(push, 8)
123 typedef struct tagTHREADNAME_INFO {
124     DWORD dwType; // must be 0x1000
125     LPCSTR szName; // pointer to name (in user addr space)
126     DWORD dwThreadID; // thread ID (-1=caller thread)
127     DWORD dwFlags; // reserved for future use, must be zero
128 } THREADNAME_INFO;
129 #pragma pack(pop)
130
131 void Thread::initializeCurrentThreadInternal(const char* szThreadName)
132 {
133 #if COMPILER(MINGW)
134     // FIXME: Implement thread name setting with MingW.
135     UNUSED_PARAM(szThreadName);
136 #else
137     THREADNAME_INFO info;
138     info.dwType = 0x1000;
139     info.szName = Thread::normalizeThreadName(szThreadName);
140     info.dwThreadID = GetCurrentThreadId();
141     info.dwFlags = 0;
142
143     __try {
144         RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
145     } __except (EXCEPTION_CONTINUE_EXECUTION) {
146     }
147 #endif
148 }
149
150 void Thread::initializePlatformThreading()
151 {
152 }
153
154 static unsigned __stdcall wtfThreadEntryPoint(void* param)
155 {
156     // Balanced by .leakPtr() in Thread::createInternal.
157     auto invocation = std::unique_ptr<ThreadFunctionInvocation>(static_cast<ThreadFunctionInvocation*>(param));
158
159     ThreadHolder::initialize(*invocation->thread, Thread::currentID());
160     invocation->thread = nullptr;
161
162     invocation->function(invocation->data);
163     return 0;
164 }
165
166 RefPtr<Thread> Thread::createInternal(ThreadFunction entryPoint, void* data, const char* threadName)
167 {
168     Ref<Thread> thread = adoptRef(*new Thread());
169     unsigned threadIdentifier = 0;
170     ThreadIdentifier threadID = 0;
171     auto invocation = std::make_unique<ThreadFunctionInvocation>(entryPoint, thread.ptr(), data);
172     HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation.get(), 0, &threadIdentifier));
173     if (!threadHandle) {
174 #if !HAVE(ERRNO_H)
175         LOG_ERROR("Failed to create thread at entry point %p with data %p.", entryPoint, data);
176 #else
177         LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno);
178 #endif
179         return 0;
180     }
181
182     // The thread will take ownership of invocation.
183     ThreadFunctionInvocation* leakedInvocation = invocation.release();
184     UNUSED_PARAM(leakedInvocation);
185
186     threadID = static_cast<ThreadIdentifier>(threadIdentifier);
187
188     thread->establish(threadHandle, threadIdentifier);
189     return thread;
190 }
191
192 void Thread::changePriority(int delta)
193 {
194     std::unique_lock<std::mutex> locker(m_mutex);
195     SetThreadPriority(m_handle, THREAD_PRIORITY_NORMAL + delta);
196 }
197
198 int Thread::waitForCompletion()
199 {
200     HANDLE handle;
201     {
202         std::unique_lock<std::mutex> locker(m_mutex);
203         handle = m_handle;
204     }
205
206     DWORD joinResult = WaitForSingleObject(handle, INFINITE);
207     if (joinResult == WAIT_FAILED)
208         LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", m_id);
209
210     std::unique_lock<std::mutex> locker(m_mutex);
211     ASSERT(joinableState() == Joinable);
212
213     // The thread has already exited, do nothing.
214     // The thread hasn't exited yet, so don't clean anything up. Just signal that we've already joined on it so that it will clean up after itself.
215     if (!hasExited())
216         didJoin();
217
218     return joinResult;
219 }
220
221 void Thread::detach()
222 {
223     // We follow the pthread semantics: even after the detach is called,
224     // we can still perform various operations onto the thread. For example,
225     // we can do pthread_kill for the detached thread. The problem in Windows
226     // is that closing HANDLE loses the way to do such operations.
227     // To do so, we do nothing here in Windows. Original detach's purpose,
228     // releasing thread resource when the thread exits, will be achieved by
229     // FlsCallback automatically. FlsCallback will call CloseHandle to clean up
230     // resource. So in this function, we just mark the thread as detached to
231     // avoid calling waitForCompletion for this thread.
232     std::unique_lock<std::mutex> locker(m_mutex);
233     if (!hasExited())
234         didBecomeDetached();
235 }
236
237 auto Thread::suspend() -> Expected<void, PlatformSuspendError>
238 {
239     RELEASE_ASSERT_WITH_MESSAGE(id() != currentThread(), "We do not support suspending the current thread itself.");
240     std::unique_lock<std::mutex> locker(m_mutex);
241     DWORD result = SuspendThread(m_handle);
242     if (result != (DWORD)-1)
243         return { };
244     return makeUnexpected(result);
245 }
246
247 // During resume, suspend or resume should not be executed from the other threads.
248 void Thread::resume()
249 {
250     std::unique_lock<std::mutex> locker(m_mutex);
251     ResumeThread(m_handle);
252 }
253
254 size_t Thread::getRegisters(PlatformRegisters& registers)
255 {
256     std::unique_lock<std::mutex> locker(m_mutex);
257     registers.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
258     GetThreadContext(m_handle, &registers);
259     return sizeof(CONTEXT);
260 }
261
262 Thread& Thread::current()
263 {
264     ThreadHolder* data = ThreadHolder::current();
265     if (data)
266         return data->thread();
267
268     // Not a WTF-created thread, ThreadIdentifier is not established yet.
269     Ref<Thread> thread = adoptRef(*new Thread());
270
271     HANDLE handle;
272     bool isSuccessful = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
273     RELEASE_ASSERT(isSuccessful);
274
275     thread->establish(handle, currentID());
276     ThreadHolder::initialize(thread.get(), Thread::currentID());
277     return thread.get();
278 }
279
280 ThreadIdentifier Thread::currentID()
281 {
282     return static_cast<ThreadIdentifier>(GetCurrentThreadId());
283 }
284
285 void Thread::establish(HANDLE handle, ThreadIdentifier threadID)
286 {
287     std::unique_lock<std::mutex> locker(m_mutex);
288     m_handle = handle;
289     m_id = threadID;
290 }
291
292 Mutex::Mutex()
293 {
294     m_mutex.m_recursionCount = 0;
295     InitializeCriticalSection(&m_mutex.m_internalMutex);
296 }
297
298 Mutex::~Mutex()
299 {
300     DeleteCriticalSection(&m_mutex.m_internalMutex);
301 }
302
303 void Mutex::lock()
304 {
305     EnterCriticalSection(&m_mutex.m_internalMutex);
306     ++m_mutex.m_recursionCount;
307 }
308     
309 #pragma warning(suppress: 26115)
310 bool Mutex::tryLock()
311 {
312     // This method is modeled after the behavior of pthread_mutex_trylock,
313     // which will return an error if the lock is already owned by the
314     // current thread.  Since the primitive Win32 'TryEnterCriticalSection'
315     // treats this as a successful case, it changes the behavior of several
316     // tests in WebKit that check to see if the current thread already
317     // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord)
318     DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex);
319     
320     if (result != 0) {       // We got the lock
321         // If this thread already had the lock, we must unlock and
322         // return false so that we mimic the behavior of POSIX's
323         // pthread_mutex_trylock:
324         if (m_mutex.m_recursionCount > 0) {
325             LeaveCriticalSection(&m_mutex.m_internalMutex);
326             return false;
327         }
328
329         ++m_mutex.m_recursionCount;
330         return true;
331     }
332
333     return false;
334 }
335
336 void Mutex::unlock()
337 {
338     ASSERT(m_mutex.m_recursionCount);
339     --m_mutex.m_recursionCount;
340     LeaveCriticalSection(&m_mutex.m_internalMutex);
341 }
342
343 bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMilliseconds)
344 {
345     // Enter the wait state.
346     DWORD res = WaitForSingleObject(m_blockLock, INFINITE);
347     ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
348     ++m_waitersBlocked;
349     res = ReleaseSemaphore(m_blockLock, 1, 0);
350     ASSERT_UNUSED(res, res);
351
352     --mutex.m_recursionCount;
353     LeaveCriticalSection(&mutex.m_internalMutex);
354
355     // Main wait - use timeout.
356     bool timedOut = (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT);
357
358     res = WaitForSingleObject(m_unblockLock, INFINITE);
359     ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
360
361     int signalsLeft = m_waitersToUnblock;
362
363     if (m_waitersToUnblock)
364         --m_waitersToUnblock;
365     else if (++m_waitersGone == (INT_MAX / 2)) { // timeout/canceled or spurious semaphore
366         // timeout or spurious wakeup occured, normalize the m_waitersGone count
367         // this may occur if many calls to wait with a timeout are made and
368         // no call to notify_* is made
369         res = WaitForSingleObject(m_blockLock, INFINITE);
370         ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
371         m_waitersBlocked -= m_waitersGone;
372         res = ReleaseSemaphore(m_blockLock, 1, 0);
373         ASSERT_UNUSED(res, res);
374         m_waitersGone = 0;
375     }
376
377     res = ReleaseMutex(m_unblockLock);
378     ASSERT_UNUSED(res, res);
379
380     if (signalsLeft == 1) {
381         res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate.
382         ASSERT_UNUSED(res, res);
383     }
384
385     EnterCriticalSection (&mutex.m_internalMutex);
386     ++mutex.m_recursionCount;
387
388     return !timedOut;
389 }
390
391 void PlatformCondition::signal(bool unblockAll)
392 {
393     unsigned signalsToIssue = 0;
394
395     DWORD res = WaitForSingleObject(m_unblockLock, INFINITE);
396     ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
397
398     if (m_waitersToUnblock) { // the gate is already closed
399         if (!m_waitersBlocked) { // no-op
400             res = ReleaseMutex(m_unblockLock);
401             ASSERT_UNUSED(res, res);
402             return;
403         }
404
405         if (unblockAll) {
406             signalsToIssue = m_waitersBlocked;
407             m_waitersToUnblock += m_waitersBlocked;
408             m_waitersBlocked = 0;
409         } else {
410             signalsToIssue = 1;
411             ++m_waitersToUnblock;
412             --m_waitersBlocked;
413         }
414     } else if (m_waitersBlocked > m_waitersGone) {
415         res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate.
416         ASSERT_UNUSED(res, res == WAIT_OBJECT_0);
417         if (m_waitersGone != 0) {
418             m_waitersBlocked -= m_waitersGone;
419             m_waitersGone = 0;
420         }
421         if (unblockAll) {
422             signalsToIssue = m_waitersBlocked;
423             m_waitersToUnblock = m_waitersBlocked;
424             m_waitersBlocked = 0;
425         } else {
426             signalsToIssue = 1;
427             m_waitersToUnblock = 1;
428             --m_waitersBlocked;
429         }
430     } else { // No-op.
431         res = ReleaseMutex(m_unblockLock);
432         ASSERT_UNUSED(res, res);
433         return;
434     }
435
436     res = ReleaseMutex(m_unblockLock);
437     ASSERT_UNUSED(res, res);
438
439     if (signalsToIssue) {
440         res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0);
441         ASSERT_UNUSED(res, res);
442     }
443 }
444
445 static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1);
446
447 ThreadCondition::ThreadCondition()
448 {
449     m_condition.m_waitersGone = 0;
450     m_condition.m_waitersBlocked = 0;
451     m_condition.m_waitersToUnblock = 0;
452     m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0);
453     m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0);
454     m_condition.m_unblockLock = CreateMutex(0, 0, 0);
455
456     if (!m_condition.m_blockLock || !m_condition.m_blockQueue || !m_condition.m_unblockLock) {
457         if (m_condition.m_blockLock)
458             CloseHandle(m_condition.m_blockLock);
459         if (m_condition.m_blockQueue)
460             CloseHandle(m_condition.m_blockQueue);
461         if (m_condition.m_unblockLock)
462             CloseHandle(m_condition.m_unblockLock);
463     }
464 }
465
466 ThreadCondition::~ThreadCondition()
467 {
468     CloseHandle(m_condition.m_blockLock);
469     CloseHandle(m_condition.m_blockQueue);
470     CloseHandle(m_condition.m_unblockLock);
471 }
472
473 void ThreadCondition::wait(Mutex& mutex)
474 {
475     m_condition.timedWait(mutex.impl(), INFINITE);
476 }
477
478 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
479 {
480     DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime);
481
482     if (!interval) {
483         // Consider the wait to have timed out, even if our condition has already been signaled, to
484         // match the pthreads implementation.
485         return false;
486     }
487
488     return m_condition.timedWait(mutex.impl(), interval);
489 }
490
491 void ThreadCondition::signal()
492 {
493     m_condition.signal(false); // Unblock only 1 thread.
494 }
495
496 void ThreadCondition::broadcast()
497 {
498     m_condition.signal(true); // Unblock all threads.
499 }
500
501 DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime)
502 {
503     double currentTime = WTF::currentTime();
504
505     // Time is in the past - return immediately.
506     if (absoluteTime < currentTime)
507         return 0;
508
509     // Time is too far in the future (and would overflow unsigned long) - wait forever.
510     if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0)
511         return INFINITE;
512
513     return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0);
514 }
515
516 // Remove this workaround code when <rdar://problem/31793213> is fixed.
517 ThreadIdentifier createThread(ThreadFunction function, void* data, const char* threadName)
518 {
519     return Thread::create(threadName, [function, data] {
520         function(data);
521     })->id();
522 }
523
524 int waitForThreadCompletion(ThreadIdentifier threadID)
525 {
526     // This function is implemented based on the old Threading implementation.
527     // It remains only due to the support library using old Threading APIs and
528     // it should not be used in new code.
529     ASSERT(threadID);
530
531     RefPtr<Thread> thread = ThreadHolder::get(threadID);
532     if (!thread) {
533         LOG_ERROR("ThreadIdentifier %u did not correspond to an active thread when trying to quit", threadID);
534         return WAIT_FAILED;
535     }
536     return thread->waitForCompletion();
537
538 }
539
540 } // namespace WTF
541
542 #endif // OS(WINDOWS)