Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: base/threading/platform_thread_posix.cc

Issue 1150563002: base/threading: Lazy thread startup for pthreads (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase and review #15 Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/threading/platform_thread.h" 5 #include "base/threading/platform_thread.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <pthread.h> 8 #include <pthread.h>
9 #include <sched.h> 9 #include <sched.h>
10 #include <sys/resource.h> 10 #include <sys/resource.h>
11 #include <sys/time.h> 11 #include <sys/time.h>
12 12
13 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
16 #include "base/profiler/scoped_tracker.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/threading/platform_thread_internal_posix.h" 16 #include "base/threading/platform_thread_internal_posix.h"
19 #include "base/threading/thread_id_name_manager.h" 17 #include "base/threading/thread_id_name_manager.h"
20 #include "base/threading/thread_restrictions.h" 18 #include "base/threading/thread_restrictions.h"
21 #include "base/tracked_objects.h"
22 19
23 #if defined(OS_LINUX) 20 #if defined(OS_LINUX)
24 #include <sys/syscall.h> 21 #include <sys/syscall.h>
25 #elif defined(OS_ANDROID) 22 #elif defined(OS_ANDROID)
26 #include <sys/types.h> 23 #include <sys/types.h>
27 #endif 24 #endif
28 25
29 namespace base { 26 namespace base {
30 27
31 void InitThreading(); 28 void InitThreading();
32 void InitOnThread(); 29 void InitOnThread();
33 void TerminateOnThread(); 30 void TerminateOnThread();
34 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes); 31 size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes);
35 32
36 namespace { 33 namespace {
37 34
38 struct ThreadParams { 35 struct ThreadParams {
39 ThreadParams() 36 ThreadParams()
40 : delegate(NULL), 37 : delegate(NULL), joinable(false), priority(ThreadPriority::NORMAL) {}
41 joinable(false),
42 priority(ThreadPriority::NORMAL),
43 handle(NULL),
44 handle_set(false, false) {
45 }
46 38
47 PlatformThread::Delegate* delegate; 39 PlatformThread::Delegate* delegate;
48 bool joinable; 40 bool joinable;
49 ThreadPriority priority; 41 ThreadPriority priority;
50 PlatformThreadHandle* handle;
51 WaitableEvent handle_set;
52 }; 42 };
53 43
54 void* ThreadFunc(void* params) { 44 void* ThreadFunc(void* params) {
55 base::InitOnThread(); 45 base::InitOnThread();
56 ThreadParams* thread_params = static_cast<ThreadParams*>(params); 46 scoped_ptr<ThreadParams> thread_params(static_cast<ThreadParams*>(params));
Dmitry Skiba 2015/07/28 21:33:41 Just curious - do we support calling pthread_exit(
57 47
58 PlatformThread::Delegate* delegate = thread_params->delegate; 48 PlatformThread::Delegate* delegate = thread_params->delegate;
59 if (!thread_params->joinable) 49 if (!thread_params->joinable)
60 base::ThreadRestrictions::SetSingletonAllowed(false); 50 base::ThreadRestrictions::SetSingletonAllowed(false);
61 51
62 if (thread_params->priority != ThreadPriority::NORMAL) 52 if (thread_params->priority != ThreadPriority::NORMAL)
63 PlatformThread::SetCurrentThreadPriority(thread_params->priority); 53 PlatformThread::SetCurrentThreadPriority(thread_params->priority);
64 54
65 // Stash the id in the handle so the calling thread has a complete
66 // handle, and unblock the parent thread.
67 *(thread_params->handle) = PlatformThreadHandle(pthread_self());
68 thread_params->handle_set.Signal();
69
70 ThreadIdNameManager::GetInstance()->RegisterThread( 55 ThreadIdNameManager::GetInstance()->RegisterThread(
71 PlatformThread::CurrentHandle().platform_handle(), 56 PlatformThread::CurrentHandle().platform_handle(),
72 PlatformThread::CurrentId()); 57 PlatformThread::CurrentId());
73 58
74 delegate->ThreadMain(); 59 delegate->ThreadMain();
75 60
76 ThreadIdNameManager::GetInstance()->RemoveName( 61 ThreadIdNameManager::GetInstance()->RemoveName(
77 PlatformThread::CurrentHandle().platform_handle(), 62 PlatformThread::CurrentHandle().platform_handle(),
78 PlatformThread::CurrentId()); 63 PlatformThread::CurrentId());
79 64
80 base::TerminateOnThread(); 65 base::TerminateOnThread();
81 return NULL; 66 return NULL;
82 } 67 }
83 68
84 bool CreateThread(size_t stack_size, bool joinable, 69 bool CreateThread(size_t stack_size,
70 bool joinable,
85 PlatformThread::Delegate* delegate, 71 PlatformThread::Delegate* delegate,
86 PlatformThreadHandle* thread_handle, 72 PlatformThreadHandle* thread_handle,
87 ThreadPriority priority) { 73 ThreadPriority priority) {
74 DCHECK(thread_handle);
88 base::InitThreading(); 75 base::InitThreading();
89 76
90 bool success = false;
91 pthread_attr_t attributes; 77 pthread_attr_t attributes;
92 pthread_attr_init(&attributes); 78 pthread_attr_init(&attributes);
93 79
94 // Pthreads are joinable by default, so only specify the detached 80 // Pthreads are joinable by default, so only specify the detached
95 // attribute if the thread should be non-joinable. 81 // attribute if the thread should be non-joinable.
96 if (!joinable) { 82 if (!joinable)
97 pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED); 83 pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
98 }
99 84
100 // Get a better default if available. 85 // Get a better default if available.
101 if (stack_size == 0) 86 if (stack_size == 0)
102 stack_size = base::GetDefaultThreadStackSize(attributes); 87 stack_size = base::GetDefaultThreadStackSize(attributes);
103 88
104 if (stack_size > 0) 89 if (stack_size > 0)
105 pthread_attr_setstacksize(&attributes, stack_size); 90 pthread_attr_setstacksize(&attributes, stack_size);
106 91
107 ThreadParams params; 92 scoped_ptr<ThreadParams> params(new ThreadParams);
108 params.delegate = delegate; 93 params->delegate = delegate;
109 params.joinable = joinable; 94 params->joinable = joinable;
110 params.priority = priority; 95 params->priority = priority;
111 params.handle = thread_handle;
112 96
113 pthread_t handle; 97 pthread_t handle;
114 int err = pthread_create(&handle, 98 int err =
115 &attributes, 99 pthread_create(&handle, &attributes, ThreadFunc, params.get());
116 ThreadFunc, 100 bool success = !err;
117 &params); 101 if (success) {
118 success = !err; 102 // ThreadParams should be deleted on the created thread after used.
119 if (!success) { 103 ignore_result(params.release());
104 } else {
120 // Value of |handle| is undefined if pthread_create fails. 105 // Value of |handle| is undefined if pthread_create fails.
121 handle = 0; 106 handle = 0;
122 errno = err; 107 errno = err;
123 PLOG(ERROR) << "pthread_create"; 108 PLOG(ERROR) << "pthread_create";
124 } 109 }
110 *thread_handle = PlatformThreadHandle(handle);
125 111
126 pthread_attr_destroy(&attributes); 112 pthread_attr_destroy(&attributes);
127 113
128 // Don't let this call complete until the thread id
129 // is set in the handle.
130 if (success) {
131 // TODO(toyoshim): Remove this after a few days (crbug.com/495097)
132 tracked_objects::ScopedTracker tracking_profile(
133 FROM_HERE_WITH_EXPLICIT_FUNCTION(
134 "495097 pthread_create and handle_set.Wait"));
135 params.handle_set.Wait();
136 }
137 CHECK_EQ(handle, thread_handle->platform_handle());
138
139 return success; 114 return success;
140 } 115 }
141 116
142 } // namespace 117 } // namespace
143 118
144 // static 119 // static
145 PlatformThreadId PlatformThread::CurrentId() { 120 PlatformThreadId PlatformThread::CurrentId() {
146 // Pthreads doesn't have the concept of a thread ID, so we have to reach down 121 // Pthreads doesn't have the concept of a thread ID, so we have to reach down
147 // into the kernel. 122 // into the kernel.
148 #if defined(OS_MACOSX) 123 #if defined(OS_MACOSX)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 170
196 // static 171 // static
197 const char* PlatformThread::GetName() { 172 const char* PlatformThread::GetName() {
198 return ThreadIdNameManager::GetInstance()->GetName(CurrentId()); 173 return ThreadIdNameManager::GetInstance()->GetName(CurrentId());
199 } 174 }
200 175
201 // static 176 // static
202 bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate, 177 bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate,
203 PlatformThreadHandle* thread_handle, 178 PlatformThreadHandle* thread_handle,
204 ThreadPriority priority) { 179 ThreadPriority priority) {
205 base::ThreadRestrictions::ScopedAllowWait allow_wait;
206 return CreateThread(stack_size, true, // joinable thread 180 return CreateThread(stack_size, true, // joinable thread
207 delegate, thread_handle, priority); 181 delegate, thread_handle, priority);
208 } 182 }
209 183
210 // static 184 // static
211 bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { 185 bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
212 PlatformThreadHandle unused; 186 PlatformThreadHandle unused;
213 187
214 base::ThreadRestrictions::ScopedAllowWait allow_wait;
215 bool result = CreateThread(stack_size, false /* non-joinable thread */, 188 bool result = CreateThread(stack_size, false /* non-joinable thread */,
216 delegate, &unused, ThreadPriority::NORMAL); 189 delegate, &unused, ThreadPriority::NORMAL);
217 return result; 190 return result;
218 } 191 }
219 192
220 // static 193 // static
221 void PlatformThread::Join(PlatformThreadHandle thread_handle) { 194 void PlatformThread::Join(PlatformThreadHandle thread_handle) {
222 // Joining another thread may block the current thread for a long time, since 195 // Joining another thread may block the current thread for a long time, since
223 // the thread referred to by |thread_handle| may still be running long-lived / 196 // the thread referred to by |thread_handle| may still be running long-lived /
224 // blocking tasks. 197 // blocking tasks.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 return ThreadPriority::NORMAL; 247 return ThreadPriority::NORMAL;
275 } 248 }
276 249
277 return internal::NiceValueToThreadPriority(nice_value); 250 return internal::NiceValueToThreadPriority(nice_value);
278 #endif // !defined(OS_NACL) 251 #endif // !defined(OS_NACL)
279 } 252 }
280 253
281 #endif // !defined(OS_MACOSX) 254 #endif // !defined(OS_MACOSX)
282 255
283 } // namespace base 256 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698