1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* 2a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Use of this source code is governed by a BSD-style license 5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * that can be found in the LICENSE file in the root of the source 6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * tree. An additional intellectual property rights grant can be found 7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * in the file PATENTS. All contributing project authors may 8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * be found in the AUTHORS file in the root of the source tree. 9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 11a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// The state of a thread is controlled by the two member variables 12a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// _alive and _dead. 13a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// _alive represents the state the thread has been ordered to achieve. 14a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// It is set to true by the thread at startup, and is set to false by 15a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// other threads, using SetNotAlive() and Stop(). 16a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// _dead represents the state the thread has achieved. 17a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// It is written by the thread encapsulated by this class only 18a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// (except at init). It is read only by the Stop() method. 19a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// The Run() method fires _event when it's started; this ensures that the 20a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Start() method does not continue until after _dead is false. 21a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// This protects against premature Stop() calls from the creator thread, but 22a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// not from other threads. 23a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 24a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Their transitions and states: 25a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// _alive _dead Set by 26a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// false true Constructor 27a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// true false Run() method entry 28a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// false any Run() method runFunction failure 29a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// any false Run() method exit (happens only with _alive false) 30a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// false any SetNotAlive 31a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// false any Stop Stop waits for _dead to become true. 32a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// 33a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Summarized a different way: 34a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Variable Writer Reader 35a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// _alive Constructor(false) Run.loop 36a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Run.start(true) 37a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Run.fail(false) 38a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// SetNotAlive(false) 39a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Stop(false) 40a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// 41a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// _dead Constructor(true) Stop.loop 42a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Run.start(false) 43a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// Run.exit(true) 44a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 45c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "thread_posix.h" 46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <errno.h> 48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <string.h> // strncpy 49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <time.h> // nanosleep 50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <unistd.h> 51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef WEBRTC_LINUX 52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <sys/types.h> 53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <sched.h> 54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <sys/syscall.h> 55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <linux/unistd.h> 56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <sys/prctl.h> 57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 59a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#if defined(WEBRTC_MAC) 60a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <mach/mach.h> 61a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#endif 62a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 63a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "system_wrappers/interface/critical_section_wrapper.h" 64a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "system_wrappers/interface/event_wrapper.h" 65a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "system_wrappers/interface/trace.h" 66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace webrtc { 68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentextern "C" 69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 70e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent static void* StartThread(void* lpParameter) 71e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 72c55a96383497a772a307b346368133960b02ad03Eric Laurent static_cast<ThreadPosix*>(lpParameter)->Run(); 73e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 74e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 75e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 77c55a96383497a772a307b346368133960b02ad03Eric LaurentThreadWrapper* ThreadPosix::Create(ThreadRunFunction func, ThreadObj obj, 78e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent ThreadPriority prio, const char* threadName) 79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 80c55a96383497a772a307b346368133960b02ad03Eric Laurent ThreadPosix* ptr = new ThreadPosix(func, obj, prio, threadName); 81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!ptr) 82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return NULL; 84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const int error = ptr->Construct(); 86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (error) 87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent delete ptr; 89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return NULL; 90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return ptr; 92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 94c55a96383497a772a307b346368133960b02ad03Eric LaurentThreadPosix::ThreadPosix(ThreadRunFunction func, ThreadObj obj, 95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent ThreadPriority prio, const char* threadName) 96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent : _runFunction(func), 97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _obj(obj), 98a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _crit_state(CriticalSectionWrapper::CreateCriticalSection()), 99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _alive(false), 100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _dead(true), 101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _prio(prio), 102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _event(EventWrapper::Create()), 103a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _name(), 104a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _setThreadName(false), 105a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)) 106a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _pid(-1), 107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 108a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _attr(), 109a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _thread(0) 110a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{ 111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (threadName != NULL) 112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _setThreadName = true; 114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent strncpy(_name, threadName, kThreadMaxNameLength); 115a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _name[kThreadMaxNameLength - 1] = '\0'; 116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 119a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinuint32_t ThreadWrapper::GetThreadId() { 120a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#if defined(WEBRTC_ANDROID) || defined(WEBRTC_LINUX) 121a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return static_cast<uint32_t>(syscall(__NR_gettid)); 122a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#elif defined(WEBRTC_MAC) 123a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return static_cast<uint32_t>(mach_thread_self()); 124a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#else 125a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return reinterpret_cast<uint32_t>(pthread_self()); 126a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#endif 127a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} 128a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 129c55a96383497a772a307b346368133960b02ad03Eric Laurentint ThreadPosix::Construct() 130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int result = 0; 132c55a96383497a772a307b346368133960b02ad03Eric Laurent#if !defined(WEBRTC_ANDROID) 133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Enable immediate cancellation if requested, see Shutdown() 134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent result = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (result != 0) 136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (result != 0) 141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent result = pthread_attr_init(&_attr); 146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (result != 0) 147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 153c55a96383497a772a307b346368133960b02ad03Eric LaurentThreadPosix::~ThreadPosix() 154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent pthread_attr_destroy(&_attr); 156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent delete _event; 157a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin delete _crit_state; 158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#define HAS_THREAD_ID !defined(MAC_IPHONE) && !defined(MAC_IPHONE_SIM) && \ 161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent !defined(WEBRTC_MAC) && !defined(WEBRTC_MAC_INTEL) && \ 162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent !defined(MAC_DYLIB) && !defined(MAC_INTEL_DYLIB) 163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#if HAS_THREAD_ID 164c55a96383497a772a307b346368133960b02ad03Eric Laurentbool ThreadPosix::Start(unsigned int& threadID) 165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#else 166c55a96383497a772a307b346368133960b02ad03Eric Laurentbool ThreadPosix::Start(unsigned int& /*threadID*/) 167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!_runFunction) 170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int result = pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_DETACHED); 174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Set the stack stack size to 1M. 175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent result |= pthread_attr_setstacksize(&_attr, 1024*1024); 176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef WEBRTC_THREAD_RR 177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const int policy = SCHED_RR; 178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#else 179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const int policy = SCHED_FIFO; 180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 181e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _event->Reset(); 182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent result |= pthread_create(&_thread, &_attr, &StartThread, this); 183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (result != 0) 184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Wait up to 10 seconds for the OS to call the callback function. Prevents 189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // race condition if Stop() is called too quickly after start. 190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (kEventSignaled != _event->Wait(WEBRTC_EVENT_10_SEC)) 191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Timed out. Something went wrong. 193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _runFunction = NULL; 194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 196e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 197e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#if HAS_THREAD_ID 198e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent threadID = static_cast<unsigned int>(_thread); 199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 200e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent sched_param param; 201e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 202e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const int minPrio = sched_get_priority_min(policy); 203e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const int maxPrio = sched_get_priority_max(policy); 204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if ((minPrio == EINVAL) || (maxPrio == EINVAL)) 205e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 206e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 209e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent switch (_prio) 210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 211e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case kLowPriority: 212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent param.sched_priority = minPrio + 1; 213e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent break; 214e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case kNormalPriority: 215e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent param.sched_priority = (minPrio + maxPrio) / 2; 216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent break; 217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case kHighPriority: 218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent param.sched_priority = maxPrio - 3; 219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent break; 220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case kHighestPriority: 221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent param.sched_priority = maxPrio - 2; 222e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent break; 223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case kRealtimePriority: 224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent param.sched_priority = maxPrio - 1; 225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent break; 226e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 227e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent result = pthread_setschedparam(_thread, policy, ¶m); 228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (result == EINVAL) 229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 231e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 232e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return true; 233e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 234e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 235a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// CPU_ZERO and CPU_SET are not available in NDK r7, so disable 236a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin// SetAffinity on Android for now. 237a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#if (defined(WEBRTC_LINUX) && (!defined(WEBRTC_ANDROID))) 238c55a96383497a772a307b346368133960b02ad03Eric Laurentbool ThreadPosix::SetAffinity(const int* processorNumbers, 239a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const unsigned int amountOfProcessors) { 240a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (!processorNumbers || (amountOfProcessors == 0)) { 241a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return false; 242a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 243a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin cpu_set_t mask; 244a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CPU_ZERO(&mask); 245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 246a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin for (unsigned int processor = 0; 247a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin processor < amountOfProcessors; 248a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin processor++) { 249a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CPU_SET(processorNumbers[processor], &mask); 250a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 251a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#if defined(WEBRTC_ANDROID) 252a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // Android. 253a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const int result = syscall(__NR_sched_setaffinity, 254a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _pid, 255a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin sizeof(mask), 256a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin &mask); 257a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#else 258a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin // "Normal" Linux. 259a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin const int result = sched_setaffinity(_pid, 260a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin sizeof(mask), 261a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin &mask); 262a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#endif 263a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (result != 0) { 264a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return false; 265a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 266a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin return true; 267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 268a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin 269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#else 270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// NOTE: On Mac OS X, use the Thread affinity API in 271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// /usr/include/mach/thread_policy.h: thread_policy_set and mach_thread_self() 272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// instead of Linux gettid() syscall. 273c55a96383497a772a307b346368133960b02ad03Eric Laurentbool ThreadPosix::SetAffinity(const int* , const unsigned int) 274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 276e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 278e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 279c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid ThreadPosix::SetNotAlive() 280e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 281a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CriticalSectionScoped cs(_crit_state); 282e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _alive = false; 283e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 284e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 285c55a96383497a772a307b346368133960b02ad03Eric Laurentbool ThreadPosix::Shutdown() 286e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 287c55a96383497a772a307b346368133960b02ad03Eric Laurent#if !defined(WEBRTC_ANDROID) 288e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (_thread && (0 != pthread_cancel(_thread))) 289e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 290e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 291e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 292e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 293e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return true; 294e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#else 295e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 296e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 297e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 298e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 299c55a96383497a772a307b346368133960b02ad03Eric Laurentbool ThreadPosix::Stop() 300e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 301a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin bool dead = false; 302a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 303a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CriticalSectionScoped cs(_crit_state); 304a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = false; 305a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin dead = _dead; 306a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 307e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 308e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // TODO (hellner) why not use an event here? 309e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Wait up to 10 seconds for the thread to terminate 310a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin for (int i = 0; i < 1000 && !dead; i++) 311e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 312e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent timespec t; 313e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent t.tv_sec = 0; 314e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent t.tv_nsec = 10*1000*1000; 315e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent nanosleep(&t, NULL); 316a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 317a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CriticalSectionScoped cs(_crit_state); 318a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin dead = _dead; 319a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 320e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 321a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (dead) 322e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 323e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return true; 324e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 325e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent else 326e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 327e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return false; 328e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 329e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 330e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 331c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid ThreadPosix::Run() 332e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 333e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 334a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CriticalSectionScoped cs(_crit_state); 335a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = true; 336a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _dead = false; 337e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 338a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)) 339a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _pid = GetThreadId(); 340e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif 341e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // The event the Start() is waiting for. 342e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent _event->Set(); 343e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 344e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (_setThreadName) 345e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 346e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#ifdef WEBRTC_LINUX 347e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent prctl(PR_SET_NAME, (unsigned long)_name, 0, 0, 0); 348a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#endif 349e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1, 350e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "Thread with name:%s started ", _name); 351a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } else 352e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 353e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, 354e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "Thread without name started"); 355e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 356a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin bool alive = true; 357e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent do 358e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 359e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (_runFunction) 360e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 361e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!_runFunction(_obj)) 362e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 363a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin alive = false; 364e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 365e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 366e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent else 367e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 368a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin alive = false; 369a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 370a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 371a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CriticalSectionScoped cs(_crit_state); 372a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin if (!alive) { 373a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _alive = false; 374a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 375a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin alive = _alive; 376e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 377e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 378a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin while (alive); 379e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 380e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (_setThreadName) 381e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Don't set the name for the trace thread because it may cause a 383e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // deadlock. TODO (hellner) there should be a better solution than 384e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // coupling the thread and the trace class like this. 385e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (strcmp(_name, "Trace")) 386e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 387e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1, 388e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "Thread with name:%s stopped", _name); 389e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 390e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 391e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent else 392e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 393e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1, 394e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent "Thread without name stopped"); 395e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 396a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin { 397a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin CriticalSectionScoped cs(_crit_state); 398a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin _dead = true; 399a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin } 400e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 401e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} // namespace webrtc 402