blob: 82abc0e8be9c620c2ee908f54d93dacbeb75bb38 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000011#include "webrtc/system_wrappers/source/thread_win.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
niklase@google.com470e71d2011-07-07 08:21:25 +000013#include <process.h>
14#include <stdio.h>
15#include <windows.h>
16
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000017#include "webrtc/base/checks.h"
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000018#include "webrtc/system_wrappers/interface/trace.h"
19#include "webrtc/system_wrappers/source/set_thread_name_win.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000020
niklase@google.com470e71d2011-07-07 08:21:25 +000021namespace webrtc {
tommi@webrtc.org9d94a0c2015-02-11 14:16:08 +000022namespace {
23void CALLBACK RaiseFlag(ULONG_PTR param) {
24 *reinterpret_cast<bool*>(param) = true;
25}
26}
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000027
niklase@google.com470e71d2011-07-07 08:21:25 +000028ThreadWindows::ThreadWindows(ThreadRunFunction func, ThreadObj obj,
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000029 ThreadPriority prio, const char* thread_name)
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000030 : run_function_(func),
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000031 obj_(obj),
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000032 prio_(prio),
tommi@webrtc.org9d94a0c2015-02-11 14:16:08 +000033 stop_(false),
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000034 thread_(NULL),
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000035 name_(thread_name ? thread_name : "webrtc") {
36 DCHECK(func);
niklase@google.com470e71d2011-07-07 08:21:25 +000037}
38
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000039ThreadWindows::~ThreadWindows() {
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000040 DCHECK(main_thread_.CalledOnValidThread());
41 DCHECK(!thread_);
niklase@google.com470e71d2011-07-07 08:21:25 +000042}
43
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000044// static
pwestin@webrtc.orgb54d7272012-01-11 08:28:04 +000045uint32_t ThreadWrapper::GetThreadId() {
46 return GetCurrentThreadId();
47}
48
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000049// static
50DWORD WINAPI ThreadWindows::StartThread(void* param) {
51 static_cast<ThreadWindows*>(param)->Run();
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000052 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000053}
54
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000055bool ThreadWindows::Start(unsigned int& id) {
56 DCHECK(main_thread_.CalledOnValidThread());
57 DCHECK(!thread_);
58
tommi@webrtc.org9d94a0c2015-02-11 14:16:08 +000059 stop_ = false;
60
61 // See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION.
62 // Set the reserved stack stack size to 1M, which is the default on Windows
63 // and Linux.
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000064 DWORD thread_id;
tommi@webrtc.org9d94a0c2015-02-11 14:16:08 +000065 thread_ = ::CreateThread(NULL, 1024 * 1024, &StartThread, this,
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000066 STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id);
67 if (!thread_ ) {
68 DCHECK(false) << "CreateThread failed";
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000069 return false;
70 }
niklase@google.com470e71d2011-07-07 08:21:25 +000071
tommi@webrtc.orgaef07792015-01-30 15:06:10 +000072 id = thread_id;
73
74 if (prio_ != kNormalPriority) {
75 int priority = THREAD_PRIORITY_NORMAL;
76 switch (prio_) {
77 case kLowPriority:
78 priority = THREAD_PRIORITY_BELOW_NORMAL;
79 break;
80 case kHighPriority:
81 priority = THREAD_PRIORITY_ABOVE_NORMAL;
82 break;
83 case kHighestPriority:
84 priority = THREAD_PRIORITY_HIGHEST;
85 break;
86 case kRealtimePriority:
87 priority = THREAD_PRIORITY_TIME_CRITICAL;
88 break;
89 default:
90 break;
91 }
92
93 SetThreadPriority(thread_, priority);
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000094 }
niklase@google.com470e71d2011-07-07 08:21:25 +000095
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000096 return true;
97}
98
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +000099bool ThreadWindows::Stop() {
tommi@webrtc.orgaef07792015-01-30 15:06:10 +0000100 DCHECK(main_thread_.CalledOnValidThread());
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +0000101 if (thread_) {
tommi@webrtc.org9d94a0c2015-02-11 14:16:08 +0000102 // Set stop_ to |true| on the worker thread.
103 QueueUserAPC(&RaiseFlag, thread_, reinterpret_cast<ULONG_PTR>(&stop_));
tommi@webrtc.orgaef07792015-01-30 15:06:10 +0000104 WaitForSingleObject(thread_, INFINITE);
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +0000105 CloseHandle(thread_);
tommi@webrtc.orgaef07792015-01-30 15:06:10 +0000106 thread_ = nullptr;
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +0000107 }
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +0000108
tommi@webrtc.orgaef07792015-01-30 15:06:10 +0000109 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000110}
111
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +0000112void ThreadWindows::Run() {
tommi@webrtc.orgaef07792015-01-30 15:06:10 +0000113 if (!name_.empty())
114 SetThreadName(static_cast<DWORD>(-1), name_.c_str());
niklase@google.com470e71d2011-07-07 08:21:25 +0000115
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +0000116 do {
tommi@webrtc.org9d94a0c2015-02-11 14:16:08 +0000117 // The interface contract of Start/Stop is that for a successfull call to
118 // Start, there should be at least one call to the run function. So we
119 // call the function before checking |stop_|.
tommi@webrtc.orgaef07792015-01-30 15:06:10 +0000120 if (!run_function_(obj_))
121 break;
tommi@webrtc.org9d94a0c2015-02-11 14:16:08 +0000122 // Alertable sleep to permit RaiseFlag to run and update |stop_|.
123 SleepEx(0, true);
124 } while (!stop_);
tommi@webrtc.orgaef07792015-01-30 15:06:10 +0000125}
phoglund@webrtc.orgec9c9422013-01-02 08:45:03 +0000126
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000127} // namespace webrtc