576 //
577 // There are two ways to expand thread stack to address "bottom", we used
578 // both of them in JVM before 1.5:
579 // 1. adjust stack pointer first so that it is below "bottom", and then
580 // touch "bottom"
581 // 2. mmap() the page in question
582 //
583 // Now alternate signal stack is gone, it's harder to use 2. For instance,
584 // if current sp is already near the lower end of page 101, and we need to
585 // call mmap() to map page 100, it is possible that part of the mmap() frame
586 // will be placed in page 100. When page 100 is mapped, it is zero-filled.
587 // That will destroy the mmap() frame and cause VM to crash.
588 //
589 // The following code works by adjusting sp first, then accessing the "bottom"
590 // page to force a page fault. Linux kernel will then automatically expand the
591 // stack mapping.
592 //
593 // _expand_stack_to() assumes its frame size is less than page size, which
594 // should always be true if the function is not inlined.
595
596 #if __GNUC__ < 3 // gcc 2.x does not support noinline attribute
597 #define NOINLINE
598 #else
599 #define NOINLINE __attribute__ ((noinline))
600 #endif
601
602 static void _expand_stack_to(address bottom) NOINLINE;
603
604 static void _expand_stack_to(address bottom) {
605 address sp;
606 size_t size;
607 volatile char *p;
608
609 // Adjust bottom to point to the largest address within the same page, it
610 // gives us a one-page buffer if alloca() allocates slightly more memory.
611 bottom = (address)align_size_down((uintptr_t)bottom, os::Linux::page_size());
612 bottom += os::Linux::page_size() - 1;
613
614 // sp might be slightly above current stack pointer; if that's the case, we
615 // will alloca() a little more space than necessary, which is OK. Don't use
616 // os::current_stack_pointer(), as its result can be slightly below current
617 // stack pointer, causing us to not alloca enough to reach "bottom".
618 sp = (address)&sp;
619
620 if (sp > bottom) {
621 size = sp - bottom;
622 p = (volatile char *)alloca(size);
623 assert(p != NULL && p <= (volatile char *)bottom, "alloca problem?");
624 p[0] = '\0';
|
576 //
577 // There are two ways to expand thread stack to address "bottom", we used
578 // both of them in JVM before 1.5:
579 // 1. adjust stack pointer first so that it is below "bottom", and then
580 // touch "bottom"
581 // 2. mmap() the page in question
582 //
583 // Now alternate signal stack is gone, it's harder to use 2. For instance,
584 // if current sp is already near the lower end of page 101, and we need to
585 // call mmap() to map page 100, it is possible that part of the mmap() frame
586 // will be placed in page 100. When page 100 is mapped, it is zero-filled.
587 // That will destroy the mmap() frame and cause VM to crash.
588 //
589 // The following code works by adjusting sp first, then accessing the "bottom"
590 // page to force a page fault. Linux kernel will then automatically expand the
591 // stack mapping.
592 //
593 // _expand_stack_to() assumes its frame size is less than page size, which
594 // should always be true if the function is not inlined.
595
596 static void NOINLINE _expand_stack_to(address bottom) {
597 address sp;
598 size_t size;
599 volatile char *p;
600
601 // Adjust bottom to point to the largest address within the same page, it
602 // gives us a one-page buffer if alloca() allocates slightly more memory.
603 bottom = (address)align_size_down((uintptr_t)bottom, os::Linux::page_size());
604 bottom += os::Linux::page_size() - 1;
605
606 // sp might be slightly above current stack pointer; if that's the case, we
607 // will alloca() a little more space than necessary, which is OK. Don't use
608 // os::current_stack_pointer(), as its result can be slightly below current
609 // stack pointer, causing us to not alloca enough to reach "bottom".
610 sp = (address)&sp;
611
612 if (sp > bottom) {
613 size = sp - bottom;
614 p = (volatile char *)alloca(size);
615 assert(p != NULL && p <= (volatile char *)bottom, "alloca problem?");
616 p[0] = '\0';
|