YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/condition_variable.cc
Line
Count
Source (jump to first uncovered line)
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
3
// found in the LICENSE file.
4
//
5
// The following only applies to changes made to this file as part of YugaByte development.
6
//
7
// Portions Copyright (c) YugaByte, Inc.
8
//
9
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
10
// in compliance with the License.  You may obtain a copy of the License at
11
//
12
// http://www.apache.org/licenses/LICENSE-2.0
13
//
14
// Unless required by applicable law or agreed to in writing, software distributed under the License
15
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
16
// or implied.  See the License for the specific language governing permissions and limitations
17
// under the License.
18
//
19
#include "yb/util/condition_variable.h"
20
21
#include <glog/logging.h>
22
23
#include "yb/util/errno.h"
24
#include "yb/util/monotime.h"
25
#include "yb/util/thread_restrictions.h"
26
27
using std::string;
28
29
namespace yb {
30
31
ConditionVariable::ConditionVariable(Mutex* user_lock)
32
    : user_mutex_(&user_lock->native_handle_)
33
#if !defined(NDEBUG)
34
    , user_lock_(user_lock)
35
#endif
36
4.42M
{
37
4.42M
  int rv = 0;
38
  // http://crbug.com/293736
39
  // NaCl doesn't support monotonic clock based absolute deadlines.
40
  // On older Android platform versions, it's supported through the
41
  // non-standard pthread_cond_timedwait_monotonic_np. Newer platform
42
  // versions have pthread_condattr_setclock.
43
  // Mac can use relative time deadlines.
44
#if !defined(__APPLE__) && !defined(OS_NACL) && \
45
      !(defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
46
  pthread_condattr_t attrs;
47
  rv = pthread_condattr_init(&attrs);
48
  DCHECK_EQ(0, rv);
49
  pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC);
50
  rv = pthread_cond_init(&condition_, &attrs);
51
  pthread_condattr_destroy(&attrs);
52
#else
53
4.42M
  rv = pthread_cond_init(&condition_, nullptr);
54
4.42M
#endif
55
0
  DCHECK_EQ(0, rv) << ErrnoToString(rv);
56
4.42M
}
57
58
2.08M
ConditionVariable::~ConditionVariable() {
59
2.08M
#if defined(OS_MACOSX)
60
  // This hack is necessary to avoid a fatal pthreads subsystem bug in the
61
  // Darwin kernel. https://codereview.chromium.org/1323293005/
62
2.08M
  {
63
2.08M
    Mutex lock;
64
2.08M
    MutexLock l(lock);
65
2.08M
    struct timespec ts;
66
2.08M
    ts.tv_sec = 0;
67
2.08M
    ts.tv_nsec = 1;
68
2.08M
    pthread_cond_timedwait_relative_np(&condition_, &lock.native_handle_, &ts);
69
2.08M
  }
70
2.08M
#endif
71
2.08M
  int rv = pthread_cond_destroy(&condition_);
72
0
  DCHECK_EQ(0, rv) << ErrnoToString(rv);
73
2.08M
}
74
75
10.7M
void ConditionVariable::Wait() const {
76
10.7M
  ThreadRestrictions::AssertWaitAllowed();
77
10.7M
#if !defined(NDEBUG)
78
10.7M
  user_lock_->CheckHeldAndUnmark();
79
10.7M
#endif
80
10.7M
  int rv = pthread_cond_wait(&condition_, user_mutex_);
81
0
  DCHECK_EQ(0, rv) << ErrnoToString(rv);
82
10.7M
#if !defined(NDEBUG)
83
10.7M
  user_lock_->CheckUnheldAndMark();
84
10.7M
#endif
85
10.7M
}
86
87
13.7M
bool ConditionVariable::WaitUntil(const MonoTime& wait_timeout_deadline) const {
88
13.7M
  return TimedWait(wait_timeout_deadline - MonoTime::Now());
89
13.7M
}
90
91
45.7M
bool ConditionVariable::TimedWait(const MonoDelta& max_time) const {
92
45.7M
  ThreadRestrictions::AssertWaitAllowed();
93
94
  // Negative delta means we've already timed out.
95
45.7M
  int64 nsecs = max_time.ToNanoseconds();
96
45.7M
  if (nsecs < 0) {
97
0
    return false;
98
0
  }
99
100
45.7M
  struct timespec relative_time;
101
45.7M
  max_time.ToTimeSpec(&relative_time);
102
103
45.7M
#if !defined(NDEBUG)
104
45.7M
  user_lock_->CheckHeldAndUnmark();
105
45.7M
#endif
106
107
45.7M
#if defined(__APPLE__)
108
45.7M
  int rv = pthread_cond_timedwait_relative_np(
109
45.7M
      &condition_, user_mutex_, &relative_time);
110
#else
111
  // The timeout argument to pthread_cond_timedwait is in absolute time.
112
  struct timespec absolute_time;
113
#if defined(OS_NACL)
114
  // See comment in constructor for why this is different in NaCl.
115
  struct timeval now;
116
  gettimeofday(&now, NULL);
117
  absolute_time.tv_sec = now.tv_sec;
118
  absolute_time.tv_nsec = now.tv_usec * MonoTime::kNanosecondsPerMicrosecond;
119
#else
120
  struct timespec now;
121
  clock_gettime(CLOCK_MONOTONIC, &now);
122
  absolute_time.tv_sec = now.tv_sec;
123
  absolute_time.tv_nsec = now.tv_nsec;
124
#endif
125
126
  absolute_time.tv_sec += relative_time.tv_sec;
127
  absolute_time.tv_nsec += relative_time.tv_nsec;
128
  absolute_time.tv_sec += absolute_time.tv_nsec / MonoTime::kNanosecondsPerSecond;
129
  absolute_time.tv_nsec %= MonoTime::kNanosecondsPerSecond;
130
  DCHECK_GE(absolute_time.tv_sec, now.tv_sec);  // Overflow paranoia
131
132
#if defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
133
  int rv = pthread_cond_timedwait_monotonic_np(
134
      &condition_, user_mutex_, &absolute_time);
135
#else
136
  int rv = pthread_cond_timedwait(&condition_, user_mutex_, &absolute_time);
137
#endif  // OS_ANDROID && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC
138
#endif  // __APPLE__
139
140
98.1k
  DCHECK(rv == 0 || rv == ETIMEDOUT)
141
98.1k
    << "unexpected pthread_cond_timedwait return value: " << rv;
142
45.7M
#if !defined(NDEBUG)
143
45.7M
  user_lock_->CheckUnheldAndMark();
144
45.7M
#endif
145
45.7M
  return rv == 0;
146
45.7M
}
147
148
66.0M
void ConditionVariable::Broadcast() {
149
66.0M
  int rv = pthread_cond_broadcast(&condition_);
150
0
  DCHECK_EQ(0, rv) << ErrnoToString(rv);
151
66.0M
}
152
153
198M
void ConditionVariable::Signal() {
154
198M
  int rv = pthread_cond_signal(&condition_);
155
0
  DCHECK_EQ(0, rv) << ErrnoToString(rv);
156
198M
}
157
158
}  // namespace yb