jdk

Форк
0
/
safepointMechanism.cpp 
172 строки · 7.0 Кб
1
/*
2
 * Copyright (c) 2017, 2022, Oracle and/or its affiliates. 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
#include "logging/log.hpp"
27
#include "nmt/memTracker.hpp"
28
#include "runtime/globals.hpp"
29
#include "runtime/javaThread.inline.hpp"
30
#include "runtime/orderAccess.hpp"
31
#include "runtime/os.hpp"
32
#include "runtime/osThread.hpp"
33
#include "runtime/safepointMechanism.inline.hpp"
34
#include "runtime/stackWatermarkSet.hpp"
35
#include "utilities/globalDefinitions.hpp"
36

37
uintptr_t SafepointMechanism::_poll_word_armed_value;
38
uintptr_t SafepointMechanism::_poll_word_disarmed_value;
39
uintptr_t SafepointMechanism::_poll_page_armed_value;
40
uintptr_t SafepointMechanism::_poll_page_disarmed_value;
41
address SafepointMechanism::_polling_page;
42

43
void SafepointMechanism::default_initialize() {
44
  // Poll bit values
45
  _poll_word_armed_value    = poll_bit();
46
  _poll_word_disarmed_value = ~_poll_word_armed_value;
47

48
  bool poll_bit_only = false;
49

50
#ifdef USE_POLL_BIT_ONLY
51
  poll_bit_only = USE_POLL_BIT_ONLY;
52
#endif
53

54
  if (poll_bit_only) {
55
    _poll_page_armed_value    = poll_bit();
56
    _poll_page_disarmed_value = 0;
57
  } else {
58
    // Polling page
59
    const size_t page_size = os::vm_page_size();
60
    const size_t allocation_size = 2 * page_size;
61
    char* polling_page = os::reserve_memory(allocation_size);
62
    os::commit_memory_or_exit(polling_page, allocation_size, false, "Unable to commit Safepoint polling page");
63
    MemTracker::record_virtual_memory_type((address)polling_page, mtSafepoint);
64

65
    char* bad_page  = polling_page;
66
    char* good_page = polling_page + page_size;
67

68
    os::protect_memory(bad_page,  page_size, os::MEM_PROT_NONE);
69
    os::protect_memory(good_page, page_size, os::MEM_PROT_READ);
70

71
    log_info(os)("SafePoint Polling address, bad (protected) page:" INTPTR_FORMAT ", good (unprotected) page:" INTPTR_FORMAT, p2i(bad_page), p2i(good_page));
72

73
    // Poll address values
74
    _poll_page_armed_value    = reinterpret_cast<uintptr_t>(bad_page);
75
    _poll_page_disarmed_value = reinterpret_cast<uintptr_t>(good_page);
76
    _polling_page = (address)bad_page;
77
  }
78
}
79

80
uintptr_t SafepointMechanism::compute_poll_word(bool armed, uintptr_t stack_watermark) {
81
  if (armed) {
82
    log_debug(stackbarrier)("Computed armed for tid %d", Thread::current()->osthread()->thread_id());
83
    return _poll_word_armed_value;
84
  }
85
  if (stack_watermark == 0) {
86
    log_debug(stackbarrier)("Computed disarmed for tid %d", Thread::current()->osthread()->thread_id());
87
    return _poll_word_disarmed_value;
88
  }
89
  log_debug(stackbarrier)("Computed watermark for tid %d", Thread::current()->osthread()->thread_id());
90
  return stack_watermark;
91
}
92

93
void SafepointMechanism::update_poll_values(JavaThread* thread) {
94
  assert(thread == Thread::current(), "Must be");
95
  assert(thread->thread_state() != _thread_blocked, "Must not be");
96
  assert(thread->thread_state() != _thread_in_native, "Must not be");
97

98
  for (;;) {
99
    bool armed = global_poll() || thread->handshake_state()->has_operation();
100
    uintptr_t stack_watermark = StackWatermarkSet::lowest_watermark(thread);
101
    uintptr_t poll_page = armed ? _poll_page_armed_value
102
                                : _poll_page_disarmed_value;
103
    uintptr_t poll_word = compute_poll_word(armed, stack_watermark);
104
    uintptr_t prev_poll_word = thread->poll_data()->get_polling_word();
105

106
    if (prev_poll_word != poll_word ||
107
        prev_poll_word == _poll_word_armed_value) {
108
      // While updating the poll value, we allow entering new nmethods
109
      // through stack unwinding. The nmethods might have been processed in
110
      // a concurrent thread by the GC. So we need to run a cross modify
111
      // fence to ensure patching becomes visible. We may also wake up from
112
      // a safepoint that has patched code. This cross modify fence will
113
      // ensure such paths can observe patched code.
114
      // Note that while other threads may arm the thread-local poll of
115
      // a thread, only the thread itself has permission to disarm its own
116
      // poll value, in any way making it less restrictive. Therefore, whenever
117
      // the frontier of what the mutator allows itself to do is increased,
118
      // we will catch that here, and ensure a cross modifying fence is used.
119
      OrderAccess::cross_modify_fence();
120
    }
121

122
    thread->poll_data()->set_polling_page(poll_page);
123
    thread->poll_data()->set_polling_word(poll_word);
124
    OrderAccess::fence();
125
    if (!armed && (global_poll() || thread->handshake_state()->has_operation())) {
126
      // We disarmed an old safepoint, but a new one is synchronizing.
127
      // We need to arm the poll for the subsequent safepoint poll.
128
      continue;
129
    }
130
    break;
131
  }
132
}
133

134
void SafepointMechanism::process(JavaThread *thread, bool allow_suspend, bool check_async_exception) {
135
  DEBUG_ONLY(intptr_t* sp_before = thread->last_Java_sp();)
136
  // Read global poll and has_handshake after local poll
137
  OrderAccess::loadload();
138

139
  // local poll already checked, if used.
140
  bool need_rechecking;
141
  do {
142
    JavaThreadState state = thread->thread_state();
143
    guarantee(state == _thread_in_vm, "Illegal threadstate encountered: %d", state);
144
    if (global_poll()) {
145
      // Any load in ::block() must not pass the global poll load.
146
      // Otherwise we might load an old safepoint counter (for example).
147
      OrderAccess::loadload();
148
      SafepointSynchronize::block(thread);
149
    }
150

151
    // The call to on_safepoint fixes the thread's oops and the first few frames.
152
    //
153
    // The call has been carefully placed here to cater to a few situations:
154
    // 1) After we exit from block after a global poll
155
    // 2) After a thread races with the disarming of the global poll and transitions from native/blocked
156
    // 3) Before the handshake code is run
157
    StackWatermarkSet::on_safepoint(thread);
158

159
    need_rechecking = thread->handshake_state()->has_operation() && thread->handshake_state()->process_by_self(allow_suspend, check_async_exception);
160
  } while (need_rechecking);
161

162
  update_poll_values(thread);
163
  assert(sp_before == thread->last_Java_sp(), "Anchor has changed");
164
}
165

166
void SafepointMechanism::initialize_header(JavaThread* thread) {
167
  disarm_local_poll(thread);
168
}
169

170
void SafepointMechanism::initialize() {
171
  pd_initialize();
172
}
173

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

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

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

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