diff options
author | nick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-10 06:05:27 +0000 |
---|---|---|
committer | nick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-10 06:05:27 +0000 |
commit | 5852edc1b6eab234b9e048c41dd0d664ae7fc747 (patch) | |
tree | 9e5d8eb4833b76cdb11e66fc3607689e0f5e0122 /chrome/browser/sync/util/pthread_helpers.cc | |
parent | f6059e37f8b8ac335ce18a189a13e702974a1c7e (diff) | |
download | chromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.zip chromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.tar.gz chromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.tar.bz2 |
Initial commit of sync engine code to browser/sync.
The code is not built on any platform yet. That will arrive
as a subsequent checkin.
This is an implementation of the interface exposed earlier
through syncapi.h. It is the client side of a sync
protocol that lets users sync their browser data
(currently, just bookmarks) with their Google Account.
Table of contents:
browser/sync/
protocol - The protocol definition, and
other definitions necessary to connect to
the service.
syncable/ - defines a data model for syncable objects,
and provides a sqlite-based backing store
for this model.
engine/ - includes the core sync logic, including commiting
changes to the server, downloading changes from
the server, resolving conflicts, other parts of
the sync algorithm.
engine/net - parts of the sync engine focused on the
business of talking to the server. Some of
this is binds a generic "server connection"
interface to a concrete implementation
provided by Chromium.
notifier - the part of the syncer focused on the business
of sending and receiving xmpp notifications.
Notifications are used instead of polling to
achieve very low latency change propagation.
util - not necessarily sync specific utility code. Much
of this is scaffolding which should either be
replaced by, or merged with, the utility code
in base/.
BUG=none
TEST=this code includes its own suite of unit tests.
Review URL: http://codereview.chromium.org/194065
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25850 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync/util/pthread_helpers.cc')
-rw-r--r-- | chrome/browser/sync/util/pthread_helpers.cc | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/chrome/browser/sync/util/pthread_helpers.cc b/chrome/browser/sync/util/pthread_helpers.cc new file mode 100644 index 0000000..4dadc55 --- /dev/null +++ b/chrome/browser/sync/util/pthread_helpers.cc @@ -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) +} |