1a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin/* 2a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * 4a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * Use of this source code is governed by a BSD-style license 5a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * that can be found in the LICENSE file in the root of the source 6a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * tree. An additional intellectual property rights grant can be found 7a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * in the file PATENTS. All contributing project authors may 8a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * be found in the AUTHORS file in the root of the source tree. 9a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin */ 10a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 11a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "thread_win.h" 12a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 13a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <assert.h> 14a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <process.h> 15a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <stdio.h> 16a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <windows.h> 17a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 18a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "set_thread_name_win.h" 19a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "trace.h" 20a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 21a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinnamespace webrtc { 22a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinThreadWindows::ThreadWindows(ThreadRunFunction func, ThreadObj obj, 23a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin ThreadPriority prio, const char* threadName) 24a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin : ThreadWrapper(), 25a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _runFunction(func), 26a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _obj(obj), 27a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive(false), 28a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _dead(true), 29a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _doNotCloseHandle(false), 30a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _prio(prio), 31a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _event(NULL), 32a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _thread(NULL), 33a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _id(0), 34a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _name(), 35a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _setThreadName(false) 36a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 37a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _event = EventWrapper::Create(); 38a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _critsectStop = CriticalSectionWrapper::CreateCriticalSection(); 39a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (threadName != NULL) 40a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 41a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Set the thread name to appear in the VS debugger. 42a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _setThreadName = true; 43a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin strncpy(_name, threadName, kThreadMaxNameLength); 44a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 45a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 46a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 47a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinThreadWindows::~ThreadWindows() 48a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 49a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#ifdef _DEBUG 50a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin assert(!_alive); 51a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#endif 52a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_thread) 53a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 54a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CloseHandle(_thread); 55a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 56a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if(_event) 57a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 58a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin delete _event; 59a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 60a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if(_critsectStop) 61a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 62a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin delete _critsectStop; 63a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 64a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 65a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 66a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinuint32_t ThreadWrapper::GetThreadId() { 67a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return GetCurrentThreadId(); 68a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 69a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 70a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinunsigned int WINAPI ThreadWindows::StartThread(LPVOID lpParameter) 71a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 72a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin static_cast<ThreadWindows*>(lpParameter)->Run(); 73a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return 0; 74a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 75a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 76a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ThreadWindows::Start(unsigned int& threadID) 77a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 78a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _doNotCloseHandle = false; 79a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 80a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Set stack size to 1M 81a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _thread=(HANDLE)_beginthreadex(NULL, 1024*1024, StartThread, (void*)this, 0, 82a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin &threadID); 83a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if(_thread == NULL) 84a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 85a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return false; 86a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 87a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _id = threadID; 88a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _event->Wait(INFINITE); 89a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 90a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin switch(_prio) 91a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 92a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin case kLowPriority: 93a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SetThreadPriority(_thread, THREAD_PRIORITY_BELOW_NORMAL); 94a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin break; 95a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin case kNormalPriority: 96a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SetThreadPriority(_thread, THREAD_PRIORITY_NORMAL); 97a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin break; 98a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin case kHighPriority: 99a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SetThreadPriority(_thread, THREAD_PRIORITY_ABOVE_NORMAL); 100a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin break; 101a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin case kHighestPriority: 102a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SetThreadPriority(_thread, THREAD_PRIORITY_HIGHEST); 103a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin break; 104a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin case kRealtimePriority: 105a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SetThreadPriority(_thread, THREAD_PRIORITY_TIME_CRITICAL); 106a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin break; 107a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin }; 108a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return true; 109a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 110a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 111a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ThreadWindows::SetAffinity(const int* processorNumbers, 112a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const unsigned int amountOfProcessors) 113a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 114a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin DWORD_PTR processorBitMask = 0; 115a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin for(unsigned int processorIndex = 0; 116a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin processorIndex < amountOfProcessors; 117a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin processorIndex++) 118a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 119a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Convert from an array with processor numbers to a bitmask 120a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Processor numbers start at zero. 121a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // TODO (hellner): this looks like a bug. Shouldn't the '=' be a '+='? 122a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Or even better |= 123a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin processorBitMask = 1 << processorNumbers[processorIndex]; 124a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 125a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return SetThreadAffinityMask(_thread,processorBitMask) != 0; 126a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 127a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 128a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid ThreadWindows::SetNotAlive() 129a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 130a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = false; 131a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 132a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 133a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ThreadWindows::Shutdown() 134a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 135a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin DWORD exitCode = 0; 136a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin BOOL ret = TRUE; 137a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_thread) 138a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 139a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin ret = TerminateThread(_thread, exitCode); 140a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = false; 141a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _dead = true; 142a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _thread = NULL; 143a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 144a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return ret == TRUE; 145a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 146a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 147a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ThreadWindows::Stop() 148a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 149a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _critsectStop->Enter(); 150a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Prevents the handle from being closed in ThreadWindows::Run() 151a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _doNotCloseHandle = true; 152a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = false; 153a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin bool signaled = false; 154a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_thread && !_dead) 155a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 156a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _critsectStop->Leave(); 157a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Wait up to 2 seconds for the thread to complete. 158a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if( WAIT_OBJECT_0 == WaitForSingleObject(_thread, 2000)) 159a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 160a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin signaled = true; 161a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 162a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _critsectStop->Enter(); 163a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 164a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_thread) 165a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 166a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CloseHandle(_thread); 167a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _thread = NULL; 168a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 169a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _critsectStop->Leave(); 170a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 171a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_dead || signaled) 172a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 173a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return true; 174a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 175a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin else 176a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 177a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return false; 178a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 179a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 180a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 181a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid ThreadWindows::Run() 182a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 183a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = true; 184a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _dead = false; 185a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _event->Set(); 186a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 187a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // All tracing must be after _event->Set to avoid deadlock in Trace. 188a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_setThreadName) 189a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 190a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id, 191a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "Thread with name:%s started ", _name); 192a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin SetThreadName(-1, _name); // -1, set thread name for the calling thread. 193a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin }else 194a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 195a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id, 196a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "Thread without name started"); 197a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 198a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 199a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin do 200a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 201a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_runFunction) 202a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 203a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (!_runFunction(_obj)) 204a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 205a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = false; 206a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 207a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } else { 208a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = false; 209a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 210a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } while(_alive); 211a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 212a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_setThreadName) 213a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 214a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id, 215a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "Thread with name:%s stopped", _name); 216a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } else { 217a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,_id, 218a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin "Thread without name stopped"); 219a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 220a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 221a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _critsectStop->Enter(); 222a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 223a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (_thread && !_doNotCloseHandle) 224a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 225a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin HANDLE thread = _thread; 226a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _thread = NULL; 227a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CloseHandle(thread); 228a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 229a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _dead = true; 230a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 231a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _critsectStop->Leave(); 232a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}; 233a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} // namespace webrtc 234