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

Side by Side Diff: base/synchronization/condition_variable_posix.cc

Issue 24158005: Fix WaitableEvent and ConditionVariable::TimedWait to use monotonic time on non-mac posix (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add test Created 7 years, 2 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | base/synchronization/condition_variable_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/synchronization/condition_variable.h" 5 #include "base/synchronization/condition_variable.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <sys/time.h> 8 #include <sys/time.h>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/synchronization/lock.h" 11 #include "base/synchronization/lock.h"
12 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
13 #include "base/time/time.h" 13 #include "base/time/time.h"
14 14
15 namespace base { 15 namespace base {
16 16
17 ConditionVariable::ConditionVariable(Lock* user_lock) 17 ConditionVariable::ConditionVariable(Lock* user_lock)
18 : user_mutex_(user_lock->lock_.native_handle()) 18 : user_mutex_(user_lock->lock_.native_handle())
19 #if !defined(NDEBUG) 19 #if !defined(NDEBUG)
20 , user_lock_(user_lock) 20 , user_lock_(user_lock)
21 #endif 21 #endif
22 { 22 {
23 int rv = pthread_cond_init(&condition_, NULL); 23 int rv = 0;
24 // http://crbug.com/293736
25 // Mac and NaCl don't support monotonic clock based deadlines.
26 // Android supports it through the non-standard
27 // pthread_cond_timedwait_monotonic_np.
28 #if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_ANDROID)
29 pthread_condattr_t attrs;
30 rv = pthread_condattr_init(&attrs);
31 DCHECK_EQ(0, rv);
32 pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC);
33 rv = pthread_cond_init(&condition_, &attrs);
34 pthread_condattr_destroy(&attrs);
35 #else
36 rv = pthread_cond_init(&condition_, NULL);
37 #endif
24 DCHECK_EQ(0, rv); 38 DCHECK_EQ(0, rv);
25 } 39 }
26 40
27 ConditionVariable::~ConditionVariable() { 41 ConditionVariable::~ConditionVariable() {
28 int rv = pthread_cond_destroy(&condition_); 42 int rv = pthread_cond_destroy(&condition_);
29 DCHECK_EQ(0, rv); 43 DCHECK_EQ(0, rv);
30 } 44 }
31 45
32 void ConditionVariable::Wait() { 46 void ConditionVariable::Wait() {
33 base::ThreadRestrictions::AssertWaitAllowed(); 47 base::ThreadRestrictions::AssertWaitAllowed();
34 #if !defined(NDEBUG) 48 #if !defined(NDEBUG)
35 user_lock_->CheckHeldAndUnmark(); 49 user_lock_->CheckHeldAndUnmark();
36 #endif 50 #endif
37 int rv = pthread_cond_wait(&condition_, user_mutex_); 51 int rv = pthread_cond_wait(&condition_, user_mutex_);
38 DCHECK_EQ(0, rv); 52 DCHECK_EQ(0, rv);
39 #if !defined(NDEBUG) 53 #if !defined(NDEBUG)
40 user_lock_->CheckUnheldAndMark(); 54 user_lock_->CheckUnheldAndMark();
41 #endif 55 #endif
42 } 56 }
43 57
44 void ConditionVariable::TimedWait(const TimeDelta& max_time) { 58 void ConditionVariable::TimedWait(const TimeDelta& max_time) {
45 base::ThreadRestrictions::AssertWaitAllowed(); 59 base::ThreadRestrictions::AssertWaitAllowed();
46 int64 usecs = max_time.InMicroseconds(); 60 int64 usecs = max_time.InMicroseconds();
47 61
48 // The timeout argument to pthread_cond_timedwait is in absolute time. 62 // The timeout argument to pthread_cond_timedwait is in absolute time.
63 struct timespec abstime;
64 #if defined(OS_MACOSX) || defined(OS_NACL)
49 struct timeval now; 65 struct timeval now;
50 gettimeofday(&now, NULL); 66 gettimeofday(&now, NULL);
67 abstime.tv_sec = now.tv_sec;
68 abstime.tv_nsec = now.tv_usec * Time::kNanosecondsPerMicrosecond;
69 #else
70 struct timespec now;
71 clock_gettime(CLOCK_MONOTONIC, &now);
72 abstime.tv_sec = now.tv_sec;
73 abstime.tv_nsec = now.tv_nsec;
74 #endif
51 75
52 struct timespec abstime; 76 abstime.tv_sec += usecs / Time::kMicrosecondsPerSecond;
53 abstime.tv_sec = now.tv_sec + (usecs / Time::kMicrosecondsPerSecond); 77 abstime.tv_nsec +=
54 abstime.tv_nsec = (now.tv_usec + (usecs % Time::kMicrosecondsPerSecond)) * 78 (usecs % Time::kMicrosecondsPerSecond) * Time::kNanosecondsPerMicrosecond;
55 Time::kNanosecondsPerMicrosecond;
56 abstime.tv_sec += abstime.tv_nsec / Time::kNanosecondsPerSecond; 79 abstime.tv_sec += abstime.tv_nsec / Time::kNanosecondsPerSecond;
57 abstime.tv_nsec %= Time::kNanosecondsPerSecond; 80 abstime.tv_nsec %= Time::kNanosecondsPerSecond;
58 DCHECK_GE(abstime.tv_sec, now.tv_sec); // Overflow paranoia 81 DCHECK_GE(abstime.tv_sec, now.tv_sec); // Overflow paranoia
59 82
60 #if !defined(NDEBUG) 83 #if !defined(NDEBUG)
61 user_lock_->CheckHeldAndUnmark(); 84 user_lock_->CheckHeldAndUnmark();
62 #endif 85 #endif
86 #if defined(OS_ANDROID)
87 int rv = pthread_cond_timedwait_monotonic_np(
88 &condition_, user_mutex_, &abstime);
Nico 2013/10/01 21:20:42 I haven't used it before, but from some googling a
89 #else
63 int rv = pthread_cond_timedwait(&condition_, user_mutex_, &abstime); 90 int rv = pthread_cond_timedwait(&condition_, user_mutex_, &abstime);
91 #endif
64 DCHECK(rv == 0 || rv == ETIMEDOUT); 92 DCHECK(rv == 0 || rv == ETIMEDOUT);
65 #if !defined(NDEBUG) 93 #if !defined(NDEBUG)
66 user_lock_->CheckUnheldAndMark(); 94 user_lock_->CheckUnheldAndMark();
67 #endif 95 #endif
68 } 96 }
69 97
70 void ConditionVariable::Broadcast() { 98 void ConditionVariable::Broadcast() {
71 int rv = pthread_cond_broadcast(&condition_); 99 int rv = pthread_cond_broadcast(&condition_);
72 DCHECK_EQ(0, rv); 100 DCHECK_EQ(0, rv);
73 } 101 }
74 102
75 void ConditionVariable::Signal() { 103 void ConditionVariable::Signal() {
76 int rv = pthread_cond_signal(&condition_); 104 int rv = pthread_cond_signal(&condition_);
77 DCHECK_EQ(0, rv); 105 DCHECK_EQ(0, rv);
78 } 106 }
79 107
80 } // namespace base 108 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | base/synchronization/condition_variable_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698