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, &param);
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