Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/platform_thread.h"
7 #include <errno.h>
8 #include <sched.h>
10 #if defined(OS_MACOSX)
11 #include <mach/mach.h>
12 #elif defined(OS_NETBSD)
13 #include <lwp.h>
14 #elif defined(OS_LINUX)
15 #include <sys/syscall.h>
16 #include <sys/prctl.h>
17 #elif defined(OS_FREEBSD) && !defined(__GLIBC__)
18 #include <sys/param.h>
19 #include <sys/thr.h>
20 #endif
22 #if !defined(OS_MACOSX)
23 #include <unistd.h>
24 #endif
26 #if defined(OS_BSD) && !defined(OS_NETBSD) && !defined(__GLIBC__)
27 #include <pthread_np.h>
28 #endif
30 #if defined(OS_MACOSX)
31 namespace base {
32 void InitThreading();
33 } // namespace
34 #endif
36 static void* ThreadFunc(void* closure) {
37 PlatformThread::Delegate* delegate =
38 static_cast<PlatformThread::Delegate*>(closure);
39 delegate->ThreadMain();
40 return NULL;
41 }
43 // static
44 PlatformThreadId PlatformThread::CurrentId() {
45 // Pthreads doesn't have the concept of a thread ID, so we have to reach down
46 // into the kernel.
47 #if defined(OS_MACOSX)
48 mach_port_t port = mach_thread_self();
49 mach_port_deallocate(mach_task_self(), port);
50 return port;
51 #elif defined(OS_LINUX)
52 #ifdef MOZ_WIDGET_GONK
53 return (intptr_t) (pthread_self());
54 #else
55 return syscall(__NR_gettid);
56 #endif
57 #elif defined(OS_OPENBSD) || defined(__GLIBC__)
58 return (intptr_t) (pthread_self());
59 #elif defined(OS_NETBSD)
60 return _lwp_self();
61 #elif defined(OS_DRAGONFLY)
62 return lwp_gettid();
63 #elif defined(OS_FREEBSD)
64 # if __FreeBSD_version > 900030
65 return pthread_getthreadid_np();
66 # else
67 long lwpid;
68 thr_self(&lwpid);
69 return lwpid;
70 # endif
71 #endif
72 }
74 // static
75 void PlatformThread::YieldCurrentThread() {
76 sched_yield();
77 }
79 // static
80 void PlatformThread::Sleep(int duration_ms) {
81 struct timespec sleep_time, remaining;
83 // Contains the portion of duration_ms >= 1 sec.
84 sleep_time.tv_sec = duration_ms / 1000;
85 duration_ms -= sleep_time.tv_sec * 1000;
87 // Contains the portion of duration_ms < 1 sec.
88 sleep_time.tv_nsec = duration_ms * 1000 * 1000; // nanoseconds.
90 while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
91 sleep_time = remaining;
92 }
94 #ifndef OS_MACOSX
95 // Mac is implemented in platform_thread_mac.mm.
97 // static
98 void PlatformThread::SetName(const char* name) {
99 // On linux we can get the thread names to show up in the debugger by setting
100 // the process name for the LWP. We don't want to do this for the main
101 // thread because that would rename the process, causing tools like killall
102 // to stop working.
103 if (PlatformThread::CurrentId() == getpid())
104 return;
106 // http://0pointer.de/blog/projects/name-your-threads.html
107 // Set the name for the LWP (which gets truncated to 15 characters).
108 // Note that glibc also has a 'pthread_setname_np' api, but it may not be
109 // available everywhere and it's only benefit over using prctl directly is
110 // that it can set the name of threads other than the current thread.
111 #if defined(OS_LINUX)
112 prctl(PR_SET_NAME, reinterpret_cast<uintptr_t>(name), 0, 0, 0);
113 #elif defined(OS_NETBSD)
114 pthread_setname_np(pthread_self(), "%s", (void *)name);
115 #elif defined(OS_BSD) && !defined(__GLIBC__)
116 pthread_set_name_np(pthread_self(), name);
117 #else
118 #endif
119 }
120 #endif // !OS_MACOSX
122 namespace {
124 bool CreateThread(size_t stack_size, bool joinable,
125 PlatformThread::Delegate* delegate,
126 PlatformThreadHandle* thread_handle) {
127 #if defined(OS_MACOSX)
128 base::InitThreading();
129 #endif // OS_MACOSX
131 bool success = false;
132 pthread_attr_t attributes;
133 pthread_attr_init(&attributes);
135 // Pthreads are joinable by default, so only specify the detached attribute if
136 // the thread should be non-joinable.
137 if (!joinable) {
138 pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
139 }
141 if (stack_size > 0)
142 pthread_attr_setstacksize(&attributes, stack_size);
144 success = !pthread_create(thread_handle, &attributes, ThreadFunc, delegate);
146 pthread_attr_destroy(&attributes);
147 return success;
148 }
150 } // anonymous namespace
152 // static
153 bool PlatformThread::Create(size_t stack_size, Delegate* delegate,
154 PlatformThreadHandle* thread_handle) {
155 return CreateThread(stack_size, true /* joinable thread */,
156 delegate, thread_handle);
157 }
159 // static
160 bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
161 PlatformThreadHandle unused;
163 bool result = CreateThread(stack_size, false /* non-joinable thread */,
164 delegate, &unused);
165 return result;
166 }
168 // static
169 void PlatformThread::Join(PlatformThreadHandle thread_handle) {
170 pthread_join(thread_handle, NULL);
171 }