jdk

Форк
0
/
shenandoahLock.cpp 
131 строка · 4.4 Кб
1
/*
2
 * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
 *
5
 * This code is free software; you can redistribute it and/or modify it
6
 * under the terms of the GNU General Public License version 2 only, as
7
 * published by the Free Software Foundation.
8
 *
9
 * This code is distributed in the hope that it will be useful, but WITHOUT
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
 * version 2 for more details (a copy is included in the LICENSE file that
13
 * accompanied this code).
14
 *
15
 * You should have received a copy of the GNU General Public License version
16
 * 2 along with this work; if not, write to the Free Software Foundation,
17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
 * or visit www.oracle.com if you need additional information or have any
21
 * questions.
22
 *
23
 */
24

25
#include "precompiled.hpp"
26

27
#include "runtime/os.hpp"
28

29
#include "gc/shenandoah/shenandoahLock.hpp"
30
#include "runtime/atomic.hpp"
31
#include "runtime/interfaceSupport.inline.hpp"
32
#include "runtime/javaThread.hpp"
33
#include "runtime/os.inline.hpp"
34

35
void ShenandoahLock::contended_lock(bool allow_block_for_safepoint) {
36
  Thread* thread = Thread::current();
37
  if (allow_block_for_safepoint && thread->is_Java_thread()) {
38
    contended_lock_internal<true>(JavaThread::cast(thread));
39
  } else {
40
    contended_lock_internal<false>(nullptr);
41
  }
42
}
43

44
template<bool ALLOW_BLOCK>
45
void ShenandoahLock::contended_lock_internal(JavaThread* java_thread) {
46
  assert(!ALLOW_BLOCK || java_thread != nullptr, "Must have a Java thread when allowing block.");
47
  // Spin this much, but only on multi-processor systems.
48
  int ctr = os::is_MP() ? 0xFF : 0;
49
  // Apply TTAS to avoid more expensive CAS calls if the lock is still held by other thread.
50
  while (Atomic::load(&_state) == locked ||
51
         Atomic::cmpxchg(&_state, unlocked, locked) != unlocked) {
52
    if (ctr > 0 && !SafepointSynchronize::is_synchronizing()) {
53
      // Lightly contended, spin a little if no safepoint is pending.
54
      SpinPause();
55
      ctr--;
56
    } else if (ALLOW_BLOCK) {
57
      ThreadBlockInVM block(java_thread);
58
      if (SafepointSynchronize::is_synchronizing()) {
59
        // If safepoint is pending, we want to block and allow safepoint to proceed.
60
        // Normally, TBIVM above would block us in its destructor.
61
        //
62
        // But that blocking only happens when TBIVM knows the thread poll is armed.
63
        // There is a window between announcing a safepoint and arming the thread poll
64
        // during which trying to continuously enter TBIVM is counter-productive.
65
        // Under high contention, we may end up going in circles thousands of times.
66
        // To avoid it, we wait here until local poll is armed and then proceed
67
        // to TBVIM exit for blocking. We do not SpinPause, but yield to let
68
        // VM thread to arm the poll sooner.
69
        while (SafepointSynchronize::is_synchronizing() &&
70
               !SafepointMechanism::local_poll_armed(java_thread)) {
71
          os::naked_yield();
72
        }
73
      } else {
74
        os::naked_yield();
75
      }
76
    } else {
77
      os::naked_yield();
78
    }
79
  }
80
}
81

82
ShenandoahSimpleLock::ShenandoahSimpleLock() {
83
  assert(os::mutex_init_done(), "Too early!");
84
}
85

86
void ShenandoahSimpleLock::lock() {
87
  _lock.lock();
88
}
89

90
void ShenandoahSimpleLock::unlock() {
91
  _lock.unlock();
92
}
93

94
ShenandoahReentrantLock::ShenandoahReentrantLock() :
95
  ShenandoahSimpleLock(), _owner(nullptr), _count(0) {
96
  assert(os::mutex_init_done(), "Too early!");
97
}
98

99
ShenandoahReentrantLock::~ShenandoahReentrantLock() {
100
  assert(_count == 0, "Unbalance");
101
}
102

103
void ShenandoahReentrantLock::lock() {
104
  Thread* const thread = Thread::current();
105
  Thread* const owner = Atomic::load(&_owner);
106

107
  if (owner != thread) {
108
    ShenandoahSimpleLock::lock();
109
    Atomic::store(&_owner, thread);
110
  }
111

112
  _count++;
113
}
114

115
void ShenandoahReentrantLock::unlock() {
116
  assert(owned_by_self(), "Invalid owner");
117
  assert(_count > 0, "Invalid count");
118

119
  _count--;
120

121
  if (_count == 0) {
122
    Atomic::store(&_owner, (Thread*)nullptr);
123
    ShenandoahSimpleLock::unlock();
124
  }
125
}
126

127
bool ShenandoahReentrantLock::owned_by_self() const {
128
  Thread* const thread = Thread::current();
129
  Thread* const owner = Atomic::load(&_owner);
130
  return owner == thread;
131
}
132

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.