717 };
718
719 #endif // !PRODUCT
720
721 // Support for showing register content on asserts/guarantees.
722 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
723
724 static ucontext_t g_stored_assertion_context;
725
726 void initialize_assert_poison() {
727 char* page = os::reserve_memory(os::vm_page_size());
728 if (page) {
729 MemTracker::record_virtual_memory_type(page, mtInternal);
730 if (os::commit_memory(page, os::vm_page_size(), false) &&
731 os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) {
732 g_assert_poison = page;
733 }
734 }
735 }
736
737 static void store_context(const void* context) {
738 memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t));
739 #if defined(__linux) && defined(PPC64)
740 // on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up
741 // after copying the context (see comment in sys/ucontext.h):
742 *((void**) &g_stored_assertion_context.uc_mcontext.regs) = &(g_stored_assertion_context.uc_mcontext.gp_regs);
743 #endif
744 }
745
746 bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) {
747 if (faulting_address == g_assert_poison) {
748 // Disarm poison page.
749 os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX);
750 // Store Context away.
751 if (ucVoid) {
752 const intx my_tid = os::current_thread_id();
753 if (Atomic::cmpxchg(my_tid, &g_asserting_thread, (intx)0) == 0) {
754 store_context(ucVoid);
755 g_assertion_context = &g_stored_assertion_context;
756 }
757 }
758 return true;
759 }
760 return false;
761 }
762 #endif // CAN_SHOW_REGISTERS_ON_ASSERT
763
|
717 };
718
719 #endif // !PRODUCT
720
721 // Support for showing register content on asserts/guarantees.
722 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
723
724 static ucontext_t g_stored_assertion_context;
725
726 void initialize_assert_poison() {
727 char* page = os::reserve_memory(os::vm_page_size());
728 if (page) {
729 MemTracker::record_virtual_memory_type(page, mtInternal);
730 if (os::commit_memory(page, os::vm_page_size(), false) &&
731 os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) {
732 g_assert_poison = page;
733 }
734 }
735 }
736
737 void disarm_assert_poison() {
738 g_assert_poison = &g_dummy;
739 }
740
741 static void store_context(const void* context) {
742 memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t));
743 #if defined(__linux) && defined(PPC64)
744 // on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up
745 // after copying the context (see comment in sys/ucontext.h):
746 *((void**) &g_stored_assertion_context.uc_mcontext.regs) = &(g_stored_assertion_context.uc_mcontext.gp_regs);
747 #endif
748 }
749
750 bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) {
751 if (faulting_address == g_assert_poison) {
752 // Disarm poison page.
753 if (os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX) == false) {
754 #ifdef ASSERT
755 fprintf(stderr, "Assertion poison page cannot be unprotected - mprotect failed with %d (%s)",
756 errno, os::strerror(errno));
757 fflush(stderr);
758 #endif
759 return false; // unprotecting memory may fail in OOM situations, as surprising as this sounds.
760 }
761 // Store Context away.
762 if (ucVoid) {
763 const intx my_tid = os::current_thread_id();
764 if (Atomic::cmpxchg(my_tid, &g_asserting_thread, (intx)0) == 0) {
765 store_context(ucVoid);
766 g_assertion_context = &g_stored_assertion_context;
767 }
768 }
769 return true;
770 }
771 return false;
772 }
773 #endif // CAN_SHOW_REGISTERS_ON_ASSERT
774
|