YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/gutil/once.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2008 Google Inc. All Rights Reserved.
2
//
3
// The following only applies to changes made to this file as part of YugaByte development.
4
//
5
// Portions Copyright (c) YugaByte, Inc.
6
//
7
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8
// in compliance with the License.  You may obtain a copy of the License at
9
//
10
// http://www.apache.org/licenses/LICENSE-2.0
11
//
12
// Unless required by applicable law or agreed to in writing, software distributed under the License
13
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14
// or implied.  See the License for the specific language governing permissions and limitations
15
// under the License.
16
//
17
18
#include <glog/logging.h>
19
#include "yb/gutil/logging-inl.h"
20
#include "yb/gutil/once.h"
21
#include "yb/gutil/dynamic_annotations.h"
22
#include "yb/gutil/spinlock_internal.h"
23
24
// All modifications to a GoogleOnceType occur inside GoogleOnceInternalInit.
25
// The fast path reads the variable with an acquire-load..
26
// This is safe provided we always perform a memory barrier
27
// immediately before setting the value to GOOGLE_ONCE_INTERNAL_DONE.
28
29
void GoogleOnceInternalInit(Atomic32 *control, void (*func)(),
30
131k
                            void (*func_with_arg)(void*), void* arg) {
31
131k
  if (DEBUG_MODE) {
32
131k
    int64 old_control = base::subtle::Acquire_Load(control);
33
131k
    if (old_control != GOOGLE_ONCE_INTERNAL_INIT &&
34
911
        old_control != GOOGLE_ONCE_INTERNAL_RUNNING &&
35
431
        old_control != GOOGLE_ONCE_INTERNAL_WAITER &&
36
40
        old_control != GOOGLE_ONCE_INTERNAL_DONE) {
37
0
      LOG(FATAL) << "Either GoogleOnceType is used in non-static storage "
38
0
                    "(where GoogleOnceDynamic might be appropriate), "
39
0
                    "or there's a memory corruption.";
40
0
    }
41
131k
  }
42
131k
  static const yb::base::internal::SpinLockWaitTransition trans[] = {
43
131k
    { GOOGLE_ONCE_INTERNAL_INIT, GOOGLE_ONCE_INTERNAL_RUNNING, true },
44
131k
    { GOOGLE_ONCE_INTERNAL_RUNNING, GOOGLE_ONCE_INTERNAL_WAITER, false },
45
131k
    { GOOGLE_ONCE_INTERNAL_DONE, GOOGLE_ONCE_INTERNAL_DONE, true }
46
131k
  };
47
  // Short circuit the simplest case to avoid procedure call overhead.
48
131k
  if (::base::subtle::Acquire_CompareAndSwap(control, GOOGLE_ONCE_INTERNAL_INIT,
49
131k
          GOOGLE_ONCE_INTERNAL_RUNNING) == GOOGLE_ONCE_INTERNAL_INIT ||
50
2.50k
      yb::base::internal::SpinLockWait(control, ARRAYSIZE(trans), trans) ==
51
129k
      GOOGLE_ONCE_INTERNAL_INIT) {
52
129k
    if (func != nullptr) {
53
129k
      (*func)();
54
3
    } else {
55
3
      (*func_with_arg)(arg);
56
3
    }
57
129k
    ANNOTATE_HAPPENS_BEFORE(control);
58
129k
    int64 old_control = base::subtle::NoBarrier_Load(control);
59
129k
    ::base::subtle::Release_Store(control, GOOGLE_ONCE_INTERNAL_DONE);
60
129k
    if (old_control == GOOGLE_ONCE_INTERNAL_WAITER) {
61
869
      yb::base::internal::SpinLockWake(control, true);
62
869
    }
63
129k
  } // else *control is already GOOGLE_ONCE_INTERNAL_DONE
64
131k
}