| Index: chrome/browser/sync/util/pthread_helpers.cc
|
| ===================================================================
|
| --- chrome/browser/sync/util/pthread_helpers.cc (revision 0)
|
| +++ chrome/browser/sync/util/pthread_helpers.cc (revision 0)
|
| @@ -0,0 +1,162 @@
|
| +// Copyright (c) 2009 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 "chrome/browser/sync/util/pthread_helpers.h"
|
| +
|
| +#if (defined(OS_LINUX) || defined(OS_MACOSX))
|
| +#include <sys/time.h>
|
| +#endif // (defined(OS_LINUX) || defined(OS_MACOSX))
|
| +
|
| +#include "base/atomicops.h"
|
| +#include "base/logging.h"
|
| +#include "base/port.h"
|
| +#include "base/scoped_ptr.h"
|
| +#include "chrome/browser/sync/protocol/service_constants.h"
|
| +
|
| +#ifdef OS_WINDOWS
|
| +
|
| +namespace {
|
| +
|
| +// Ensure that we don't bug the user more than once about the process being
|
| +// terminated.
|
| +base::subtle::AtomicWord g_process_terminating = 0;
|
| +
|
| +struct ThreadStartParams {
|
| + void *(*start) (void* payload);
|
| + void* param;
|
| +};
|
| +
|
| +void* ThreadMainProc(void* parameter) {
|
| + ThreadStartParams* tsp = reinterpret_cast<ThreadStartParams*>(parameter);
|
| + void *(*start) (void *) = tsp->start;
|
| + void* param = tsp->param;
|
| +
|
| + delete tsp;
|
| +
|
| + void* result = NULL;
|
| + __try {
|
| + result = start(param);
|
| + } __except(EXCEPTION_CONTINUE_SEARCH) {
|
| + // Make sure only one thread complains and exits the process. Other
|
| + // faulting threads simply return.
|
| + if (0 == base::subtle::NoBarrier_CompareAndSwap(
|
| + &g_process_terminating, 0, 1)) {
|
| + // Service notification means we don't have a recursive event loop inside
|
| + // this call, and so won't suffer recursive exceptions.
|
| + ::MessageBox(NULL,
|
| + PRODUCT_NAME_STRING
|
| + L" has suffered a non-recoverable\n"
|
| + L"exception, and must exit immediately",
|
| + L"Nonrecoverable Exception",
|
| + MB_OK | MB_APPLMODAL | MB_SERVICE_NOTIFICATION);
|
| +
|
| + ::ExitProcess(GetExceptionCode());
|
| + }
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +#endif
|
| +
|
| +thread_handle CreatePThread(void *(*start) (void *), void* parameter) {
|
| +#ifdef OS_WINDOWS
|
| + scoped_ptr<ThreadStartParams> param(new ThreadStartParams);
|
| + if (NULL == param.get())
|
| + return NULL;
|
| +
|
| + param->start = start;
|
| + param->param = parameter;
|
| +
|
| + pthread_t pthread;
|
| + if (0 != pthread_create(&pthread, NULL, ThreadMainProc, param.get()))
|
| + return NULL;
|
| +
|
| + // ownership has passed to the new thread
|
| + param.release();
|
| +
|
| + const HANDLE thread_handle = pthread_getw32threadhandle_np(pthread);
|
| + HANDLE thread_copy;
|
| + // Have to duplicate the thread handle, because when we call
|
| + // pthread_detach(), the handle will get closed as soon as the thread exits.
|
| + // We want to keep the handle indefinitely.
|
| + CHECK(DuplicateHandle(GetCurrentProcess(), thread_handle,
|
| + GetCurrentProcess(), &thread_copy, 0, FALSE,
|
| + DUPLICATE_SAME_ACCESS)) <<
|
| + "DuplicateHandle() failed with error " << GetLastError();
|
| + pthread_detach(pthread);
|
| + return thread_copy;
|
| +#else
|
| + pthread_t handle;
|
| +
|
| + int result = pthread_create(&handle, NULL, start, parameter);
|
| + if (result == 0) {
|
| + return handle;
|
| + } else {
|
| + return 0;
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +struct timespec GetPThreadAbsoluteTime(uint32 ms) {
|
| +#ifdef OS_WINDOWS
|
| + FILETIME filenow;
|
| + GetSystemTimeAsFileTime(&filenow);
|
| + ULARGE_INTEGER n;
|
| + n.LowPart = filenow.dwLowDateTime;
|
| + n.HighPart = filenow.dwHighDateTime;
|
| + // Filetime unit is 100-nanosecond intervals
|
| + const int64 ms_ftime = 10000;
|
| + n.QuadPart += ms_ftime * ms;
|
| +
|
| + // The number of 100 nanosecond intervals from Jan 1, 1601 'til Jan 1, 1970.
|
| + const int64 kOffset = GG_LONGLONG(116444736000000000);
|
| + timespec result;
|
| + result.tv_sec = (n.QuadPart - kOffset) / 10000000;
|
| + result.tv_nsec = (n.QuadPart - kOffset -
|
| + (result.tv_sec * GG_LONGLONG(10000000))) * 100;
|
| + return result;
|
| +#else
|
| + struct timeval now;
|
| + struct timezone zone;
|
| + gettimeofday(&now, &zone);
|
| + struct timespec deadline = { now.tv_sec };
|
| + // microseconds to nanoseconds.
|
| + // and add the ms delay.
|
| + ms += now.tv_usec / 1000;
|
| + deadline.tv_sec += ms / 1000;
|
| + deadline.tv_nsec = (ms % 1000) * 1000000;
|
| + return deadline;
|
| +#endif
|
| +}
|
| +
|
| +void NameCurrentThreadForDebugging(char* name) {
|
| +#if defined(OS_WINDOWS)
|
| + // This implementation is taken from Chromium's platform_thread framework.
|
| + // The information on how to set the thread name comes from a MSDN article:
|
| + // http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
|
| + const DWORD kVCThreadNameException = 0x406D1388;
|
| + typedef struct tagTHREADNAME_INFO {
|
| + DWORD dwType; // Must be 0x1000.
|
| + LPCSTR szName; // Pointer to name (in user addr space).
|
| + DWORD dwThreadID; // Thread ID (-1=caller thread).
|
| + DWORD dwFlags; // Reserved for future use, must be zero.
|
| + } THREADNAME_INFO;
|
| +
|
| + // The debugger needs to be around to catch the name in the exception. If
|
| + // there isn't a debugger, we are just needlessly throwing an exception.
|
| + if (!::IsDebuggerPresent())
|
| + return;
|
| +
|
| + THREADNAME_INFO info = { 0x1000, name, GetCurrentThreadId(), 0 };
|
| +
|
| + __try {
|
| + RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD),
|
| + reinterpret_cast<DWORD_PTR*>(&info));
|
| + } __except(EXCEPTION_CONTINUE_EXECUTION) {
|
| + }
|
| +#endif // defined(OS_WINDOWS)
|
| +}
|
|
|
| Property changes on: chrome\browser\sync\util\pthread_helpers.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|