annotate src/os_cpu/linux_x86/vm/os_linux_x86.cpp @ 2030:fb712ff22571

7000559: G1: assertion failure !outer || (full_collections_started == _full_collections_completed + 1) Summary: The concurrent marking thread can complete its operation and increment the full GC counter during a Full GC. This causes the nesting of increments to the start and end of Full GCs that we are expecting to be wrong. the fix is for the marking thread to join the suspendible thread set before incrementing the counter so that it's blocked until the Full GC (or any other safepoint) is finished. The change also includes some minor code cleanup (I renamed a parameter). Reviewed-by: brutisso, ysr
author tonyp
date Tue, 14 Dec 2010 16:19:44 -0500
parents 828eafbd85cc
children 06f017f7daa7 d70fe6ab4436
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1907
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1490
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1490
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1490
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
25 // no precompiled headers
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
26 #include "assembler_x86.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
27 #include "classfile/classLoader.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
28 #include "classfile/systemDictionary.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
29 #include "classfile/vmSymbols.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
30 #include "code/icBuffer.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
31 #include "code/vtableStubs.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
32 #include "interpreter/interpreter.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
33 #include "jvm_linux.h"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
34 #include "memory/allocation.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
35 #include "mutex_linux.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
36 #include "nativeInst_x86.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
37 #include "os_share_linux.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
38 #include "prims/jniFastGetField.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
39 #include "prims/jvm.h"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
40 #include "prims/jvm_misc.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
41 #include "runtime/arguments.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
42 #include "runtime/extendedPC.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
43 #include "runtime/frame.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
44 #include "runtime/interfaceSupport.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
45 #include "runtime/java.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
46 #include "runtime/javaCalls.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
47 #include "runtime/mutexLocker.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
48 #include "runtime/osThread.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
49 #include "runtime/sharedRuntime.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
50 #include "runtime/stubRoutines.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
51 #include "runtime/timer.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
52 #include "thread_linux.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
53 #include "utilities/events.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
54 #include "utilities/vmError.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
55 #ifdef COMPILER1
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
56 #include "c1/c1_Runtime1.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
57 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
58 #ifdef COMPILER2
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
59 #include "opto/runtime.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1907
diff changeset
60 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // put OS-includes here
a61af66fc99e Initial load
duke
parents:
diff changeset
63 # include <sys/types.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
64 # include <sys/mman.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
65 # include <pthread.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
66 # include <signal.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
67 # include <errno.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
68 # include <dlfcn.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
69 # include <stdlib.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
70 # include <stdio.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
71 # include <unistd.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
72 # include <sys/resource.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
73 # include <pthread.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
74 # include <sys/stat.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
75 # include <sys/time.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
76 # include <sys/utsname.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
77 # include <sys/socket.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
78 # include <sys/wait.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
79 # include <pwd.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
80 # include <poll.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
81 # include <ucontext.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
82 # include <fpu_control.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
85 #define REG_SP REG_RSP
a61af66fc99e Initial load
duke
parents:
diff changeset
86 #define REG_PC REG_RIP
a61af66fc99e Initial load
duke
parents:
diff changeset
87 #define REG_FP REG_RBP
a61af66fc99e Initial load
duke
parents:
diff changeset
88 #define SPELL_REG_SP "rsp"
a61af66fc99e Initial load
duke
parents:
diff changeset
89 #define SPELL_REG_FP "rbp"
a61af66fc99e Initial load
duke
parents:
diff changeset
90 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
91 #define REG_SP REG_UESP
a61af66fc99e Initial load
duke
parents:
diff changeset
92 #define REG_PC REG_EIP
a61af66fc99e Initial load
duke
parents:
diff changeset
93 #define REG_FP REG_EBP
a61af66fc99e Initial load
duke
parents:
diff changeset
94 #define SPELL_REG_SP "esp"
a61af66fc99e Initial load
duke
parents:
diff changeset
95 #define SPELL_REG_FP "ebp"
a61af66fc99e Initial load
duke
parents:
diff changeset
96 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
97
a61af66fc99e Initial load
duke
parents:
diff changeset
98 address os::current_stack_pointer() {
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
99 #ifdef SPARC_WORKS
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
100 register void *esp;
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
101 __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp));
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
102 return (address) ((char*)esp + sizeof(long)*2);
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
103 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
104 register void *esp __asm__ (SPELL_REG_SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
105 return (address) esp;
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
106 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
108
a61af66fc99e Initial load
duke
parents:
diff changeset
109 char* os::non_memory_address_word() {
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // Must never look like an address returned by reserve_memory,
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // even in its subfields (as defined by the CPU immediate fields,
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // if the CPU splits constants across multiple instructions).
a61af66fc99e Initial load
duke
parents:
diff changeset
113
a61af66fc99e Initial load
duke
parents:
diff changeset
114 return (char*) -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116
a61af66fc99e Initial load
duke
parents:
diff changeset
117 void os::initialize_thread() {
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // Nothing to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
119 }
a61af66fc99e Initial load
duke
parents:
diff changeset
120
a61af66fc99e Initial load
duke
parents:
diff changeset
121 address os::Linux::ucontext_get_pc(ucontext_t * uc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
122 return (address)uc->uc_mcontext.gregs[REG_PC];
a61af66fc99e Initial load
duke
parents:
diff changeset
123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
124
a61af66fc99e Initial load
duke
parents:
diff changeset
125 intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
a61af66fc99e Initial load
duke
parents:
diff changeset
127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
128
a61af66fc99e Initial load
duke
parents:
diff changeset
129 intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
a61af66fc99e Initial load
duke
parents:
diff changeset
131 }
a61af66fc99e Initial load
duke
parents:
diff changeset
132
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // For Forte Analyzer AsyncGetCallTrace profiling support - thread
a61af66fc99e Initial load
duke
parents:
diff changeset
134 // is currently interrupted by SIGPROF.
a61af66fc99e Initial load
duke
parents:
diff changeset
135 // os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal
a61af66fc99e Initial load
duke
parents:
diff changeset
136 // frames. Currently we don't do that on Linux, so it's the same as
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // os::fetch_frame_from_context().
a61af66fc99e Initial load
duke
parents:
diff changeset
138 ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread,
a61af66fc99e Initial load
duke
parents:
diff changeset
139 ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
140
a61af66fc99e Initial load
duke
parents:
diff changeset
141 assert(thread != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
142 assert(ret_sp != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
143 assert(ret_fp != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 return os::fetch_frame_from_context(uc, ret_sp, ret_fp);
a61af66fc99e Initial load
duke
parents:
diff changeset
146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 ExtendedPC os::fetch_frame_from_context(void* ucVoid,
a61af66fc99e Initial load
duke
parents:
diff changeset
149 intptr_t** ret_sp, intptr_t** ret_fp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
150
a61af66fc99e Initial load
duke
parents:
diff changeset
151 ExtendedPC epc;
a61af66fc99e Initial load
duke
parents:
diff changeset
152 ucontext_t* uc = (ucontext_t*)ucVoid;
a61af66fc99e Initial load
duke
parents:
diff changeset
153
a61af66fc99e Initial load
duke
parents:
diff changeset
154 if (uc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
155 epc = ExtendedPC(os::Linux::ucontext_get_pc(uc));
a61af66fc99e Initial load
duke
parents:
diff changeset
156 if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
157 if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
158 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // construct empty ExtendedPC for return value checking
a61af66fc99e Initial load
duke
parents:
diff changeset
160 epc = ExtendedPC(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
161 if (ret_sp) *ret_sp = (intptr_t *)NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
162 if (ret_fp) *ret_fp = (intptr_t *)NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
164
a61af66fc99e Initial load
duke
parents:
diff changeset
165 return epc;
a61af66fc99e Initial load
duke
parents:
diff changeset
166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
167
a61af66fc99e Initial load
duke
parents:
diff changeset
168 frame os::fetch_frame_from_context(void* ucVoid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
169 intptr_t* sp;
a61af66fc99e Initial load
duke
parents:
diff changeset
170 intptr_t* fp;
a61af66fc99e Initial load
duke
parents:
diff changeset
171 ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
a61af66fc99e Initial load
duke
parents:
diff changeset
172 return frame(sp, fp, epc.pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
173 }
a61af66fc99e Initial load
duke
parents:
diff changeset
174
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // By default, gcc always save frame pointer (%ebp/%rbp) on stack. It may get
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // turned off by -fomit-frame-pointer,
a61af66fc99e Initial load
duke
parents:
diff changeset
177 frame os::get_sender_for_C_frame(frame* fr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
178 return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
179 }
a61af66fc99e Initial load
duke
parents:
diff changeset
180
a61af66fc99e Initial load
duke
parents:
diff changeset
181 intptr_t* _get_previous_fp() {
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
182 #ifdef SPARC_WORKS
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
183 register intptr_t **ebp;
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
184 __asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp));
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
185 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
186 register intptr_t **ebp __asm__ (SPELL_REG_FP);
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
187 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
188 return (intptr_t*) *ebp; // we want what it points to.
a61af66fc99e Initial load
duke
parents:
diff changeset
189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
190
a61af66fc99e Initial load
duke
parents:
diff changeset
191
a61af66fc99e Initial load
duke
parents:
diff changeset
192 frame os::current_frame() {
a61af66fc99e Initial load
duke
parents:
diff changeset
193 intptr_t* fp = _get_previous_fp();
a61af66fc99e Initial load
duke
parents:
diff changeset
194 frame myframe((intptr_t*)os::current_stack_pointer(),
a61af66fc99e Initial load
duke
parents:
diff changeset
195 (intptr_t*)fp,
a61af66fc99e Initial load
duke
parents:
diff changeset
196 CAST_FROM_FN_PTR(address, os::current_frame));
a61af66fc99e Initial load
duke
parents:
diff changeset
197 if (os::is_first_C_frame(&myframe)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // stack is not walkable
a61af66fc99e Initial load
duke
parents:
diff changeset
199 return frame(NULL, NULL, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
200 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
201 return os::get_sender_for_C_frame(&myframe);
a61af66fc99e Initial load
duke
parents:
diff changeset
202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 // Utility functions
a61af66fc99e Initial load
duke
parents:
diff changeset
206
a61af66fc99e Initial load
duke
parents:
diff changeset
207 // From IA32 System Programming Guide
a61af66fc99e Initial load
duke
parents:
diff changeset
208 enum {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 trap_page_fault = 0xE
a61af66fc99e Initial load
duke
parents:
diff changeset
210 };
a61af66fc99e Initial load
duke
parents:
diff changeset
211
a61af66fc99e Initial load
duke
parents:
diff changeset
212 extern "C" void Fetch32PFI () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
213 extern "C" void Fetch32Resume () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
214 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
215 extern "C" void FetchNPFI () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
216 extern "C" void FetchNResume () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
217 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
218
a61af66fc99e Initial load
duke
parents:
diff changeset
219 extern "C" int
a61af66fc99e Initial load
duke
parents:
diff changeset
220 JVM_handle_linux_signal(int sig,
a61af66fc99e Initial load
duke
parents:
diff changeset
221 siginfo_t* info,
a61af66fc99e Initial load
duke
parents:
diff changeset
222 void* ucVoid,
a61af66fc99e Initial load
duke
parents:
diff changeset
223 int abort_if_unrecognized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
224 ucontext_t* uc = (ucontext_t*) ucVoid;
a61af66fc99e Initial load
duke
parents:
diff changeset
225
a61af66fc99e Initial load
duke
parents:
diff changeset
226 Thread* t = ThreadLocalStorage::get_thread_slow();
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 SignalHandlerMark shm(t);
a61af66fc99e Initial load
duke
parents:
diff changeset
229
a61af66fc99e Initial load
duke
parents:
diff changeset
230 // Note: it's not uncommon that JNI code uses signal/sigset to install
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // then restore certain signal handler (e.g. to temporarily block SIGPIPE,
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // or have a SIGILL handler when detecting CPU type). When that happens,
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // avoid unnecessary crash when libjsig is not preloaded, try handle signals
a61af66fc99e Initial load
duke
parents:
diff changeset
235 // that do not require siginfo/ucontext first.
a61af66fc99e Initial load
duke
parents:
diff changeset
236
a61af66fc99e Initial load
duke
parents:
diff changeset
237 if (sig == SIGPIPE || sig == SIGXFSZ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // allow chained handler to go first
a61af66fc99e Initial load
duke
parents:
diff changeset
239 if (os::Linux::chained_handler(sig, info, ucVoid)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
240 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
241 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
242 if (PrintMiscellaneous && (WizardMode || Verbose)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
243 char buf[64];
a61af66fc99e Initial load
duke
parents:
diff changeset
244 warning("Ignoring %s - see bugs 4229104 or 646499219",
a61af66fc99e Initial load
duke
parents:
diff changeset
245 os::exception_name(sig, buf, sizeof(buf)));
a61af66fc99e Initial load
duke
parents:
diff changeset
246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
247 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
248 }
a61af66fc99e Initial load
duke
parents:
diff changeset
249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
250
a61af66fc99e Initial load
duke
parents:
diff changeset
251 JavaThread* thread = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
252 VMThread* vmthread = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
253 if (os::Linux::signal_handlers_are_installed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
254 if (t != NULL ){
a61af66fc99e Initial load
duke
parents:
diff changeset
255 if(t->is_Java_thread()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
256 thread = (JavaThread*)t;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
258 else if(t->is_VM_thread()){
a61af66fc99e Initial load
duke
parents:
diff changeset
259 vmthread = (VMThread *)t;
a61af66fc99e Initial load
duke
parents:
diff changeset
260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
263 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
264 NOTE: does not seem to work on linux.
a61af66fc99e Initial load
duke
parents:
diff changeset
265 if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
a61af66fc99e Initial load
duke
parents:
diff changeset
266 // can't decode this kind of signal
a61af66fc99e Initial load
duke
parents:
diff changeset
267 info = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
268 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
269 assert(sig == info->si_signo, "bad siginfo");
a61af66fc99e Initial load
duke
parents:
diff changeset
270 }
a61af66fc99e Initial load
duke
parents:
diff changeset
271 */
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // decide if this trap can be handled by a stub
a61af66fc99e Initial load
duke
parents:
diff changeset
273 address stub = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 address pc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
276
a61af66fc99e Initial load
duke
parents:
diff changeset
277 //%note os_trap_1
a61af66fc99e Initial load
duke
parents:
diff changeset
278 if (info != NULL && uc != NULL && thread != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
279 pc = (address) os::Linux::ucontext_get_pc(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
280
a61af66fc99e Initial load
duke
parents:
diff changeset
281 if (pc == (address) Fetch32PFI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
282 uc->uc_mcontext.gregs[REG_PC] = intptr_t(Fetch32Resume) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
283 return 1 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
284 }
a61af66fc99e Initial load
duke
parents:
diff changeset
285 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
286 if (pc == (address) FetchNPFI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
287 uc->uc_mcontext.gregs[REG_PC] = intptr_t (FetchNResume) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
288 return 1 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
289 }
a61af66fc99e Initial load
duke
parents:
diff changeset
290 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 // Handle ALL stack overflow variations here
a61af66fc99e Initial load
duke
parents:
diff changeset
293 if (sig == SIGSEGV) {
a61af66fc99e Initial load
duke
parents:
diff changeset
294 address addr = (address) info->si_addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
295
a61af66fc99e Initial load
duke
parents:
diff changeset
296 // check if fault address is within thread stack
a61af66fc99e Initial load
duke
parents:
diff changeset
297 if (addr < thread->stack_base() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
298 addr >= thread->stack_base() - thread->stack_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // stack overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
300 if (thread->in_stack_yellow_zone(addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
301 thread->disable_stack_yellow_zone();
a61af66fc99e Initial load
duke
parents:
diff changeset
302 if (thread->thread_state() == _thread_in_Java) {
a61af66fc99e Initial load
duke
parents:
diff changeset
303 // Throw a stack overflow exception. Guard pages will be reenabled
a61af66fc99e Initial load
duke
parents:
diff changeset
304 // while unwinding the stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
305 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
a61af66fc99e Initial load
duke
parents:
diff changeset
306 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // Thread was in the vm or native code. Return and try to finish.
a61af66fc99e Initial load
duke
parents:
diff changeset
308 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
309 }
a61af66fc99e Initial load
duke
parents:
diff changeset
310 } else if (thread->in_stack_red_zone(addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
311 // Fatal red zone violation. Disable the guard pages and fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
312 // to handle_unexpected_exception way down below.
a61af66fc99e Initial load
duke
parents:
diff changeset
313 thread->disable_stack_red_zone();
a61af66fc99e Initial load
duke
parents:
diff changeset
314 tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
a61af66fc99e Initial load
duke
parents:
diff changeset
315 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // Accessing stack address below sp may cause SEGV if current
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // thread has MAP_GROWSDOWN stack. This should only happen when
a61af66fc99e Initial load
duke
parents:
diff changeset
318 // current thread was created by user code with MAP_GROWSDOWN flag
a61af66fc99e Initial load
duke
parents:
diff changeset
319 // and then attached to VM. See notes in os_linux.cpp.
a61af66fc99e Initial load
duke
parents:
diff changeset
320 if (thread->osthread()->expanding_stack() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
321 thread->osthread()->set_expanding_stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
322 if (os::Linux::manually_expand_stack(thread, addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
323 thread->osthread()->clear_expanding_stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
324 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
325 }
a61af66fc99e Initial load
duke
parents:
diff changeset
326 thread->osthread()->clear_expanding_stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
327 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
328 fatal("recursive segv. expanding stack.");
a61af66fc99e Initial load
duke
parents:
diff changeset
329 }
a61af66fc99e Initial load
duke
parents:
diff changeset
330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
331 }
a61af66fc99e Initial load
duke
parents:
diff changeset
332 }
a61af66fc99e Initial load
duke
parents:
diff changeset
333
a61af66fc99e Initial load
duke
parents:
diff changeset
334 if (thread->thread_state() == _thread_in_Java) {
a61af66fc99e Initial load
duke
parents:
diff changeset
335 // Java thread running in Java code => find exception handler if any
a61af66fc99e Initial load
duke
parents:
diff changeset
336 // a fault inside compiled code, the interpreter, or a stub
a61af66fc99e Initial load
duke
parents:
diff changeset
337
a61af66fc99e Initial load
duke
parents:
diff changeset
338 if (sig == SIGSEGV && os::is_poll_address((address)info->si_addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
339 stub = SharedRuntime::get_poll_stub(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
340 } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // BugId 4454115: A read from a MappedByteBuffer can fault
a61af66fc99e Initial load
duke
parents:
diff changeset
342 // here if the underlying file has been truncated.
a61af66fc99e Initial load
duke
parents:
diff changeset
343 // Do not crash the VM in such a case.
a61af66fc99e Initial load
duke
parents:
diff changeset
344 CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
345 nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
346 if (nm != NULL && nm->has_unsafe_access()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
347 stub = StubRoutines::handler_for_unsafe_access();
a61af66fc99e Initial load
duke
parents:
diff changeset
348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
349 }
a61af66fc99e Initial load
duke
parents:
diff changeset
350 else
a61af66fc99e Initial load
duke
parents:
diff changeset
351
a61af66fc99e Initial load
duke
parents:
diff changeset
352 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
353 if (sig == SIGFPE &&
a61af66fc99e Initial load
duke
parents:
diff changeset
354 (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
355 stub =
a61af66fc99e Initial load
duke
parents:
diff changeset
356 SharedRuntime::
a61af66fc99e Initial load
duke
parents:
diff changeset
357 continuation_for_implicit_exception(thread,
a61af66fc99e Initial load
duke
parents:
diff changeset
358 pc,
a61af66fc99e Initial load
duke
parents:
diff changeset
359 SharedRuntime::
a61af66fc99e Initial load
duke
parents:
diff changeset
360 IMPLICIT_DIVIDE_BY_ZERO);
a61af66fc99e Initial load
duke
parents:
diff changeset
361 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
362 if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) {
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // HACK: si_code does not work on linux 2.2.12-20!!!
a61af66fc99e Initial load
duke
parents:
diff changeset
364 int op = pc[0];
a61af66fc99e Initial load
duke
parents:
diff changeset
365 if (op == 0xDB) {
a61af66fc99e Initial load
duke
parents:
diff changeset
366 // FIST
a61af66fc99e Initial load
duke
parents:
diff changeset
367 // TODO: The encoding of D2I in i486.ad can cause an exception
a61af66fc99e Initial load
duke
parents:
diff changeset
368 // prior to the fist instruction if there was an invalid operation
a61af66fc99e Initial load
duke
parents:
diff changeset
369 // pending. We want to dismiss that exception. From the win_32
a61af66fc99e Initial load
duke
parents:
diff changeset
370 // side it also seems that if it really was the fist causing
a61af66fc99e Initial load
duke
parents:
diff changeset
371 // the exception that we do the d2i by hand with different
a61af66fc99e Initial load
duke
parents:
diff changeset
372 // rounding. Seems kind of weird.
a61af66fc99e Initial load
duke
parents:
diff changeset
373 // NOTE: that we take the exception at the NEXT floating point instruction.
a61af66fc99e Initial load
duke
parents:
diff changeset
374 assert(pc[0] == 0xDB, "not a FIST opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
375 assert(pc[1] == 0x14, "not a FIST opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
376 assert(pc[2] == 0x24, "not a FIST opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
377 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
378 } else if (op == 0xF7) {
a61af66fc99e Initial load
duke
parents:
diff changeset
379 // IDIV
a61af66fc99e Initial load
duke
parents:
diff changeset
380 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
a61af66fc99e Initial load
duke
parents:
diff changeset
381 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
382 // TODO: handle more cases if we are using other x86 instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
383 // that can generate SIGFPE signal on linux.
a61af66fc99e Initial load
duke
parents:
diff changeset
384 tty->print_cr("unknown opcode 0x%X with SIGFPE.", op);
a61af66fc99e Initial load
duke
parents:
diff changeset
385 fatal("please update this code.");
a61af66fc99e Initial load
duke
parents:
diff changeset
386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
387 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
388 } else if (sig == SIGSEGV &&
a61af66fc99e Initial load
duke
parents:
diff changeset
389 !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
390 // Determination of interpreter/vtable stub/compiled code null exception
a61af66fc99e Initial load
duke
parents:
diff changeset
391 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
393 } else if (thread->thread_state() == _thread_in_vm &&
a61af66fc99e Initial load
duke
parents:
diff changeset
394 sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
a61af66fc99e Initial load
duke
parents:
diff changeset
395 thread->doing_unsafe_access()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
396 stub = StubRoutines::handler_for_unsafe_access();
a61af66fc99e Initial load
duke
parents:
diff changeset
397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
398
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // and the heap gets shrunk before the field access.
a61af66fc99e Initial load
duke
parents:
diff changeset
401 if ((sig == SIGSEGV) || (sig == SIGBUS)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
402 address addr = JNI_FastGetField::find_slowcase_pc(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
403 if (addr != (address)-1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
404 stub = addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
405 }
a61af66fc99e Initial load
duke
parents:
diff changeset
406 }
a61af66fc99e Initial load
duke
parents:
diff changeset
407
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // Check to see if we caught the safepoint code in the
a61af66fc99e Initial load
duke
parents:
diff changeset
409 // process of write protecting the memory serialization page.
a61af66fc99e Initial load
duke
parents:
diff changeset
410 // It write enables the page immediately after protecting it
a61af66fc99e Initial load
duke
parents:
diff changeset
411 // so we can just return to retry the write.
a61af66fc99e Initial load
duke
parents:
diff changeset
412 if ((sig == SIGSEGV) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
413 os::is_memory_serialize_page(thread, (address) info->si_addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
414 // Block current thread until the memory serialize page permission restored.
a61af66fc99e Initial load
duke
parents:
diff changeset
415 os::block_on_serialize_page_trap();
a61af66fc99e Initial load
duke
parents:
diff changeset
416 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
418 }
a61af66fc99e Initial load
duke
parents:
diff changeset
419
a61af66fc99e Initial load
duke
parents:
diff changeset
420 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // Execution protection violation
a61af66fc99e Initial load
duke
parents:
diff changeset
422 //
a61af66fc99e Initial load
duke
parents:
diff changeset
423 // This should be kept as the last step in the triage. We don't
a61af66fc99e Initial load
duke
parents:
diff changeset
424 // have a dedicated trap number for a no-execute fault, so be
a61af66fc99e Initial load
duke
parents:
diff changeset
425 // conservative and allow other handlers the first shot.
a61af66fc99e Initial load
duke
parents:
diff changeset
426 //
a61af66fc99e Initial load
duke
parents:
diff changeset
427 // Note: We don't test that info->si_code == SEGV_ACCERR here.
a61af66fc99e Initial load
duke
parents:
diff changeset
428 // this si_code is so generic that it is almost meaningless; and
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // the si_code for this condition may change in the future.
a61af66fc99e Initial load
duke
parents:
diff changeset
430 // Furthermore, a false-positive should be harmless.
a61af66fc99e Initial load
duke
parents:
diff changeset
431 if (UnguardOnExecutionViolation > 0 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
432 (sig == SIGSEGV || sig == SIGBUS) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
433 uc->uc_mcontext.gregs[REG_TRAPNO] == trap_page_fault) {
a61af66fc99e Initial load
duke
parents:
diff changeset
434 int page_size = os::vm_page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
435 address addr = (address) info->si_addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
436 address pc = os::Linux::ucontext_get_pc(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
437 // Make sure the pc and the faulting address are sane.
a61af66fc99e Initial load
duke
parents:
diff changeset
438 //
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // If an instruction spans a page boundary, and the page containing
a61af66fc99e Initial load
duke
parents:
diff changeset
440 // the beginning of the instruction is executable but the following
a61af66fc99e Initial load
duke
parents:
diff changeset
441 // page is not, the pc and the faulting address might be slightly
a61af66fc99e Initial load
duke
parents:
diff changeset
442 // different - we still want to unguard the 2nd page in this case.
a61af66fc99e Initial load
duke
parents:
diff changeset
443 //
a61af66fc99e Initial load
duke
parents:
diff changeset
444 // 15 bytes seems to be a (very) safe value for max instruction size.
a61af66fc99e Initial load
duke
parents:
diff changeset
445 bool pc_is_near_addr =
a61af66fc99e Initial load
duke
parents:
diff changeset
446 (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);
a61af66fc99e Initial load
duke
parents:
diff changeset
447 bool instr_spans_page_boundary =
a61af66fc99e Initial load
duke
parents:
diff changeset
448 (align_size_down((intptr_t) pc ^ (intptr_t) addr,
a61af66fc99e Initial load
duke
parents:
diff changeset
449 (intptr_t) page_size) > 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
450
a61af66fc99e Initial load
duke
parents:
diff changeset
451 if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
452 static volatile address last_addr =
a61af66fc99e Initial load
duke
parents:
diff changeset
453 (address) os::non_memory_address_word();
a61af66fc99e Initial load
duke
parents:
diff changeset
454
a61af66fc99e Initial load
duke
parents:
diff changeset
455 // In conservative mode, don't unguard unless the address is in the VM
a61af66fc99e Initial load
duke
parents:
diff changeset
456 if (addr != last_addr &&
a61af66fc99e Initial load
duke
parents:
diff changeset
457 (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
458
477
24fda36852ce 6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents: 196
diff changeset
459 // Set memory to RWX and retry
0
a61af66fc99e Initial load
duke
parents:
diff changeset
460 address page_start =
a61af66fc99e Initial load
duke
parents:
diff changeset
461 (address) align_size_down((intptr_t) addr, (intptr_t) page_size);
477
24fda36852ce 6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents: 196
diff changeset
462 bool res = os::protect_memory((char*) page_start, page_size,
24fda36852ce 6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents: 196
diff changeset
463 os::MEM_PROT_RWX);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
464
a61af66fc99e Initial load
duke
parents:
diff changeset
465 if (PrintMiscellaneous && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
466 char buf[256];
a61af66fc99e Initial load
duke
parents:
diff changeset
467 jio_snprintf(buf, sizeof(buf), "Execution protection violation "
a61af66fc99e Initial load
duke
parents:
diff changeset
468 "at " INTPTR_FORMAT
a61af66fc99e Initial load
duke
parents:
diff changeset
469 ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr,
a61af66fc99e Initial load
duke
parents:
diff changeset
470 page_start, (res ? "success" : "failed"), errno);
a61af66fc99e Initial load
duke
parents:
diff changeset
471 tty->print_raw_cr(buf);
a61af66fc99e Initial load
duke
parents:
diff changeset
472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
473 stub = pc;
a61af66fc99e Initial load
duke
parents:
diff changeset
474
a61af66fc99e Initial load
duke
parents:
diff changeset
475 // Set last_addr so if we fault again at the same address, we don't end
a61af66fc99e Initial load
duke
parents:
diff changeset
476 // up in an endless loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
477 //
a61af66fc99e Initial load
duke
parents:
diff changeset
478 // There are two potential complications here. Two threads trapping at
a61af66fc99e Initial load
duke
parents:
diff changeset
479 // the same address at the same time could cause one of the threads to
a61af66fc99e Initial load
duke
parents:
diff changeset
480 // think it already unguarded, and abort the VM. Likely very rare.
a61af66fc99e Initial load
duke
parents:
diff changeset
481 //
a61af66fc99e Initial load
duke
parents:
diff changeset
482 // The other race involves two threads alternately trapping at
a61af66fc99e Initial load
duke
parents:
diff changeset
483 // different addresses and failing to unguard the page, resulting in
a61af66fc99e Initial load
duke
parents:
diff changeset
484 // an endless loop. This condition is probably even more unlikely than
a61af66fc99e Initial load
duke
parents:
diff changeset
485 // the first.
a61af66fc99e Initial load
duke
parents:
diff changeset
486 //
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // Although both cases could be avoided by using locks or thread local
a61af66fc99e Initial load
duke
parents:
diff changeset
488 // last_addr, these solutions are unnecessary complication: this
a61af66fc99e Initial load
duke
parents:
diff changeset
489 // handler is a best-effort safety net, not a complete solution. It is
a61af66fc99e Initial load
duke
parents:
diff changeset
490 // disabled by default and should only be used as a workaround in case
a61af66fc99e Initial load
duke
parents:
diff changeset
491 // we missed any no-execute-unsafe VM code.
a61af66fc99e Initial load
duke
parents:
diff changeset
492
a61af66fc99e Initial load
duke
parents:
diff changeset
493 last_addr = addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
494 }
a61af66fc99e Initial load
duke
parents:
diff changeset
495 }
a61af66fc99e Initial load
duke
parents:
diff changeset
496 }
a61af66fc99e Initial load
duke
parents:
diff changeset
497 #endif // !AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
498
a61af66fc99e Initial load
duke
parents:
diff changeset
499 if (stub != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
500 // save all thread context in case we need to restore it
a61af66fc99e Initial load
duke
parents:
diff changeset
501 if (thread != NULL) thread->set_saved_exception_pc(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
502
a61af66fc99e Initial load
duke
parents:
diff changeset
503 uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub;
a61af66fc99e Initial load
duke
parents:
diff changeset
504 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
505 }
a61af66fc99e Initial load
duke
parents:
diff changeset
506
a61af66fc99e Initial load
duke
parents:
diff changeset
507 // signal-chaining
a61af66fc99e Initial load
duke
parents:
diff changeset
508 if (os::Linux::chained_handler(sig, info, ucVoid)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
509 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
510 }
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 if (!abort_if_unrecognized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // caller wants another chance, so give it to him
a61af66fc99e Initial load
duke
parents:
diff changeset
514 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
515 }
a61af66fc99e Initial load
duke
parents:
diff changeset
516
a61af66fc99e Initial load
duke
parents:
diff changeset
517 if (pc == NULL && uc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
518 pc = os::Linux::ucontext_get_pc(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
519 }
a61af66fc99e Initial load
duke
parents:
diff changeset
520
a61af66fc99e Initial load
duke
parents:
diff changeset
521 // unmask current signal
a61af66fc99e Initial load
duke
parents:
diff changeset
522 sigset_t newset;
a61af66fc99e Initial load
duke
parents:
diff changeset
523 sigemptyset(&newset);
a61af66fc99e Initial load
duke
parents:
diff changeset
524 sigaddset(&newset, sig);
a61af66fc99e Initial load
duke
parents:
diff changeset
525 sigprocmask(SIG_UNBLOCK, &newset, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
526
a61af66fc99e Initial load
duke
parents:
diff changeset
527 VMError err(t, sig, pc, info, ucVoid);
a61af66fc99e Initial load
duke
parents:
diff changeset
528 err.report_and_die();
a61af66fc99e Initial load
duke
parents:
diff changeset
529
a61af66fc99e Initial load
duke
parents:
diff changeset
530 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
531 }
a61af66fc99e Initial load
duke
parents:
diff changeset
532
a61af66fc99e Initial load
duke
parents:
diff changeset
533 void os::Linux::init_thread_fpu_state(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
534 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
535 // set fpu to 53 bit precision
a61af66fc99e Initial load
duke
parents:
diff changeset
536 set_fpu_control_word(0x27f);
a61af66fc99e Initial load
duke
parents:
diff changeset
537 #endif // !AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
538 }
a61af66fc99e Initial load
duke
parents:
diff changeset
539
a61af66fc99e Initial load
duke
parents:
diff changeset
540 int os::Linux::get_fpu_control_word(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
541 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
542 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
543 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
544 int fpu_control;
a61af66fc99e Initial load
duke
parents:
diff changeset
545 _FPU_GETCW(fpu_control);
a61af66fc99e Initial load
duke
parents:
diff changeset
546 return fpu_control & 0xffff;
a61af66fc99e Initial load
duke
parents:
diff changeset
547 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
548 }
a61af66fc99e Initial load
duke
parents:
diff changeset
549
a61af66fc99e Initial load
duke
parents:
diff changeset
550 void os::Linux::set_fpu_control_word(int fpu_control) {
a61af66fc99e Initial load
duke
parents:
diff changeset
551 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
552 _FPU_SETCW(fpu_control);
a61af66fc99e Initial load
duke
parents:
diff changeset
553 #endif // !AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
554 }
a61af66fc99e Initial load
duke
parents:
diff changeset
555
a61af66fc99e Initial load
duke
parents:
diff changeset
556 // Check that the linux kernel version is 2.4 or higher since earlier
a61af66fc99e Initial load
duke
parents:
diff changeset
557 // versions do not support SSE without patches.
a61af66fc99e Initial load
duke
parents:
diff changeset
558 bool os::supports_sse() {
a61af66fc99e Initial load
duke
parents:
diff changeset
559 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
560 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
561 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
562 struct utsname uts;
a61af66fc99e Initial load
duke
parents:
diff changeset
563 if( uname(&uts) != 0 ) return false; // uname fails?
a61af66fc99e Initial load
duke
parents:
diff changeset
564 char *minor_string;
a61af66fc99e Initial load
duke
parents:
diff changeset
565 int major = strtol(uts.release,&minor_string,10);
a61af66fc99e Initial load
duke
parents:
diff changeset
566 int minor = strtol(minor_string+1,NULL,10);
a61af66fc99e Initial load
duke
parents:
diff changeset
567 bool result = (major > 2 || (major==2 && minor >= 4));
a61af66fc99e Initial load
duke
parents:
diff changeset
568 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
569 if (PrintMiscellaneous && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
570 tty->print("OS version is %d.%d, which %s support SSE/SSE2\n",
a61af66fc99e Initial load
duke
parents:
diff changeset
571 major,minor, result ? "DOES" : "does NOT");
a61af66fc99e Initial load
duke
parents:
diff changeset
572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
573 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
574 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
575 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
576 }
a61af66fc99e Initial load
duke
parents:
diff changeset
577
a61af66fc99e Initial load
duke
parents:
diff changeset
578 bool os::is_allocatable(size_t bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
579 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
580 // unused on amd64?
a61af66fc99e Initial load
duke
parents:
diff changeset
581 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
582 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
583
a61af66fc99e Initial load
duke
parents:
diff changeset
584 if (bytes < 2 * G) {
a61af66fc99e Initial load
duke
parents:
diff changeset
585 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
586 }
a61af66fc99e Initial load
duke
parents:
diff changeset
587
a61af66fc99e Initial load
duke
parents:
diff changeset
588 char* addr = reserve_memory(bytes, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
589
a61af66fc99e Initial load
duke
parents:
diff changeset
590 if (addr != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
591 release_memory(addr, bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
592 }
a61af66fc99e Initial load
duke
parents:
diff changeset
593
a61af66fc99e Initial load
duke
parents:
diff changeset
594 return addr != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
595 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
596 }
a61af66fc99e Initial load
duke
parents:
diff changeset
597
a61af66fc99e Initial load
duke
parents:
diff changeset
598 ////////////////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
599 // thread stack
a61af66fc99e Initial load
duke
parents:
diff changeset
600
a61af66fc99e Initial load
duke
parents:
diff changeset
601 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
602 size_t os::Linux::min_stack_allowed = 64 * K;
a61af66fc99e Initial load
duke
parents:
diff changeset
603
a61af66fc99e Initial load
duke
parents:
diff changeset
604 // amd64: pthread on amd64 is always in floating stack mode
a61af66fc99e Initial load
duke
parents:
diff changeset
605 bool os::Linux::supports_variable_stack_size() { return true; }
a61af66fc99e Initial load
duke
parents:
diff changeset
606 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
607 size_t os::Linux::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
a61af66fc99e Initial load
duke
parents:
diff changeset
608
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
609 #ifdef __GNUC__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
610 #define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
611 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
612
a61af66fc99e Initial load
duke
parents:
diff changeset
613 // Test if pthread library can support variable thread stack size. LinuxThreads
a61af66fc99e Initial load
duke
parents:
diff changeset
614 // in fixed stack mode allocates 2M fixed slot for each thread. LinuxThreads
a61af66fc99e Initial load
duke
parents:
diff changeset
615 // in floating stack mode and NPTL support variable stack size.
a61af66fc99e Initial load
duke
parents:
diff changeset
616 bool os::Linux::supports_variable_stack_size() {
a61af66fc99e Initial load
duke
parents:
diff changeset
617 if (os::Linux::is_NPTL()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
618 // NPTL, yes
a61af66fc99e Initial load
duke
parents:
diff changeset
619 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
620
a61af66fc99e Initial load
duke
parents:
diff changeset
621 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
622 // Note: We can't control default stack size when creating a thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
623 // If we use non-default stack size (pthread_attr_setstacksize), both
a61af66fc99e Initial load
duke
parents:
diff changeset
624 // floating stack and non-floating stack LinuxThreads will return the
a61af66fc99e Initial load
duke
parents:
diff changeset
625 // same value. This makes it impossible to implement this function by
a61af66fc99e Initial load
duke
parents:
diff changeset
626 // detecting thread stack size directly.
a61af66fc99e Initial load
duke
parents:
diff changeset
627 //
a61af66fc99e Initial load
duke
parents:
diff changeset
628 // An alternative approach is to check %gs. Fixed-stack LinuxThreads
a61af66fc99e Initial load
duke
parents:
diff changeset
629 // do not use %gs, so its value is 0. Floating-stack LinuxThreads use
a61af66fc99e Initial load
duke
parents:
diff changeset
630 // %gs (either as LDT selector or GDT selector, depending on kernel)
a61af66fc99e Initial load
duke
parents:
diff changeset
631 // to access thread specific data.
a61af66fc99e Initial load
duke
parents:
diff changeset
632 //
a61af66fc99e Initial load
duke
parents:
diff changeset
633 // Note that %gs is a reserved glibc register since early 2001, so
a61af66fc99e Initial load
duke
parents:
diff changeset
634 // applications are not allowed to change its value (Ulrich Drepper from
a61af66fc99e Initial load
duke
parents:
diff changeset
635 // Redhat confirmed that all known offenders have been modified to use
a61af66fc99e Initial load
duke
parents:
diff changeset
636 // either %fs or TSD). In the worst case scenario, when VM is embedded in
a61af66fc99e Initial load
duke
parents:
diff changeset
637 // a native application that plays with %gs, we might see non-zero %gs
a61af66fc99e Initial load
duke
parents:
diff changeset
638 // even LinuxThreads is running in fixed stack mode. As the result, we'll
a61af66fc99e Initial load
duke
parents:
diff changeset
639 // return true and skip _thread_safety_check(), so we may not be able to
a61af66fc99e Initial load
duke
parents:
diff changeset
640 // detect stack-heap collisions. But otherwise it's harmless.
a61af66fc99e Initial load
duke
parents:
diff changeset
641 //
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
642 #ifdef __GNUC__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
643 return (GET_GS() != 0);
50
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
644 #else
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
645 return false;
485d403e94e1 6452081: 3/4 Allow for Linux builds with Sun Studio Linux compilers
dcubed
parents: 0
diff changeset
646 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
647 }
a61af66fc99e Initial load
duke
parents:
diff changeset
648 }
a61af66fc99e Initial load
duke
parents:
diff changeset
649 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
650
a61af66fc99e Initial load
duke
parents:
diff changeset
651 // return default stack size for thr_type
a61af66fc99e Initial load
duke
parents:
diff changeset
652 size_t os::Linux::default_stack_size(os::ThreadType thr_type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // default stack size (compiler thread needs larger stack)
a61af66fc99e Initial load
duke
parents:
diff changeset
654 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
655 size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
a61af66fc99e Initial load
duke
parents:
diff changeset
656 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
657 size_t s = (thr_type == os::compiler_thread ? 2 * M : 512 * K);
a61af66fc99e Initial load
duke
parents:
diff changeset
658 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
659 return s;
a61af66fc99e Initial load
duke
parents:
diff changeset
660 }
a61af66fc99e Initial load
duke
parents:
diff changeset
661
a61af66fc99e Initial load
duke
parents:
diff changeset
662 size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
663 // Creating guard page is very expensive. Java thread has HotSpot
a61af66fc99e Initial load
duke
parents:
diff changeset
664 // guard page, only enable glibc guard page for non-Java threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
665 return (thr_type == java_thread ? 0 : page_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
666 }
a61af66fc99e Initial load
duke
parents:
diff changeset
667
a61af66fc99e Initial load
duke
parents:
diff changeset
668 // Java thread:
a61af66fc99e Initial load
duke
parents:
diff changeset
669 //
a61af66fc99e Initial load
duke
parents:
diff changeset
670 // Low memory addresses
a61af66fc99e Initial load
duke
parents:
diff changeset
671 // +------------------------+
a61af66fc99e Initial load
duke
parents:
diff changeset
672 // | |\ JavaThread created by VM does not have glibc
a61af66fc99e Initial load
duke
parents:
diff changeset
673 // | glibc guard page | - guard, attached Java thread usually has
a61af66fc99e Initial load
duke
parents:
diff changeset
674 // | |/ 1 page glibc guard.
a61af66fc99e Initial load
duke
parents:
diff changeset
675 // P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
a61af66fc99e Initial load
duke
parents:
diff changeset
676 // | |\
a61af66fc99e Initial load
duke
parents:
diff changeset
677 // | HotSpot Guard Pages | - red and yellow pages
a61af66fc99e Initial load
duke
parents:
diff changeset
678 // | |/
a61af66fc99e Initial load
duke
parents:
diff changeset
679 // +------------------------+ JavaThread::stack_yellow_zone_base()
a61af66fc99e Initial load
duke
parents:
diff changeset
680 // | |\
a61af66fc99e Initial load
duke
parents:
diff changeset
681 // | Normal Stack | -
a61af66fc99e Initial load
duke
parents:
diff changeset
682 // | |/
a61af66fc99e Initial load
duke
parents:
diff changeset
683 // P2 +------------------------+ Thread::stack_base()
a61af66fc99e Initial load
duke
parents:
diff changeset
684 //
a61af66fc99e Initial load
duke
parents:
diff changeset
685 // Non-Java thread:
a61af66fc99e Initial load
duke
parents:
diff changeset
686 //
a61af66fc99e Initial load
duke
parents:
diff changeset
687 // Low memory addresses
a61af66fc99e Initial load
duke
parents:
diff changeset
688 // +------------------------+
a61af66fc99e Initial load
duke
parents:
diff changeset
689 // | |\
a61af66fc99e Initial load
duke
parents:
diff changeset
690 // | glibc guard page | - usually 1 page
a61af66fc99e Initial load
duke
parents:
diff changeset
691 // | |/
a61af66fc99e Initial load
duke
parents:
diff changeset
692 // P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
a61af66fc99e Initial load
duke
parents:
diff changeset
693 // | |\
a61af66fc99e Initial load
duke
parents:
diff changeset
694 // | Normal Stack | -
a61af66fc99e Initial load
duke
parents:
diff changeset
695 // | |/
a61af66fc99e Initial load
duke
parents:
diff changeset
696 // P2 +------------------------+ Thread::stack_base()
a61af66fc99e Initial load
duke
parents:
diff changeset
697 //
a61af66fc99e Initial load
duke
parents:
diff changeset
698 // ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
a61af66fc99e Initial load
duke
parents:
diff changeset
699 // pthread_attr_getstack()
a61af66fc99e Initial load
duke
parents:
diff changeset
700
a61af66fc99e Initial load
duke
parents:
diff changeset
701 static void current_stack_region(address * bottom, size_t * size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
702 if (os::Linux::is_initial_thread()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
703 // initial thread needs special handling because pthread_getattr_np()
a61af66fc99e Initial load
duke
parents:
diff changeset
704 // may return bogus value.
a61af66fc99e Initial load
duke
parents:
diff changeset
705 *bottom = os::Linux::initial_thread_stack_bottom();
a61af66fc99e Initial load
duke
parents:
diff changeset
706 *size = os::Linux::initial_thread_stack_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
707 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
708 pthread_attr_t attr;
a61af66fc99e Initial load
duke
parents:
diff changeset
709
a61af66fc99e Initial load
duke
parents:
diff changeset
710 int rslt = pthread_getattr_np(pthread_self(), &attr);
a61af66fc99e Initial load
duke
parents:
diff changeset
711
a61af66fc99e Initial load
duke
parents:
diff changeset
712 // JVM needs to know exact stack location, abort if it fails
a61af66fc99e Initial load
duke
parents:
diff changeset
713 if (rslt != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
714 if (rslt == ENOMEM) {
a61af66fc99e Initial load
duke
parents:
diff changeset
715 vm_exit_out_of_memory(0, "pthread_getattr_np");
a61af66fc99e Initial load
duke
parents:
diff changeset
716 } else {
1490
f03d0a26bf83 6888954: argument formatting for assert() and friends
jcoomes
parents: 579
diff changeset
717 fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
719 }
a61af66fc99e Initial load
duke
parents:
diff changeset
720
a61af66fc99e Initial load
duke
parents:
diff changeset
721 if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
722 fatal("Can not locate current stack attributes!");
a61af66fc99e Initial load
duke
parents:
diff changeset
723 }
a61af66fc99e Initial load
duke
parents:
diff changeset
724
a61af66fc99e Initial load
duke
parents:
diff changeset
725 pthread_attr_destroy(&attr);
a61af66fc99e Initial load
duke
parents:
diff changeset
726
a61af66fc99e Initial load
duke
parents:
diff changeset
727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
728 assert(os::current_stack_pointer() >= *bottom &&
a61af66fc99e Initial load
duke
parents:
diff changeset
729 os::current_stack_pointer() < *bottom + *size, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
730 }
a61af66fc99e Initial load
duke
parents:
diff changeset
731
a61af66fc99e Initial load
duke
parents:
diff changeset
732 address os::current_stack_base() {
a61af66fc99e Initial load
duke
parents:
diff changeset
733 address bottom;
a61af66fc99e Initial load
duke
parents:
diff changeset
734 size_t size;
a61af66fc99e Initial load
duke
parents:
diff changeset
735 current_stack_region(&bottom, &size);
a61af66fc99e Initial load
duke
parents:
diff changeset
736 return (bottom + size);
a61af66fc99e Initial load
duke
parents:
diff changeset
737 }
a61af66fc99e Initial load
duke
parents:
diff changeset
738
a61af66fc99e Initial load
duke
parents:
diff changeset
739 size_t os::current_stack_size() {
a61af66fc99e Initial load
duke
parents:
diff changeset
740 // stack size includes normal stack and HotSpot guard pages
a61af66fc99e Initial load
duke
parents:
diff changeset
741 address bottom;
a61af66fc99e Initial load
duke
parents:
diff changeset
742 size_t size;
a61af66fc99e Initial load
duke
parents:
diff changeset
743 current_stack_region(&bottom, &size);
a61af66fc99e Initial load
duke
parents:
diff changeset
744 return size;
a61af66fc99e Initial load
duke
parents:
diff changeset
745 }
a61af66fc99e Initial load
duke
parents:
diff changeset
746
a61af66fc99e Initial load
duke
parents:
diff changeset
747 /////////////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
748 // helper functions for fatal error handler
a61af66fc99e Initial load
duke
parents:
diff changeset
749
a61af66fc99e Initial load
duke
parents:
diff changeset
750 void os::print_context(outputStream *st, void *context) {
a61af66fc99e Initial load
duke
parents:
diff changeset
751 if (context == NULL) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
752
a61af66fc99e Initial load
duke
parents:
diff changeset
753 ucontext_t *uc = (ucontext_t*)context;
a61af66fc99e Initial load
duke
parents:
diff changeset
754 st->print_cr("Registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
755 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
756 st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
757 st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
758 st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
759 st->print(", RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
760 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
761 st->print( "RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
762 st->print(", RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
763 st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
a61af66fc99e Initial load
duke
parents:
diff changeset
764 st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
a61af66fc99e Initial load
duke
parents:
diff changeset
765 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
766 st->print( "R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
a61af66fc99e Initial load
duke
parents:
diff changeset
767 st->print(", R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
a61af66fc99e Initial load
duke
parents:
diff changeset
768 st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
a61af66fc99e Initial load
duke
parents:
diff changeset
769 st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
a61af66fc99e Initial load
duke
parents:
diff changeset
770 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
771 st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
a61af66fc99e Initial load
duke
parents:
diff changeset
772 st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
a61af66fc99e Initial load
duke
parents:
diff changeset
773 st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
a61af66fc99e Initial load
duke
parents:
diff changeset
774 st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
a61af66fc99e Initial load
duke
parents:
diff changeset
775 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
776 st->print( "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]);
1907
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
777 st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
778 st->print(", CSGSFS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_CSGSFS]);
a61af66fc99e Initial load
duke
parents:
diff changeset
779 st->print(", ERR=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ERR]);
a61af66fc99e Initial load
duke
parents:
diff changeset
780 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
781 st->print(" TRAPNO=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_TRAPNO]);
a61af66fc99e Initial load
duke
parents:
diff changeset
782 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
783 st->print( "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EAX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
784 st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
785 st->print(", ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ECX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
786 st->print(", EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
787 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
788 st->print( "ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_UESP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
789 st->print(", EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
790 st->print(", ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ESI]);
a61af66fc99e Initial load
duke
parents:
diff changeset
791 st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDI]);
a61af66fc99e Initial load
duke
parents:
diff changeset
792 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
793 st->print( "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EIP]);
1907
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
794 st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
795 st->print(", CR2=" INTPTR_FORMAT, uc->uc_mcontext.cr2);
a61af66fc99e Initial load
duke
parents:
diff changeset
796 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
797 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
798 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
799
a61af66fc99e Initial load
duke
parents:
diff changeset
800 intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
801 st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
a61af66fc99e Initial load
duke
parents:
diff changeset
802 print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t));
a61af66fc99e Initial load
duke
parents:
diff changeset
803 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
804
a61af66fc99e Initial load
duke
parents:
diff changeset
805 // Note: it may be unsafe to inspect memory near pc. For example, pc may
a61af66fc99e Initial load
duke
parents:
diff changeset
806 // point to garbage if entry point in an nmethod is corrupted. Leave
a61af66fc99e Initial load
duke
parents:
diff changeset
807 // this at the end, and hope for the best.
a61af66fc99e Initial load
duke
parents:
diff changeset
808 address pc = os::Linux::ucontext_get_pc(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
809 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
1907
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
810 print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
811 }
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
812
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
813 void os::print_register_info(outputStream *st, void *context) {
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
814 if (context == NULL) return;
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
815
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
816 ucontext_t *uc = (ucontext_t*)context;
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
817
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
818 st->print_cr("Register to memory mapping:");
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
819 st->cr();
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
820
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
821 // this is horrendously verbose but the layout of the registers in the
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
822 // context does not match how we defined our abstract Register set, so
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
823 // we can't just iterate through the gregs area
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
824
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
825 // this is only for the "general purpose" registers
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
826
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
827 #ifdef AMD64
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
828 st->print("RAX="); print_location(st, uc->uc_mcontext.gregs[REG_RAX]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
829 st->print("RBX="); print_location(st, uc->uc_mcontext.gregs[REG_RBX]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
830 st->print("RCX="); print_location(st, uc->uc_mcontext.gregs[REG_RCX]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
831 st->print("RDX="); print_location(st, uc->uc_mcontext.gregs[REG_RDX]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
832 st->print("RSP="); print_location(st, uc->uc_mcontext.gregs[REG_RSP]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
833 st->print("RBP="); print_location(st, uc->uc_mcontext.gregs[REG_RBP]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
834 st->print("RSI="); print_location(st, uc->uc_mcontext.gregs[REG_RSI]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
835 st->print("RDI="); print_location(st, uc->uc_mcontext.gregs[REG_RDI]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
836 st->print("R8 ="); print_location(st, uc->uc_mcontext.gregs[REG_R8]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
837 st->print("R9 ="); print_location(st, uc->uc_mcontext.gregs[REG_R9]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
838 st->print("R10="); print_location(st, uc->uc_mcontext.gregs[REG_R10]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
839 st->print("R11="); print_location(st, uc->uc_mcontext.gregs[REG_R11]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
840 st->print("R12="); print_location(st, uc->uc_mcontext.gregs[REG_R12]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
841 st->print("R13="); print_location(st, uc->uc_mcontext.gregs[REG_R13]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
842 st->print("R14="); print_location(st, uc->uc_mcontext.gregs[REG_R14]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
843 st->print("R15="); print_location(st, uc->uc_mcontext.gregs[REG_R15]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
844 #else
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
845 st->print("EAX="); print_location(st, uc->uc_mcontext.gregs[REG_EAX]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
846 st->print("EBX="); print_location(st, uc->uc_mcontext.gregs[REG_EBX]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
847 st->print("ECX="); print_location(st, uc->uc_mcontext.gregs[REG_ECX]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
848 st->print("EDX="); print_location(st, uc->uc_mcontext.gregs[REG_EDX]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
849 st->print("ESP="); print_location(st, uc->uc_mcontext.gregs[REG_ESP]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
850 st->print("EBP="); print_location(st, uc->uc_mcontext.gregs[REG_EBP]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
851 st->print("ESI="); print_location(st, uc->uc_mcontext.gregs[REG_ESI]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
852 st->print("EDI="); print_location(st, uc->uc_mcontext.gregs[REG_EDI]);
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
853 #endif // AMD64
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
854
1e9a9d2e6509 6970683: improvements to hs_err output
never
parents: 1681
diff changeset
855 st->cr();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
856 }
a61af66fc99e Initial load
duke
parents:
diff changeset
857
a61af66fc99e Initial load
duke
parents:
diff changeset
858 void os::setup_fpu() {
a61af66fc99e Initial load
duke
parents:
diff changeset
859 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
860 address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std();
a61af66fc99e Initial load
duke
parents:
diff changeset
861 __asm__ volatile ( "fldcw (%0)" :
a61af66fc99e Initial load
duke
parents:
diff changeset
862 : "r" (fpu_cntrl) : "memory");
a61af66fc99e Initial load
duke
parents:
diff changeset
863 #endif // !AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
864 }