8335362: [Windows] Stack pointer increment in _cont_thaw stub can cause program to terminate with exit code 0xc0000005
Reviewed-by: dholmes, fparain
This commit is contained in:
parent
237a540f01
commit
591aa7c5c7
src/hotspot
test/jdk/java/lang/Thread/virtual
@ -49,12 +49,17 @@ inline void os::map_stack_shadow_pages(address sp) {
|
||||
// If we decrement stack pointer more than one page
|
||||
// the OS may not map an intervening page into our space
|
||||
// and may fault on a memory access to interior of our frame.
|
||||
address original_sp = sp;
|
||||
const size_t page_size = os::vm_page_size();
|
||||
const size_t n_pages = StackOverflow::stack_shadow_zone_size() / page_size;
|
||||
for (size_t pages = 1; pages <= n_pages; pages++) {
|
||||
sp -= page_size;
|
||||
*sp = 0;
|
||||
}
|
||||
StackOverflow* state = JavaThread::current()->stack_overflow_state();
|
||||
assert(original_sp > state->shadow_zone_safe_limit(), "original_sp=" INTPTR_FORMAT ", "
|
||||
"shadow_zone_safe_limit=" INTPTR_FORMAT, p2i(original_sp), p2i(state->shadow_zone_safe_limit()));
|
||||
state->set_shadow_zone_growth_watermark(original_sp);
|
||||
}
|
||||
|
||||
inline bool os::numa_has_group_homing() { return false; }
|
||||
|
@ -277,12 +277,31 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _WINDOWS
|
||||
static void map_stack_pages(JavaThread* thread, size_t size, address sp) {
|
||||
address new_sp = sp - size;
|
||||
address watermark = thread->stack_overflow_state()->shadow_zone_growth_watermark();
|
||||
|
||||
if (new_sp < watermark) {
|
||||
size_t page_size = os::vm_page_size();
|
||||
address last_touched_page = watermark - StackOverflow::stack_shadow_zone_size();
|
||||
size_t pages_to_touch = align_up(watermark - new_sp, page_size) / page_size;
|
||||
while (pages_to_touch-- > 0) {
|
||||
last_touched_page -= page_size;
|
||||
*last_touched_page = 0;
|
||||
}
|
||||
thread->stack_overflow_state()->set_shadow_zone_growth_watermark(new_sp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool stack_overflow_check(JavaThread* thread, size_t size, address sp) {
|
||||
const size_t page_size = os::vm_page_size();
|
||||
if (size > page_size) {
|
||||
if (sp - size < thread->stack_overflow_state()->shadow_zone_safe_limit()) {
|
||||
return false;
|
||||
}
|
||||
WINDOWS_ONLY(map_stack_pages(thread, size, sp));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -293,6 +293,16 @@ class StackOverflow {
|
||||
return _shadow_zone_safe_limit;
|
||||
}
|
||||
|
||||
address shadow_zone_growth_watermark() const {
|
||||
assert(_shadow_zone_growth_watermark != nullptr, "Don't call this before the field is initialized.");
|
||||
return _shadow_zone_growth_watermark;
|
||||
}
|
||||
|
||||
void set_shadow_zone_growth_watermark(address new_watermark) {
|
||||
assert(_shadow_zone_growth_watermark != nullptr, "Don't call this before the field is initialized.");
|
||||
_shadow_zone_growth_watermark = new_watermark;
|
||||
}
|
||||
|
||||
void create_stack_guard_pages();
|
||||
void remove_stack_guard_pages();
|
||||
|
||||
|
96
test/jdk/java/lang/Thread/virtual/BigStackChunk.java
Normal file
96
test/jdk/java/lang/Thread/virtual/BigStackChunk.java
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=default
|
||||
* @bug 8335362
|
||||
* @summary Test virtual thread usage with big stackChunks
|
||||
* @requires vm.continuations
|
||||
* @run junit/othervm BigStackChunk
|
||||
*/
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class BigStackChunk {
|
||||
|
||||
void recurse(int cnt, ReentrantLock rlock) {
|
||||
int i1 = cnt;
|
||||
int i2 = i1 + 1;
|
||||
int i3 = i2 + 1;
|
||||
int i4 = i3 + 1;
|
||||
int i5 = i4 + 1;
|
||||
int i6 = i5 + 1;
|
||||
int i7 = i6 + 1;
|
||||
long ll = 2 * (long)i1;
|
||||
float ff = ll + 1.2f;
|
||||
double dd = ff + 1.3D;
|
||||
|
||||
if (cnt > 0) {
|
||||
recurse(cnt - 1, rlock);
|
||||
} else {
|
||||
rlock.lock();
|
||||
rlock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void bigStackChunkTest() throws Exception {
|
||||
int VTHREAD_CNT = Runtime.getRuntime().availableProcessors();
|
||||
ReentrantLock rlock = new ReentrantLock();
|
||||
Thread[] vthreads = new Thread[VTHREAD_CNT];
|
||||
|
||||
rlock.lock();
|
||||
for (int i = 0; i < VTHREAD_CNT; i++) {
|
||||
vthreads[i] = Thread.ofVirtual().start(() -> {
|
||||
// Set up things so that half of the carriers will commit lots of
|
||||
// pages in the stack while running the mounted vthread and half
|
||||
// will just commit very few ones.
|
||||
if (Math.random() < 0.5) {
|
||||
recurse(300, rlock);
|
||||
} else {
|
||||
recurse(1, rlock);
|
||||
}
|
||||
});
|
||||
}
|
||||
await(vthreads[0], Thread.State.WAITING);
|
||||
// Now we expect that some vthread that recursed a lot is mounted on
|
||||
// a carrier that previously run a vthread that didn't recurse at all.
|
||||
rlock.unlock();
|
||||
|
||||
for (int i = 0; i < VTHREAD_CNT; i++) {
|
||||
vthreads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
private void await(Thread thread, Thread.State expectedState) throws InterruptedException {
|
||||
Thread.State state = thread.getState();
|
||||
while (state != expectedState) {
|
||||
assertTrue(state != Thread.State.TERMINATED, "Thread has terminated");
|
||||
Thread.sleep(10);
|
||||
state = thread.getState();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user