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. 4 5 #include "base/platform_thread.h" 6 7 #include <errno.h> 8 #include <sched.h> 9 10 #if defined(OS_MACOSX) 11 #include <mach/mach.h> 12 #else 13 #include <sys/syscall.h> 14 #include <unistd.h> 15 #endif 16 17 #if defined(OS_MACOSX) 18 namespace base { 19 void InitThreading(); 20 } // namespace 21 #endif 22 23 static void* ThreadFunc(void* closure) { 24 PlatformThread::Delegate* delegate = 25 static_cast<PlatformThread::Delegate*>(closure); 26 delegate->ThreadMain(); 27 return NULL; 28 } 29 30 // static 31 PlatformThreadId PlatformThread::CurrentId() { 32 // Pthreads doesn't have the concept of a thread ID, so we have to reach down 33 // into the kernel. 34 #if defined(OS_MACOSX) 35 return mach_thread_self(); 36 #elif defined(OS_LINUX) 37 return syscall(__NR_gettid); 38 #elif defined(OS_FREEBSD) 39 // TODO(BSD): find a better thread ID 40 return reinterpret_cast<int64>(pthread_self()); 41 #endif 42 } 43 44 // static 45 void PlatformThread::YieldCurrentThread() { 46 sched_yield(); 47 } 48 49 // static 50 void PlatformThread::Sleep(int duration_ms) { 51 struct timespec sleep_time, remaining; 52 53 // Contains the portion of duration_ms >= 1 sec. 54 sleep_time.tv_sec = duration_ms / 1000; 55 duration_ms -= sleep_time.tv_sec * 1000; 56 57 // Contains the portion of duration_ms < 1 sec. 58 sleep_time.tv_nsec = duration_ms * 1000 * 1000; // nanoseconds. 59 60 while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR) 61 sleep_time = remaining; 62 } 63 64 // static 65 void PlatformThread::SetName(const char* name) { 66 // The POSIX standard does not provide for naming threads, and neither Linux 67 // nor Mac OS X (our two POSIX targets) provide any non-portable way of doing 68 // it either. (Some BSDs provide pthread_set_name_np but that isn't much of a 69 // consolation prize.) 70 // TODO(darin): decide whether stuffing the name in TLS or other in-memory 71 // structure would be useful for debugging or not. 72 } 73 74 namespace { 75 76 bool CreateThread(size_t stack_size, bool joinable, 77 PlatformThread::Delegate* delegate, 78 PlatformThreadHandle* thread_handle) { 79 #if defined(OS_MACOSX) 80 base::InitThreading(); 81 #endif // OS_MACOSX 82 83 bool success = false; 84 pthread_attr_t attributes; 85 pthread_attr_init(&attributes); 86 87 // Pthreads are joinable by default, so only specify the detached attribute if 88 // the thread should be non-joinable. 89 if (!joinable) { 90 pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED); 91 } 92 93 if (stack_size > 0) 94 pthread_attr_setstacksize(&attributes, stack_size); 95 96 success = !pthread_create(thread_handle, &attributes, ThreadFunc, delegate); 97 98 pthread_attr_destroy(&attributes); 99 return success; 100 } 101 102 } // anonymous namespace 103 104 // static 105 bool PlatformThread::Create(size_t stack_size, Delegate* delegate, 106 PlatformThreadHandle* thread_handle) { 107 return CreateThread(stack_size, true /* joinable thread */, 108 delegate, thread_handle); 109 } 110 111 // static 112 bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { 113 PlatformThreadHandle unused; 114 115 bool result = CreateThread(stack_size, false /* non-joinable thread */, 116 delegate, &unused); 117 return result; 118 } 119 120 // static 121 void PlatformThread::Join(PlatformThreadHandle thread_handle) { 122 pthread_join(thread_handle, NULL); 123 } 124