| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 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 "chrome/browser/sync/util/pthread_helpers.h" | |
| 6 | |
| 7 #if (defined(OS_LINUX) || defined(OS_MACOSX)) | |
| 8 #include <sys/time.h> | |
| 9 #endif // (defined(OS_LINUX) || defined(OS_MACOSX)) | |
| 10 | |
| 11 #include "base/atomicops.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/port.h" | |
| 14 #include "base/scoped_ptr.h" | |
| 15 #include "chrome/browser/sync/protocol/service_constants.h" | |
| 16 | |
| 17 #ifdef OS_WIN | |
| 18 | |
| 19 namespace { | |
| 20 | |
| 21 // Ensure that we don't bug the user more than once about the process being | |
| 22 // terminated. | |
| 23 base::subtle::AtomicWord g_process_terminating = 0; | |
| 24 | |
| 25 struct ThreadStartParams { | |
| 26 void *(*start) (void* payload); | |
| 27 void* param; | |
| 28 }; | |
| 29 | |
| 30 void* ThreadMainProc(void* parameter) { | |
| 31 ThreadStartParams* tsp = reinterpret_cast<ThreadStartParams*>(parameter); | |
| 32 void *(*start) (void *) = tsp->start; | |
| 33 void* param = tsp->param; | |
| 34 | |
| 35 delete tsp; | |
| 36 | |
| 37 void* result = NULL; | |
| 38 __try { | |
| 39 result = start(param); | |
| 40 } __except(EXCEPTION_CONTINUE_SEARCH) { | |
| 41 // Make sure only one thread complains and exits the process. Other | |
| 42 // faulting threads simply return. | |
| 43 if (0 == base::subtle::NoBarrier_CompareAndSwap( | |
| 44 &g_process_terminating, 0, 1)) { | |
| 45 // Service notification means we don't have a recursive event loop inside | |
| 46 // this call, and so won't suffer recursive exceptions. | |
| 47 ::MessageBox(NULL, | |
| 48 PRODUCT_NAME_STRING | |
| 49 L" has suffered a non-recoverable\n" | |
| 50 L"exception, and must exit immediately", | |
| 51 L"Nonrecoverable Exception", | |
| 52 MB_OK | MB_APPLMODAL | MB_SERVICE_NOTIFICATION); | |
| 53 | |
| 54 ::ExitProcess(GetExceptionCode()); | |
| 55 } | |
| 56 } | |
| 57 | |
| 58 return result; | |
| 59 } | |
| 60 | |
| 61 } // namespace | |
| 62 | |
| 63 #endif // OS_WIN | |
| 64 | |
| 65 thread_handle CreatePThread(void *(*start) (void *), void* parameter) { | |
| 66 #ifdef OS_WIN | |
| 67 scoped_ptr<ThreadStartParams> param(new ThreadStartParams); | |
| 68 if (NULL == param.get()) | |
| 69 return NULL; | |
| 70 | |
| 71 param->start = start; | |
| 72 param->param = parameter; | |
| 73 | |
| 74 pthread_t pthread; | |
| 75 if (0 != pthread_create(&pthread, NULL, ThreadMainProc, param.get())) | |
| 76 return NULL; | |
| 77 | |
| 78 // Ownership has passed to the new thread. | |
| 79 param.release(); | |
| 80 | |
| 81 const HANDLE thread_handle = pthread_getw32threadhandle_np(pthread); | |
| 82 HANDLE thread_copy; | |
| 83 // Have to duplicate the thread handle, because when we call | |
| 84 // pthread_detach(), the handle will get closed as soon as the thread exits. | |
| 85 // We want to keep the handle indefinitely. | |
| 86 CHECK(DuplicateHandle(GetCurrentProcess(), thread_handle, | |
| 87 GetCurrentProcess(), &thread_copy, 0, FALSE, | |
| 88 DUPLICATE_SAME_ACCESS)) << | |
| 89 "DuplicateHandle() failed with error " << GetLastError(); | |
| 90 pthread_detach(pthread); | |
| 91 return thread_copy; | |
| 92 #else | |
| 93 pthread_t handle; | |
| 94 | |
| 95 int result = pthread_create(&handle, NULL, start, parameter); | |
| 96 if (result == 0) { | |
| 97 return handle; | |
| 98 } else { | |
| 99 return 0; | |
| 100 } | |
| 101 #endif // OS_WIN | |
| 102 } | |
| 103 | |
| 104 struct timespec GetPThreadAbsoluteTime(uint32 ms) { | |
| 105 #ifdef OS_WIN | |
| 106 FILETIME filenow; | |
| 107 GetSystemTimeAsFileTime(&filenow); | |
| 108 ULARGE_INTEGER n; | |
| 109 n.LowPart = filenow.dwLowDateTime; | |
| 110 n.HighPart = filenow.dwHighDateTime; | |
| 111 // Filetime unit is 100-nanosecond intervals | |
| 112 const int64 ms_ftime = 10000; | |
| 113 n.QuadPart += ms_ftime * ms; | |
| 114 | |
| 115 // The number of 100 nanosecond intervals from Jan 1, 1601 'til Jan 1, 1970. | |
| 116 const int64 kOffset = GG_LONGLONG(116444736000000000); | |
| 117 timespec result; | |
| 118 result.tv_sec = static_cast<long>((n.QuadPart - kOffset) / 10000000); | |
| 119 result.tv_nsec = static_cast<long>((n.QuadPart - kOffset - | |
| 120 (result.tv_sec * GG_LONGLONG(10000000))) * 100); | |
| 121 return result; | |
| 122 #else | |
| 123 struct timeval now; | |
| 124 struct timezone zone; | |
| 125 gettimeofday(&now, &zone); | |
| 126 struct timespec deadline = { now.tv_sec }; | |
| 127 // microseconds to nanoseconds. | |
| 128 // and add the ms delay. | |
| 129 ms += now.tv_usec / 1000; | |
| 130 deadline.tv_sec += ms / 1000; | |
| 131 deadline.tv_nsec = (ms % 1000) * 1000000; | |
| 132 return deadline; | |
| 133 #endif // OS_WIN | |
| 134 } | |
| 135 | |
| 136 void NameCurrentThreadForDebugging(const char* name) { | |
| 137 #if defined(OS_WIN) | |
| 138 // This implementation is taken from Chromium's platform_thread framework. | |
| 139 // The information on how to set the thread name comes from a MSDN article: | |
| 140 // http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx | |
| 141 const DWORD kVCThreadNameException = 0x406D1388; | |
| 142 typedef struct tagTHREADNAME_INFO { | |
| 143 DWORD dwType; // Must be 0x1000. | |
| 144 LPCSTR szName; // Pointer to name (in user addr space). | |
| 145 DWORD dwThreadID; // Thread ID (-1=caller thread). | |
| 146 DWORD dwFlags; // Reserved for future use, must be zero. | |
| 147 } THREADNAME_INFO; | |
| 148 | |
| 149 // The debugger needs to be around to catch the name in the exception. If | |
| 150 // there isn't a debugger, we are just needlessly throwing an exception. | |
| 151 if (!::IsDebuggerPresent()) | |
| 152 return; | |
| 153 | |
| 154 THREADNAME_INFO info = { 0x1000, name, GetCurrentThreadId(), 0 }; | |
| 155 | |
| 156 __try { | |
| 157 RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD), | |
| 158 reinterpret_cast<DWORD_PTR*>(&info)); | |
| 159 } __except(EXCEPTION_CONTINUE_EXECUTION) { | |
| 160 } | |
| 161 #endif // defined(OS_WIN) | |
| 162 } | |
| OLD | NEW |