Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(692)

Side by Side Diff: mojo/edk/util/cond_var.cc

Issue 1426343002: EDK: Move mutex.*, cond_var.*, and thread_annotations.h to //mojo/edk/util. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/edk/system/cond_var.h" 5 #include "mojo/edk/util/cond_var.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <string.h> 8 #include <string.h>
9 #include <time.h> 9 #include <time.h>
10 10
11 #include <limits> 11 #include <limits>
12 12
13 #include "base/logging.h"
14 #include "build/build_config.h" 13 #include "build/build_config.h"
15 #include "mojo/edk/system/mutex.h" 14 #include "mojo/edk/util/logging_internal.h"
15 #include "mojo/edk/util/mutex.h"
16 16
17 namespace mojo { 17 namespace mojo {
18 namespace system { 18 namespace util {
19 19
20 namespace { 20 namespace {
21 21
22 // Helper for |CondVar::WaitWithTimeout()|. Returns true on (definite) time-out. 22 // Helper for |CondVar::WaitWithTimeout()|. Returns true on (definite) time-out.
23 bool RelativeTimedWait(const struct timespec& timeout_rel, 23 bool RelativeTimedWait(const struct timespec& timeout_rel,
24 pthread_cond_t* posix_cond_var, 24 pthread_cond_t* posix_cond_var,
25 pthread_mutex_t* posix_mutex) { 25 pthread_mutex_t* posix_mutex) {
26 // Mac has a function to do a relative timed wait directly. 26 // Mac has a function to do a relative timed wait directly.
27 #if defined(OS_MACOSX) 27 #if defined(OS_MACOSX)
28 int error = pthread_cond_timedwait_relative_np(posix_cond_var, posix_mutex, 28 int error = pthread_cond_timedwait_relative_np(posix_cond_var, posix_mutex,
29 &timeout_rel); 29 &timeout_rel);
30 DCHECK(error == 0 || error == ETIMEDOUT || error == EINTR) 30 INTERNAL_DCHECK_WITH_ERRNO(error == 0 || error == ETIMEDOUT || error == EINTR,
31 << ". pthread_cond_timedwait_relative_np: " << strerror(error); 31 "pthread_cond_timedwait_relative_np", error);
32 return error == ETIMEDOUT; 32 return error == ETIMEDOUT;
33 #else 33 #else
34 static const long kNanosecondsPerSecond = 1000000000L; 34 static const long kNanosecondsPerSecond = 1000000000L;
35 35
36 // NaCl's |pthread_condattr_setclock()| only supports |CLOCK_REALTIME| (which is 36 // NaCl's |pthread_condattr_setclock()| only supports |CLOCK_REALTIME| (which is
37 // the default, which is why we don't bother setting it in |CondVar|'s 37 // the default, which is why we don't bother setting it in |CondVar|'s
38 // constructor). 38 // constructor).
39 #if defined(OS_NACL) 39 #if defined(OS_NACL)
40 static const clockid_t kClockType = CLOCK_REALTIME; 40 static const clockid_t kClockType = CLOCK_REALTIME;
41 #else 41 #else
42 static const clockid_t kClockType = CLOCK_MONOTONIC; 42 static const clockid_t kClockType = CLOCK_MONOTONIC;
43 #endif // defined(OS_NACL) 43 #endif // defined(OS_NACL)
44 44
45 struct timespec timeout_abs; 45 struct timespec timeout_abs;
46 int error = clock_gettime(kClockType, &timeout_abs); 46 int error = clock_gettime(kClockType, &timeout_abs);
47 // Note: The return value of |clock_gettime()| is *not* an error code, unlike 47 // Note: The return value of |clock_gettime()| is *not* an error code, unlike
48 // the pthreads functions. 48 // the pthreads functions (however, it sets errno).
49 DPCHECK(!error) << "clock_gettime"; 49 INTERNAL_DCHECK_WITH_ERRNO(!error, "clock_gettime", errno);
50 50
51 timeout_abs.tv_sec += timeout_rel.tv_sec; 51 timeout_abs.tv_sec += timeout_rel.tv_sec;
52 timeout_abs.tv_nsec += timeout_rel.tv_nsec; 52 timeout_abs.tv_nsec += timeout_rel.tv_nsec;
53 if (timeout_abs.tv_nsec >= kNanosecondsPerSecond) { 53 if (timeout_abs.tv_nsec >= kNanosecondsPerSecond) {
54 timeout_abs.tv_sec++; 54 timeout_abs.tv_sec++;
55 timeout_abs.tv_nsec -= kNanosecondsPerSecond; 55 timeout_abs.tv_nsec -= kNanosecondsPerSecond;
56 DCHECK_LT(timeout_abs.tv_nsec, kNanosecondsPerSecond); 56 INTERNAL_DCHECK(timeout_abs.tv_nsec < kNanosecondsPerSecond);
57 } 57 }
58 58
59 // Older Android doesn't have |pthread_condattr_setclock()|, but they have 59 // Older Android doesn't have |pthread_condattr_setclock()|, but they have
60 // |pthread_cond_timedwait_monotonic_np()|. 60 // |pthread_cond_timedwait_monotonic_np()|.
61 #if defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) 61 #if defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
62 error = pthread_cond_timedwait_monotonic_np(posix_cond_var, posix_mutex, 62 error = pthread_cond_timedwait_monotonic_np(posix_cond_var, posix_mutex,
63 &timeout_abs); 63 &timeout_abs);
64 DCHECK(error == 0 || error == ETIMEDOUT || error == EINTR) 64 INTERNAL_DCHECK_WITH_ERRNO(error == 0 || error == ETIMEDOUT || error == EINTR,
65 << ". pthread_cond_timedwait_monotonic_np: " << strerror(error); 65 "pthread_cond_timedwait_monotonic_np", error);
66 #else 66 #else
67 error = pthread_cond_timedwait(posix_cond_var, posix_mutex, &timeout_abs); 67 error = pthread_cond_timedwait(posix_cond_var, posix_mutex, &timeout_abs);
68 DCHECK(error == 0 || error == ETIMEDOUT || error == EINTR) 68 INTERNAL_DCHECK_WITH_ERRNO(error == 0 || error == ETIMEDOUT || error == EINTR,
69 << ". pthread_cond_timedwait: " << strerror(error); 69 "pthread_cond_timedwait", error);
70 #endif // defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) 70 #endif // defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
71 return error == ETIMEDOUT; 71 return error == ETIMEDOUT;
72 #endif // defined(OS_MACOSX) 72 #endif // defined(OS_MACOSX)
73 } 73 }
74 74
75 } // namespace 75 } // namespace
76 76
77 CondVar::CondVar() { 77 CondVar::CondVar() {
78 // Mac and older Android don't have |pthread_condattr_setclock()| (but they have 78 // Mac and older Android don't have |pthread_condattr_setclock()| (but they have
79 // other timed wait functions we can use) and NaCl doesn't have a useful one. 79 // other timed wait functions we can use) and NaCl doesn't have a useful one.
80 #if !defined(OS_MACOSX) && !defined(OS_NACL) && \ 80 #if !defined(OS_MACOSX) && !defined(OS_NACL) && \
81 !(defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) 81 !(defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
82 pthread_condattr_t attr; 82 pthread_condattr_t attr;
83 int error = pthread_condattr_init(&attr); 83 int error = pthread_condattr_init(&attr);
84 DCHECK(!error) << "pthread_condattr_init: " << strerror(error); 84 INTERNAL_DCHECK_WITH_ERRNO(!error, "pthread_condattr_init", error);
85 error = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 85 error = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
86 DCHECK(!error) << "pthread_condattr_setclock: " << strerror(error); 86 INTERNAL_DCHECK_WITH_ERRNO(!error, "pthread_condattr_setclock", error);
87 error = pthread_cond_init(&impl_, &attr); 87 error = pthread_cond_init(&impl_, &attr);
88 DCHECK(!error) << "pthread_cond_init: " << strerror(error); 88 INTERNAL_DCHECK_WITH_ERRNO(!error, "pthread_cond_init", error);
89 error = pthread_condattr_destroy(&attr); 89 error = pthread_condattr_destroy(&attr);
90 DCHECK(!error) << "pthread_condattr_destroy: " << strerror(error); 90 INTERNAL_DCHECK_WITH_ERRNO(!error, "pthread_condattr_destroy", error);
91 #else 91 #else
92 int error = pthread_cond_init(&impl_, nullptr); 92 int error = pthread_cond_init(&impl_, nullptr);
93 DCHECK(!error) << "pthread_cond_init: " << strerror(error); 93 INTERNAL_DCHECK_WITH_ERRNO(!error, pthread_cond_init, error);
jamesr 2015/11/03 22:34:49 you probably meant "pthread_cond_init" here (i.e.
94 #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !(defined(OS_ANDROID)...) 94 #endif // !defined(OS_MACOSX) && !defined(OS_NACL) && !(defined(OS_ANDROID)...)
95 } 95 }
96 96
97 CondVar::~CondVar() { 97 CondVar::~CondVar() {
98 int error = pthread_cond_destroy(&impl_); 98 int error = pthread_cond_destroy(&impl_);
99 DCHECK(!error) << "pthread_cond_destroy: " << strerror(error); 99 INTERNAL_DCHECK_WITH_ERRNO(!error, "pthread_cond_destroy", error);
100 } 100 }
101 101
102 void CondVar::Wait(Mutex* mutex) { 102 void CondVar::Wait(Mutex* mutex) {
103 DCHECK(mutex); 103 INTERNAL_DCHECK(mutex);
104 mutex->AssertHeld(); 104 mutex->AssertHeld();
105 105
106 int error = pthread_cond_wait(&impl_, &mutex->impl_); 106 int error = pthread_cond_wait(&impl_, &mutex->impl_);
107 DCHECK(!error) << "pthread_cond_wait: " << strerror(error); 107 INTERNAL_DCHECK_WITH_ERRNO(!error, "pthread_cond_wait", error);
108 } 108 }
109 109
110 bool CondVar::WaitWithTimeout(Mutex* mutex, uint64_t timeout_microseconds) { 110 bool CondVar::WaitWithTimeout(Mutex* mutex, uint64_t timeout_microseconds) {
111 static const uint64_t kMicrosecondsPerSecond = 1000000ULL; 111 static const uint64_t kMicrosecondsPerSecond = 1000000ULL;
112 static const uint64_t kNanosecondsPerMicrosecond = 1000ULL; 112 static const uint64_t kNanosecondsPerMicrosecond = 1000ULL;
113 113
114 // Turn very long waits into "forever". This isn't a huge concern if |time_t| 114 // Turn very long waits into "forever". This isn't a huge concern if |time_t|
115 // is 64-bit, but overflowing |time_t| is a real risk if it's only 32-bit. 115 // is 64-bit, but overflowing |time_t| is a real risk if it's only 32-bit.
116 // (2^31 / 16 seconds = ~4.25 years, so we won't risk overflowing until 2033.) 116 // (2^31 / 16 seconds = ~4.25 years, so we won't risk overflowing until 2033.)
117 constexpr uint64_t kForeverThresholdSeconds = 117 constexpr uint64_t kForeverThresholdSeconds =
118 std::numeric_limits<time_t>::max() / 16; 118 std::numeric_limits<time_t>::max() / 16;
119 uint64_t timeout_seconds = timeout_microseconds / kMicrosecondsPerSecond; 119 uint64_t timeout_seconds = timeout_microseconds / kMicrosecondsPerSecond;
120 if (timeout_seconds >= kForeverThresholdSeconds) { 120 if (timeout_seconds >= kForeverThresholdSeconds) {
121 Wait(mutex); 121 Wait(mutex);
122 return false; // Did *not* time out. 122 return false; // Did *not* time out.
123 } 123 }
124 124
125 DCHECK(mutex); 125 INTERNAL_DCHECK(mutex);
126 mutex->AssertHeld(); 126 mutex->AssertHeld();
127 127
128 struct timespec timeout_rel = {}; 128 struct timespec timeout_rel = {};
129 timeout_rel.tv_sec = static_cast<time_t>(timeout_seconds); 129 timeout_rel.tv_sec = static_cast<time_t>(timeout_seconds);
130 timeout_rel.tv_nsec = 130 timeout_rel.tv_nsec =
131 static_cast<long>((timeout_microseconds % kMicrosecondsPerSecond) * 131 static_cast<long>((timeout_microseconds % kMicrosecondsPerSecond) *
132 kNanosecondsPerMicrosecond); 132 kNanosecondsPerMicrosecond);
133 return RelativeTimedWait(timeout_rel, &impl_, &mutex->impl_); 133 return RelativeTimedWait(timeout_rel, &impl_, &mutex->impl_);
134 } 134 }
135 135
136 void CondVar::Signal() { 136 void CondVar::Signal() {
137 int error = pthread_cond_signal(&impl_); 137 int error = pthread_cond_signal(&impl_);
138 DCHECK(!error) << "pthread_cond_signal: " << strerror(error); 138 INTERNAL_DCHECK_WITH_ERRNO(!error, "pthread_cond_signal", error);
139 } 139 }
140 140
141 void CondVar::SignalAll() { 141 void CondVar::SignalAll() {
142 int error = pthread_cond_broadcast(&impl_); 142 int error = pthread_cond_broadcast(&impl_);
143 DCHECK(!error) << "pthread_cond_broadcast: " << strerror(error); 143 INTERNAL_DCHECK_WITH_ERRNO(!error, "pthread_cond_broadcast", error);
144 } 144 }
145 145
146 } // namespace system 146 } // namespace util
147 } // namespace mojo 147 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698