1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/threading/platform_thread.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <errno.h>
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <sched.h>
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/lazy_instance.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/safe_strerror_posix.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/threading/thread_id_name_manager.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/tracked_objects.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if !defined(OS_NACL)
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <sys/resource.h>
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <sys/syscall.h>
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <sys/time.h>
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <sys/types.h>
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <unistd.h>
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace base {
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int ThreadNiceValue(ThreadPriority priority) {
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (priority) {
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case kThreadPriority_RealtimeAudio:
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return -10;
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case kThreadPriority_Background:
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return 10;
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case kThreadPriority_Normal:
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return 0;
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case kThreadPriority_Display:
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return -6;
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    default:
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NOTREACHED() << "Unknown priority.";
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return 0;
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PlatformThread::SetName(const char* name) {
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name);
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  tracked_objects::ThreadData::InitializeThreadContext(name);
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if !defined(OS_NACL)
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // On FreeBSD we can get the thread names to show up in the debugger by
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // setting the process name for the LWP.  We don't want to do this for the
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // main thread because that would rename the process, causing tools like
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // killall to stop working.
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (PlatformThread::CurrentId() == getpid())
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  setproctitle("%s", name);
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  //  !defined(OS_NACL)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PlatformThread::SetThreadPriority(PlatformThreadHandle handle,
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       ThreadPriority priority) {
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if !defined(OS_NACL)
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (priority == kThreadPriority_RealtimeAudio) {
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const struct sched_param kRealTimePrio = { 8 };
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0) {
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // Got real time priority, no need to set nice level.
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return;
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // setpriority(2) will set a thread's priority if it is passed a tid as
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // the 'process identifier', not affecting the rest of the threads in the
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // process. Setting this priority will only succeed if the user has been
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // granted permission to adjust nice values on the system.
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_NE(handle.id_, kInvalidThreadId);
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const int kNiceSetting = ThreadNiceValue(priority);
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (setpriority(PRIO_PROCESS, handle.id_, kNiceSetting)) {
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DVPLOG(1) << "Failed to set nice value of thread ("
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              << handle.id_ << ") to " << kNiceSetting;
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif  //  !defined(OS_NACL)
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void InitThreading() {}
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void InitOnThread() {}
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TerminateOnThread() {}
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if !defined(THREAD_SANITIZER)
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return 0;
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#else
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // ThreadSanitizer bloats the stack heavily. Evidence has been that the
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // default stack size isn't enough for some browser tests.
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return 2 * (1 << 23);  // 2 times 8192K (the default stack size on Linux).
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace base
104