From b880b5a9200231dfeea17d2d9400d2d8b2e7d476 Mon Sep 17 00:00:00 2001 From: HyungKyu Song Date: Fri, 15 Feb 2013 15:08:30 +0900 Subject: Tizen 2.0 Release --- base/threading/platform_thread_posix.cc | 262 ++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 base/threading/platform_thread_posix.cc (limited to 'base/threading/platform_thread_posix.cc') diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc new file mode 100644 index 000000000000..c924a16d384c --- /dev/null +++ b/base/threading/platform_thread_posix.cc @@ -0,0 +1,262 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/platform_thread.h" + +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/safe_strerror_posix.h" +#include "base/threading/thread_local.h" +#include "base/threading/thread_restrictions.h" + +#if defined(OS_MACOSX) +#include +#include +#include +#endif + +#if defined(OS_LINUX) +#include +#include +#include +#include +#endif + +#if defined(OS_ANDROID) +#include "base/android/jni_android.h" +#endif + +#if defined(OS_NACL) +#include +#endif + +namespace base { + +#if defined(OS_MACOSX) +void InitThreading(); +#endif + +namespace { + +static ThreadLocalPointer current_thread_name; + +struct ThreadParams { + PlatformThread::Delegate* delegate; + bool joinable; +}; + +void* ThreadFunc(void* params) { + ThreadParams* thread_params = static_cast(params); + PlatformThread::Delegate* delegate = thread_params->delegate; + if (!thread_params->joinable) + base::ThreadRestrictions::SetSingletonAllowed(false); + delete thread_params; + delegate->ThreadMain(); +#if defined(OS_ANDROID) + base::android::DetachFromVM(); +#endif + return NULL; +} + +bool CreateThread(size_t stack_size, bool joinable, + PlatformThread::Delegate* delegate, + PlatformThreadHandle* thread_handle) { +#if defined(OS_MACOSX) + base::InitThreading(); +#endif // OS_MACOSX + + bool success = false; + pthread_attr_t attributes; + pthread_attr_init(&attributes); + + // Pthreads are joinable by default, so only specify the detached attribute if + // the thread should be non-joinable. + if (!joinable) { + pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED); + } + +#if defined(OS_MACOSX) + // The Mac OS X default for a pthread stack size is 512kB. + // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses + // DEFAULT_STACK_SIZE for this purpose. + // + // 512kB isn't quite generous enough for some deeply recursive threads that + // otherwise request the default stack size by specifying 0. Here, adopt + // glibc's behavior as on Linux, which is to use the current stack size + // limit (ulimit -s) as the default stack size. See + // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To + // avoid setting the limit below the Mac OS X default or the minimum usable + // stack size, these values are also considered. If any of these values + // can't be determined, or if stack size is unlimited (ulimit -s unlimited), + // stack_size is left at 0 to get the system default. + // + // Mac OS X normally only applies ulimit -s to the main thread stack. On + // contemporary OS X and Linux systems alike, this value is generally 8MB + // or in that neighborhood. + if (stack_size == 0) { + size_t default_stack_size; + struct rlimit stack_rlimit; + if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 && + getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 && + stack_rlimit.rlim_cur != RLIM_INFINITY) { + stack_size = std::max(std::max(default_stack_size, + static_cast(PTHREAD_STACK_MIN)), + static_cast(stack_rlimit.rlim_cur)); + } + } +#endif // OS_MACOSX + + if (stack_size > 0) + pthread_attr_setstacksize(&attributes, stack_size); + + ThreadParams* params = new ThreadParams; + params->delegate = delegate; + params->joinable = joinable; + success = !pthread_create(thread_handle, &attributes, ThreadFunc, params); + + pthread_attr_destroy(&attributes); + if (!success) + delete params; + return success; +} + +} // namespace + +// static +PlatformThreadId PlatformThread::CurrentId() { + // Pthreads doesn't have the concept of a thread ID, so we have to reach down + // into the kernel. +#if defined(OS_MACOSX) + return mach_thread_self(); +#elif defined(OS_LINUX) + return syscall(__NR_gettid); +#elif defined(OS_ANDROID) + return gettid(); +#elif defined(OS_FREEBSD) + // TODO(BSD): find a better thread ID + return reinterpret_cast(pthread_self()); +#elif defined(OS_NACL) || defined(OS_SOLARIS) + return pthread_self(); +#endif +} + +// static +void PlatformThread::YieldCurrentThread() { + sched_yield(); +} + +// static +void PlatformThread::Sleep(int duration_ms) { + struct timespec sleep_time, remaining; + + // Contains the portion of duration_ms >= 1 sec. + sleep_time.tv_sec = duration_ms / 1000; + duration_ms -= sleep_time.tv_sec * 1000; + + // Contains the portion of duration_ms < 1 sec. + sleep_time.tv_nsec = duration_ms * 1000 * 1000; // nanoseconds. + + while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR) + sleep_time = remaining; +} + +// Linux SetName is currently disabled, as we need to distinguish between +// helper threads (where it's ok to make this call) and the main thread +// (where making this call renames our process, causing tools like killall +// to stop working). +#if 0 && defined(OS_LINUX) +// static +void PlatformThread::SetName(const char* name) { + // have to cast away const because ThreadLocalPointer does not support const + // void* + current_thread_name.Set(const_cast(name)); + + // http://0pointer.de/blog/projects/name-your-threads.html + + // glibc recently added support for pthread_setname_np, but it's not + // commonly available yet. So test for it at runtime. + int (*dynamic_pthread_setname_np)(pthread_t, const char*); + *reinterpret_cast(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + + if (dynamic_pthread_setname_np) { + // This limit comes from glibc, which gets it from the kernel + // (TASK_COMM_LEN). + const int kMaxNameLength = 15; + std::string shortened_name = std::string(name).substr(0, kMaxNameLength); + int err = dynamic_pthread_setname_np(pthread_self(), + shortened_name.c_str()); + if (err < 0) + LOG(ERROR) << "pthread_setname_np: " << safe_strerror(err); + } else { + // Implementing this function without glibc is simple enough. (We + // don't do the name length clipping as above because it will be + // truncated by the callee (see TASK_COMM_LEN above).) + int err = prctl(PR_SET_NAME, name); + if (err < 0) + PLOG(ERROR) << "prctl(PR_SET_NAME)"; + } +} +#elif defined(OS_MACOSX) +// Mac is implemented in platform_thread_mac.mm. +#else +// static +void PlatformThread::SetName(const char* name) { + // have to cast away const because ThreadLocalPointer does not support const + // void* + current_thread_name.Set(const_cast(name)); + + // (This should be relatively simple to implement for the BSDs; I + // just don't have one handy to test the code on.) +} +#endif // defined(OS_LINUX) + + +#if !defined(OS_MACOSX) +// Mac is implemented in platform_thread_mac.mm. +// static +const char* PlatformThread::GetName() { + return current_thread_name.Get(); +} +#endif + +// static +bool PlatformThread::Create(size_t stack_size, Delegate* delegate, + PlatformThreadHandle* thread_handle) { + return CreateThread(stack_size, true /* joinable thread */, + delegate, thread_handle); +} + +// static +bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { + PlatformThreadHandle unused; + + bool result = CreateThread(stack_size, false /* non-joinable thread */, + delegate, &unused); + return result; +} + +// static +void PlatformThread::Join(PlatformThreadHandle thread_handle) { + // Joining another thread may block the current thread for a long time, since + // the thread referred to by |thread_handle| may still be running long-lived / + // blocking tasks. + base::ThreadRestrictions::AssertIOAllowed(); + pthread_join(thread_handle, NULL); +} + +#if !defined(OS_MACOSX) +// Mac OS X uses lower-level mach APIs + +// static +void PlatformThread::SetThreadPriority(PlatformThreadHandle, ThreadPriority) { + // TODO(crogers): implement + NOTIMPLEMENTED(); +} +#endif + +} // namespace base -- cgit v1.2.3