annotate src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @ 795:215f81b4d9b3

6841831: G1: assert(contains_reference(from),"We just added it!") fires Summary: During parallel rset updating we have to make sure that the worker ids of the refinement threads do not intersect with the worker ids that can be claimed by the mutator threads. Reviewed-by: tonyp
author iveresov
date Mon, 18 May 2009 11:52:46 -0700
parents d0994e5bebce
children 3f5b7efb9642
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
585
22e09c0f4b47 6808589: Merge vm_version_x86_{32,64}.{cpp,hpp}
twisti
parents: 477
diff changeset
2 * Copyright 1999-2009 Sun Microsystems, Inc. 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 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 // do not include precompiled header file
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_os_solaris_x86.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 // put OS-includes here
a61af66fc99e Initial load
duke
parents:
diff changeset
29 # include <sys/types.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
30 # include <sys/mman.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
31 # include <pthread.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
32 # include <signal.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
33 # include <setjmp.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
34 # include <errno.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
35 # include <dlfcn.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
36 # include <stdio.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
37 # include <unistd.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
38 # include <sys/resource.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
39 # include <thread.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
40 # include <sys/stat.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
41 # include <sys/time.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
42 # include <sys/filio.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
43 # include <sys/utsname.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
44 # include <sys/systeminfo.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
45 # include <sys/socket.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
46 # include <sys/trap.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
47 # include <sys/lwp.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
48 # include <pwd.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
49 # include <poll.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
50 # include <sys/lwp.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
51 # include <procfs.h> // see comment in <sys/procfs.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
52
a61af66fc99e Initial load
duke
parents:
diff changeset
53 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
54 // QQQ seems useless at this point
a61af66fc99e Initial load
duke
parents:
diff changeset
55 # define _STRUCTURED_PROC 1 // this gets us the new structured proc interfaces of 5.6 & later
a61af66fc99e Initial load
duke
parents:
diff changeset
56 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
57 # include <sys/procfs.h> // see comment in <sys/procfs.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
58
a61af66fc99e Initial load
duke
parents:
diff changeset
59
a61af66fc99e Initial load
duke
parents:
diff changeset
60 #define MAX_PATH (2 * K)
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // Minimum stack size for the VM. It's easier to document a constant value
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // but it's different for x86 and sparc because the page sizes are different.
a61af66fc99e Initial load
duke
parents:
diff changeset
64 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 size_t os::Solaris::min_stack_allowed = 224*K;
a61af66fc99e Initial load
duke
parents:
diff changeset
66 #define REG_SP REG_RSP
a61af66fc99e Initial load
duke
parents:
diff changeset
67 #define REG_PC REG_RIP
a61af66fc99e Initial load
duke
parents:
diff changeset
68 #define REG_FP REG_RBP
a61af66fc99e Initial load
duke
parents:
diff changeset
69 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
70 size_t os::Solaris::min_stack_allowed = 64*K;
a61af66fc99e Initial load
duke
parents:
diff changeset
71 #define REG_SP UESP
a61af66fc99e Initial load
duke
parents:
diff changeset
72 #define REG_PC EIP
a61af66fc99e Initial load
duke
parents:
diff changeset
73 #define REG_FP EBP
a61af66fc99e Initial load
duke
parents:
diff changeset
74 // 4900493 counter to prevent runaway LDTR refresh attempt
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 static volatile int ldtr_refresh = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
77 // the libthread instruction that faults because of the stale LDTR
a61af66fc99e Initial load
duke
parents:
diff changeset
78
a61af66fc99e Initial load
duke
parents:
diff changeset
79 static const unsigned char movlfs[] = { 0x8e, 0xe0 // movl %eax,%fs
a61af66fc99e Initial load
duke
parents:
diff changeset
80 };
a61af66fc99e Initial load
duke
parents:
diff changeset
81 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
82
a61af66fc99e Initial load
duke
parents:
diff changeset
83 char* os::non_memory_address_word() {
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // Must never look like an address returned by reserve_memory,
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // even in its subfields (as defined by the CPU immediate fields,
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // if the CPU splits constants across multiple instructions).
a61af66fc99e Initial load
duke
parents:
diff changeset
87 return (char*) -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
88 }
a61af66fc99e Initial load
duke
parents:
diff changeset
89
a61af66fc99e Initial load
duke
parents:
diff changeset
90 //
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // Validate a ucontext retrieved from walking a uc_link of a ucontext.
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // There are issues with libthread giving out uc_links for different threads
a61af66fc99e Initial load
duke
parents:
diff changeset
93 // on the same uc_link chain and bad or circular links.
a61af66fc99e Initial load
duke
parents:
diff changeset
94 //
a61af66fc99e Initial load
duke
parents:
diff changeset
95 bool os::Solaris::valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect) {
a61af66fc99e Initial load
duke
parents:
diff changeset
96 if (valid >= suspect ||
a61af66fc99e Initial load
duke
parents:
diff changeset
97 valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags ||
a61af66fc99e Initial load
duke
parents:
diff changeset
98 valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp ||
a61af66fc99e Initial load
duke
parents:
diff changeset
99 valid->uc_stack.ss_size != suspect->uc_stack.ss_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
100 DEBUG_ONLY(tty->print_cr("valid_ucontext: failed test 1");)
a61af66fc99e Initial load
duke
parents:
diff changeset
101 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103
a61af66fc99e Initial load
duke
parents:
diff changeset
104 if (thread->is_Java_thread()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 if (!valid_stack_address(thread, (address)suspect)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 DEBUG_ONLY(tty->print_cr("valid_ucontext: uc_link not in thread stack");)
a61af66fc99e Initial load
duke
parents:
diff changeset
107 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
109 if (!valid_stack_address(thread, (address) suspect->uc_mcontext.gregs[REG_SP])) {
a61af66fc99e Initial load
duke
parents:
diff changeset
110 DEBUG_ONLY(tty->print_cr("valid_ucontext: stackpointer not in thread stack");)
a61af66fc99e Initial load
duke
parents:
diff changeset
111 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
112 }
a61af66fc99e Initial load
duke
parents:
diff changeset
113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
114 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // We will only follow one level of uc_link since there are libthread
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // issues with ucontext linking and it is better to be safe and just
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // let caller retry later.
a61af66fc99e Initial load
duke
parents:
diff changeset
120 ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread,
a61af66fc99e Initial load
duke
parents:
diff changeset
121 ucontext_t *uc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
122
a61af66fc99e Initial load
duke
parents:
diff changeset
123 ucontext_t *retuc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
124
a61af66fc99e Initial load
duke
parents:
diff changeset
125 if (uc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 if (uc->uc_link == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
127 // cannot validate without uc_link so accept current ucontext
a61af66fc99e Initial load
duke
parents:
diff changeset
128 retuc = uc;
a61af66fc99e Initial load
duke
parents:
diff changeset
129 } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // first ucontext is valid so try the next one
a61af66fc99e Initial load
duke
parents:
diff changeset
131 uc = uc->uc_link;
a61af66fc99e Initial load
duke
parents:
diff changeset
132 if (uc->uc_link == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // cannot validate without uc_link so accept current ucontext
a61af66fc99e Initial load
duke
parents:
diff changeset
134 retuc = uc;
a61af66fc99e Initial load
duke
parents:
diff changeset
135 } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
136 // the ucontext one level down is also valid so return it
a61af66fc99e Initial load
duke
parents:
diff changeset
137 retuc = uc;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
141 return retuc;
a61af66fc99e Initial load
duke
parents:
diff changeset
142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144 // Assumes ucontext is valid
a61af66fc99e Initial load
duke
parents:
diff changeset
145 ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
146 return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]);
a61af66fc99e Initial load
duke
parents:
diff changeset
147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
148
a61af66fc99e Initial load
duke
parents:
diff changeset
149 // Assumes ucontext is valid
a61af66fc99e Initial load
duke
parents:
diff changeset
150 intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 return (intptr_t*)uc->uc_mcontext.gregs[REG_SP];
a61af66fc99e Initial load
duke
parents:
diff changeset
152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
153
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // Assumes ucontext is valid
a61af66fc99e Initial load
duke
parents:
diff changeset
155 intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
156 return (intptr_t*)uc->uc_mcontext.gregs[REG_FP];
a61af66fc99e Initial load
duke
parents:
diff changeset
157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
158
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // For Forte Analyzer AsyncGetCallTrace profiling support - thread
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // is currently interrupted by SIGPROF.
a61af66fc99e Initial load
duke
parents:
diff changeset
161 //
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // The difference between this and os::fetch_frame_from_context() is that
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // here we try to skip nested signal frames.
a61af66fc99e Initial load
duke
parents:
diff changeset
164 ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread,
a61af66fc99e Initial load
duke
parents:
diff changeset
165 ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
166
a61af66fc99e Initial load
duke
parents:
diff changeset
167 assert(thread != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
168 assert(ret_sp != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
169 assert(ret_fp != NULL, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
170
a61af66fc99e Initial load
duke
parents:
diff changeset
171 ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
172 return os::fetch_frame_from_context(luc, ret_sp, ret_fp);
a61af66fc99e Initial load
duke
parents:
diff changeset
173 }
a61af66fc99e Initial load
duke
parents:
diff changeset
174
a61af66fc99e Initial load
duke
parents:
diff changeset
175 ExtendedPC os::fetch_frame_from_context(void* ucVoid,
a61af66fc99e Initial load
duke
parents:
diff changeset
176 intptr_t** ret_sp, intptr_t** ret_fp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
177
a61af66fc99e Initial load
duke
parents:
diff changeset
178 ExtendedPC epc;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 ucontext_t *uc = (ucontext_t*)ucVoid;
a61af66fc99e Initial load
duke
parents:
diff changeset
180
a61af66fc99e Initial load
duke
parents:
diff changeset
181 if (uc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
182 epc = os::Solaris::ucontext_get_ExtendedPC(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
183 if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
184 if (ret_fp) *ret_fp = os::Solaris::ucontext_get_fp(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
185 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
186 // construct empty ExtendedPC for return value checking
a61af66fc99e Initial load
duke
parents:
diff changeset
187 epc = ExtendedPC(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
188 if (ret_sp) *ret_sp = (intptr_t *)NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
189 if (ret_fp) *ret_fp = (intptr_t *)NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
191
a61af66fc99e Initial load
duke
parents:
diff changeset
192 return epc;
a61af66fc99e Initial load
duke
parents:
diff changeset
193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195 frame os::fetch_frame_from_context(void* ucVoid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
196 intptr_t* sp;
a61af66fc99e Initial load
duke
parents:
diff changeset
197 intptr_t* fp;
a61af66fc99e Initial load
duke
parents:
diff changeset
198 ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
a61af66fc99e Initial load
duke
parents:
diff changeset
199 return frame(sp, fp, epc.pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
201
a61af66fc99e Initial load
duke
parents:
diff changeset
202 frame os::get_sender_for_C_frame(frame* fr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
203 return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
204 }
a61af66fc99e Initial load
duke
parents:
diff changeset
205
472
7b920868b475 6773838: There is no calling stack for Compiler thread in hs_err file on x86
coleenp
parents: 196
diff changeset
206 extern "C" intptr_t *_get_current_fp(); // in .il file
0
a61af66fc99e Initial load
duke
parents:
diff changeset
207
a61af66fc99e Initial load
duke
parents:
diff changeset
208 frame os::current_frame() {
472
7b920868b475 6773838: There is no calling stack for Compiler thread in hs_err file on x86
coleenp
parents: 196
diff changeset
209 intptr_t* fp = _get_current_fp(); // it's inlined so want current fp
0
a61af66fc99e Initial load
duke
parents:
diff changeset
210 frame myframe((intptr_t*)os::current_stack_pointer(),
a61af66fc99e Initial load
duke
parents:
diff changeset
211 (intptr_t*)fp,
a61af66fc99e Initial load
duke
parents:
diff changeset
212 CAST_FROM_FN_PTR(address, os::current_frame));
a61af66fc99e Initial load
duke
parents:
diff changeset
213 if (os::is_first_C_frame(&myframe)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
214 // stack is not walkable
107
93b6525e3b82 6603919: Stackwalking crash on x86 -server with Sun Studio's collect -j on
sgoldman
parents: 0
diff changeset
215 frame ret; // This will be a null useless frame
93b6525e3b82 6603919: Stackwalking crash on x86 -server with Sun Studio's collect -j on
sgoldman
parents: 0
diff changeset
216 return ret;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
217 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
218 return os::get_sender_for_C_frame(&myframe);
a61af66fc99e Initial load
duke
parents:
diff changeset
219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
221
a61af66fc99e Initial load
duke
parents:
diff changeset
222 // This is a simple callback that just fetches a PC for an interrupted thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
223 // The thread need not be suspended and the fetched PC is just a hint.
a61af66fc99e Initial load
duke
parents:
diff changeset
224 // This one is currently used for profiling the VMThread ONLY!
a61af66fc99e Initial load
duke
parents:
diff changeset
225
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // Must be synchronous
a61af66fc99e Initial load
duke
parents:
diff changeset
227 void GetThreadPC_Callback::execute(OSThread::InterruptArguments *args) {
a61af66fc99e Initial load
duke
parents:
diff changeset
228 Thread* thread = args->thread();
a61af66fc99e Initial load
duke
parents:
diff changeset
229 ucontext_t* uc = args->ucontext();
a61af66fc99e Initial load
duke
parents:
diff changeset
230 intptr_t* sp;
a61af66fc99e Initial load
duke
parents:
diff changeset
231
a61af66fc99e Initial load
duke
parents:
diff changeset
232 assert(ProfileVM && thread->is_VM_thread(), "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
233
a61af66fc99e Initial load
duke
parents:
diff changeset
234 ExtendedPC new_addr((address)uc->uc_mcontext.gregs[REG_PC]);
a61af66fc99e Initial load
duke
parents:
diff changeset
235 _addr = new_addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
237
a61af66fc99e Initial load
duke
parents:
diff changeset
238 static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) {
a61af66fc99e Initial load
duke
parents:
diff changeset
239 char lwpstatusfile[PROCFILE_LENGTH];
a61af66fc99e Initial load
duke
parents:
diff changeset
240 int lwpfd, err;
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs))
a61af66fc99e Initial load
duke
parents:
diff changeset
243 return (err);
a61af66fc99e Initial load
duke
parents:
diff changeset
244 if (*flags == TRS_LWPID) {
a61af66fc99e Initial load
duke
parents:
diff changeset
245 sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(),
a61af66fc99e Initial load
duke
parents:
diff changeset
246 *lwp);
a61af66fc99e Initial load
duke
parents:
diff changeset
247 if ((lwpfd = open(lwpstatusfile, O_RDONLY)) < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
248 perror("thr_mutator_status: open lwpstatus");
a61af66fc99e Initial load
duke
parents:
diff changeset
249 return (EINVAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251 if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) !=
a61af66fc99e Initial load
duke
parents:
diff changeset
252 sizeof (lwpstatus_t)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
253 perror("thr_mutator_status: read lwpstatus");
a61af66fc99e Initial load
duke
parents:
diff changeset
254 (void) close(lwpfd);
a61af66fc99e Initial load
duke
parents:
diff changeset
255 return (EINVAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
257 (void) close(lwpfd);
a61af66fc99e Initial load
duke
parents:
diff changeset
258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
259 return (0);
a61af66fc99e Initial load
duke
parents:
diff changeset
260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
261
a61af66fc99e Initial load
duke
parents:
diff changeset
262 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
263
a61af66fc99e Initial load
duke
parents:
diff changeset
264 // Detecting SSE support by OS
a61af66fc99e Initial load
duke
parents:
diff changeset
265 // From solaris_i486.s
a61af66fc99e Initial load
duke
parents:
diff changeset
266 extern "C" bool sse_check();
a61af66fc99e Initial load
duke
parents:
diff changeset
267 extern "C" bool sse_unavailable();
a61af66fc99e Initial load
duke
parents:
diff changeset
268
a61af66fc99e Initial load
duke
parents:
diff changeset
269 enum { SSE_UNKNOWN, SSE_NOT_SUPPORTED, SSE_SUPPORTED};
a61af66fc99e Initial load
duke
parents:
diff changeset
270 static int sse_status = SSE_UNKNOWN;
a61af66fc99e Initial load
duke
parents:
diff changeset
271
a61af66fc99e Initial load
duke
parents:
diff changeset
272
a61af66fc99e Initial load
duke
parents:
diff changeset
273 static void check_for_sse_support() {
a61af66fc99e Initial load
duke
parents:
diff changeset
274 if (!VM_Version::supports_sse()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
275 sse_status = SSE_NOT_SUPPORTED;
a61af66fc99e Initial load
duke
parents:
diff changeset
276 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
278 // looking for _sse_hw in libc.so, if it does not exist or
a61af66fc99e Initial load
duke
parents:
diff changeset
279 // the value (int) is 0, OS has no support for SSE
a61af66fc99e Initial load
duke
parents:
diff changeset
280 int *sse_hwp;
a61af66fc99e Initial load
duke
parents:
diff changeset
281 void *h;
a61af66fc99e Initial load
duke
parents:
diff changeset
282
a61af66fc99e Initial load
duke
parents:
diff changeset
283 if ((h=dlopen("/usr/lib/libc.so", RTLD_LAZY)) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
284 //open failed, presume no support for SSE
a61af66fc99e Initial load
duke
parents:
diff changeset
285 sse_status = SSE_NOT_SUPPORTED;
a61af66fc99e Initial load
duke
parents:
diff changeset
286 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
288 if ((sse_hwp = (int *)dlsym(h, "_sse_hw")) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
289 sse_status = SSE_NOT_SUPPORTED;
a61af66fc99e Initial load
duke
parents:
diff changeset
290 } else if (*sse_hwp == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
291 sse_status = SSE_NOT_SUPPORTED;
a61af66fc99e Initial load
duke
parents:
diff changeset
292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
293 dlclose(h);
a61af66fc99e Initial load
duke
parents:
diff changeset
294
a61af66fc99e Initial load
duke
parents:
diff changeset
295 if (sse_status == SSE_UNKNOWN) {
a61af66fc99e Initial load
duke
parents:
diff changeset
296 bool (*try_sse)() = (bool (*)())sse_check;
a61af66fc99e Initial load
duke
parents:
diff changeset
297 sse_status = (*try_sse)() ? SSE_SUPPORTED : SSE_NOT_SUPPORTED;
a61af66fc99e Initial load
duke
parents:
diff changeset
298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
299
a61af66fc99e Initial load
duke
parents:
diff changeset
300 }
a61af66fc99e Initial load
duke
parents:
diff changeset
301
585
22e09c0f4b47 6808589: Merge vm_version_x86_{32,64}.{cpp,hpp}
twisti
parents: 477
diff changeset
302 #endif // AMD64
22e09c0f4b47 6808589: Merge vm_version_x86_{32,64}.{cpp,hpp}
twisti
parents: 477
diff changeset
303
0
a61af66fc99e Initial load
duke
parents:
diff changeset
304 bool os::supports_sse() {
585
22e09c0f4b47 6808589: Merge vm_version_x86_{32,64}.{cpp,hpp}
twisti
parents: 477
diff changeset
305 #ifdef AMD64
22e09c0f4b47 6808589: Merge vm_version_x86_{32,64}.{cpp,hpp}
twisti
parents: 477
diff changeset
306 return true;
22e09c0f4b47 6808589: Merge vm_version_x86_{32,64}.{cpp,hpp}
twisti
parents: 477
diff changeset
307 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
308 if (sse_status == SSE_UNKNOWN)
a61af66fc99e Initial load
duke
parents:
diff changeset
309 check_for_sse_support();
a61af66fc99e Initial load
duke
parents:
diff changeset
310 return sse_status == SSE_SUPPORTED;
585
22e09c0f4b47 6808589: Merge vm_version_x86_{32,64}.{cpp,hpp}
twisti
parents: 477
diff changeset
311 #endif // AMD64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
313
a61af66fc99e Initial load
duke
parents:
diff changeset
314 bool os::is_allocatable(size_t bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
315 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
316 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
317 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
318
a61af66fc99e Initial load
duke
parents:
diff changeset
319 if (bytes < 2 * G) {
a61af66fc99e Initial load
duke
parents:
diff changeset
320 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
321 }
a61af66fc99e Initial load
duke
parents:
diff changeset
322
a61af66fc99e Initial load
duke
parents:
diff changeset
323 char* addr = reserve_memory(bytes, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
324
a61af66fc99e Initial load
duke
parents:
diff changeset
325 if (addr != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
326 release_memory(addr, bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
327 }
a61af66fc99e Initial load
duke
parents:
diff changeset
328
a61af66fc99e Initial load
duke
parents:
diff changeset
329 return addr != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
330 #endif // AMD64
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 extern "C" int JVM_handle_solaris_signal(int signo, siginfo_t* siginfo, void* ucontext, int abort_if_unrecognized);
a61af66fc99e Initial load
duke
parents:
diff changeset
335
a61af66fc99e Initial load
duke
parents:
diff changeset
336 extern "C" void Fetch32PFI () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
337 extern "C" void Fetch32Resume () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
338 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
339 extern "C" void FetchNPFI () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
340 extern "C" void FetchNResume () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
341 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
342
a61af66fc99e Initial load
duke
parents:
diff changeset
343 int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrecognized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
344 ucontext_t* uc = (ucontext_t*) ucVoid;
a61af66fc99e Initial load
duke
parents:
diff changeset
345
a61af66fc99e Initial load
duke
parents:
diff changeset
346 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
347 if (sig == SIGILL && info->si_addr == (caddr_t)sse_check) {
a61af66fc99e Initial load
duke
parents:
diff changeset
348 // the SSE instruction faulted. supports_sse() need return false.
a61af66fc99e Initial load
duke
parents:
diff changeset
349 uc->uc_mcontext.gregs[EIP] = (greg_t)sse_unavailable;
a61af66fc99e Initial load
duke
parents:
diff changeset
350 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
352 #endif // !AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
353
a61af66fc99e Initial load
duke
parents:
diff changeset
354 Thread* t = ThreadLocalStorage::get_thread_slow(); // slow & steady
a61af66fc99e Initial load
duke
parents:
diff changeset
355
a61af66fc99e Initial load
duke
parents:
diff changeset
356 SignalHandlerMark shm(t);
a61af66fc99e Initial load
duke
parents:
diff changeset
357
a61af66fc99e Initial load
duke
parents:
diff changeset
358 if(sig == SIGPIPE || sig == SIGXFSZ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
359 if (os::Solaris::chained_handler(sig, info, ucVoid)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
360 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
361 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
362 if (PrintMiscellaneous && (WizardMode || Verbose)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
363 char buf[64];
a61af66fc99e Initial load
duke
parents:
diff changeset
364 warning("Ignoring %s - see 4229104 or 6499219",
a61af66fc99e Initial load
duke
parents:
diff changeset
365 os::exception_name(sig, buf, sizeof(buf)));
a61af66fc99e Initial load
duke
parents:
diff changeset
366
a61af66fc99e Initial load
duke
parents:
diff changeset
367 }
a61af66fc99e Initial load
duke
parents:
diff changeset
368 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
369 }
a61af66fc99e Initial load
duke
parents:
diff changeset
370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
371
a61af66fc99e Initial load
duke
parents:
diff changeset
372 JavaThread* thread = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
373 VMThread* vmthread = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
374
a61af66fc99e Initial load
duke
parents:
diff changeset
375 if (os::Solaris::signal_handlers_are_installed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
376 if (t != NULL ){
a61af66fc99e Initial load
duke
parents:
diff changeset
377 if(t->is_Java_thread()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
378 thread = (JavaThread*)t;
a61af66fc99e Initial load
duke
parents:
diff changeset
379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
380 else if(t->is_VM_thread()){
a61af66fc99e Initial load
duke
parents:
diff changeset
381 vmthread = (VMThread *)t;
a61af66fc99e Initial load
duke
parents:
diff changeset
382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
383 }
a61af66fc99e Initial load
duke
parents:
diff changeset
384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
385
a61af66fc99e Initial load
duke
parents:
diff changeset
386 guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs");
a61af66fc99e Initial load
duke
parents:
diff changeset
387
a61af66fc99e Initial load
duke
parents:
diff changeset
388 if (sig == os::Solaris::SIGasync()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
389 if(thread){
a61af66fc99e Initial load
duke
parents:
diff changeset
390 OSThread::InterruptArguments args(thread, uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
391 thread->osthread()->do_interrupt_callbacks_at_interrupt(&args);
a61af66fc99e Initial load
duke
parents:
diff changeset
392 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
393 }
a61af66fc99e Initial load
duke
parents:
diff changeset
394 else if(vmthread){
a61af66fc99e Initial load
duke
parents:
diff changeset
395 OSThread::InterruptArguments args(vmthread, uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
396 vmthread->osthread()->do_interrupt_callbacks_at_interrupt(&args);
a61af66fc99e Initial load
duke
parents:
diff changeset
397 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
398 } else if (os::Solaris::chained_handler(sig, info, ucVoid)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
399 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
400 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
401 // If os::Solaris::SIGasync not chained, and this is a non-vm and
a61af66fc99e Initial load
duke
parents:
diff changeset
402 // non-java thread
a61af66fc99e Initial load
duke
parents:
diff changeset
403 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
404 }
a61af66fc99e Initial load
duke
parents:
diff changeset
405 }
a61af66fc99e Initial load
duke
parents:
diff changeset
406
a61af66fc99e Initial load
duke
parents:
diff changeset
407 if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // can't decode this kind of signal
a61af66fc99e Initial load
duke
parents:
diff changeset
409 info = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
410 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
411 assert(sig == info->si_signo, "bad siginfo");
a61af66fc99e Initial load
duke
parents:
diff changeset
412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
413
a61af66fc99e Initial load
duke
parents:
diff changeset
414 // decide if this trap can be handled by a stub
a61af66fc99e Initial load
duke
parents:
diff changeset
415 address stub = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
416
a61af66fc99e Initial load
duke
parents:
diff changeset
417 address pc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
418
a61af66fc99e Initial load
duke
parents:
diff changeset
419 //%note os_trap_1
a61af66fc99e Initial load
duke
parents:
diff changeset
420 if (info != NULL && uc != NULL && thread != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // factor me: getPCfromContext
a61af66fc99e Initial load
duke
parents:
diff changeset
422 pc = (address) uc->uc_mcontext.gregs[REG_PC];
a61af66fc99e Initial load
duke
parents:
diff changeset
423
a61af66fc99e Initial load
duke
parents:
diff changeset
424 // SafeFetch32() support
a61af66fc99e Initial load
duke
parents:
diff changeset
425 if (pc == (address) Fetch32PFI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
426 uc->uc_mcontext.gregs[REG_PC] = intptr_t(Fetch32Resume) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
427 return true ;
a61af66fc99e Initial load
duke
parents:
diff changeset
428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
429 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
430 if (pc == (address) FetchNPFI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
431 uc->uc_mcontext.gregs [REG_PC] = intptr_t(FetchNResume) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
432 return true ;
a61af66fc99e Initial load
duke
parents:
diff changeset
433 }
a61af66fc99e Initial load
duke
parents:
diff changeset
434 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
435
a61af66fc99e Initial load
duke
parents:
diff changeset
436 // Handle ALL stack overflow variations here
a61af66fc99e Initial load
duke
parents:
diff changeset
437 if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) {
a61af66fc99e Initial load
duke
parents:
diff changeset
438 address addr = (address) info->si_addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
439 if (thread->in_stack_yellow_zone(addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
440 thread->disable_stack_yellow_zone();
a61af66fc99e Initial load
duke
parents:
diff changeset
441 if (thread->thread_state() == _thread_in_Java) {
a61af66fc99e Initial load
duke
parents:
diff changeset
442 // Throw a stack overflow exception. Guard pages will be reenabled
a61af66fc99e Initial load
duke
parents:
diff changeset
443 // while unwinding the stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
444 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
a61af66fc99e Initial load
duke
parents:
diff changeset
445 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
446 // Thread was in the vm or native code. Return and try to finish.
a61af66fc99e Initial load
duke
parents:
diff changeset
447 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
449 } else if (thread->in_stack_red_zone(addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
450 // Fatal red zone violation. Disable the guard pages and fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
451 // to handle_unexpected_exception way down below.
a61af66fc99e Initial load
duke
parents:
diff changeset
452 thread->disable_stack_red_zone();
a61af66fc99e Initial load
duke
parents:
diff changeset
453 tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
a61af66fc99e Initial load
duke
parents:
diff changeset
454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
455 }
a61af66fc99e Initial load
duke
parents:
diff changeset
456
a61af66fc99e Initial load
duke
parents:
diff changeset
457 if (thread->thread_state() == _thread_in_vm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
458 if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
459 stub = StubRoutines::handler_for_unsafe_access();
a61af66fc99e Initial load
duke
parents:
diff changeset
460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
461 }
a61af66fc99e Initial load
duke
parents:
diff changeset
462
a61af66fc99e Initial load
duke
parents:
diff changeset
463 if (thread->thread_state() == _thread_in_Java) {
a61af66fc99e Initial load
duke
parents:
diff changeset
464 // Support Safepoint Polling
a61af66fc99e Initial load
duke
parents:
diff changeset
465 if ( sig == SIGSEGV && os::is_poll_address((address)info->si_addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
466 stub = SharedRuntime::get_poll_stub(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
468 else if (sig == SIGBUS && info->si_code == BUS_OBJERR) {
a61af66fc99e Initial load
duke
parents:
diff changeset
469 // BugId 4454115: A read from a MappedByteBuffer can fault
a61af66fc99e Initial load
duke
parents:
diff changeset
470 // here if the underlying file has been truncated.
a61af66fc99e Initial load
duke
parents:
diff changeset
471 // Do not crash the VM in such a case.
a61af66fc99e Initial load
duke
parents:
diff changeset
472 CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
473 nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
474 if (nm != NULL && nm->has_unsafe_access()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
475 stub = StubRoutines::handler_for_unsafe_access();
a61af66fc99e Initial load
duke
parents:
diff changeset
476 }
a61af66fc99e Initial load
duke
parents:
diff changeset
477 }
a61af66fc99e Initial load
duke
parents:
diff changeset
478 else
a61af66fc99e Initial load
duke
parents:
diff changeset
479 if (sig == SIGFPE && info->si_code == FPE_INTDIV) {
a61af66fc99e Initial load
duke
parents:
diff changeset
480 // integer divide by zero
a61af66fc99e Initial load
duke
parents:
diff changeset
481 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
a61af66fc99e Initial load
duke
parents:
diff changeset
482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
483 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
484 else if (sig == SIGFPE && info->si_code == FPE_FLTDIV) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 // floating-point divide by zero
a61af66fc99e Initial load
duke
parents:
diff changeset
486 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
a61af66fc99e Initial load
duke
parents:
diff changeset
487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
488 else if (sig == SIGFPE && info->si_code == FPE_FLTINV) {
a61af66fc99e Initial load
duke
parents:
diff changeset
489 // The encoding of D2I in i486.ad can cause an exception prior
a61af66fc99e Initial load
duke
parents:
diff changeset
490 // to the fist instruction if there was an invalid operation
a61af66fc99e Initial load
duke
parents:
diff changeset
491 // pending. We want to dismiss that exception. From the win_32
a61af66fc99e Initial load
duke
parents:
diff changeset
492 // side it also seems that if it really was the fist causing
a61af66fc99e Initial load
duke
parents:
diff changeset
493 // the exception that we do the d2i by hand with different
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // rounding. Seems kind of weird. QQQ TODO
a61af66fc99e Initial load
duke
parents:
diff changeset
495 // Note that we take the exception at the NEXT floating point instruction.
a61af66fc99e Initial load
duke
parents:
diff changeset
496 if (pc[0] == 0xDB) {
a61af66fc99e Initial load
duke
parents:
diff changeset
497 assert(pc[0] == 0xDB, "not a FIST opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
498 assert(pc[1] == 0x14, "not a FIST opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
499 assert(pc[2] == 0x24, "not a FIST opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
500 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
501 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
502 assert(pc[-3] == 0xDB, "not an flt invalid opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
503 assert(pc[-2] == 0x14, "not an flt invalid opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
504 assert(pc[-1] == 0x24, "not an flt invalid opcode");
a61af66fc99e Initial load
duke
parents:
diff changeset
505 }
a61af66fc99e Initial load
duke
parents:
diff changeset
506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
507 else if (sig == SIGFPE ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
508 tty->print_cr("caught SIGFPE, info 0x%x.", info->si_code);
a61af66fc99e Initial load
duke
parents:
diff changeset
509 }
a61af66fc99e Initial load
duke
parents:
diff changeset
510 #endif // !AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // QQQ It doesn't seem that we need to do this on x86 because we should be able
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // to return properly from the handler without this extra stuff on the back side.
a61af66fc99e Initial load
duke
parents:
diff changeset
514
a61af66fc99e Initial load
duke
parents:
diff changeset
515 else if (sig == SIGSEGV && info->si_code > 0 && !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
516 // Determination of interpreter/vtable stub/compiled code null exception
a61af66fc99e Initial load
duke
parents:
diff changeset
517 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
518 }
a61af66fc99e Initial load
duke
parents:
diff changeset
519 }
a61af66fc99e Initial load
duke
parents:
diff changeset
520
a61af66fc99e Initial load
duke
parents:
diff changeset
521 // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
a61af66fc99e Initial load
duke
parents:
diff changeset
522 // and the heap gets shrunk before the field access.
a61af66fc99e Initial load
duke
parents:
diff changeset
523 if ((sig == SIGSEGV) || (sig == SIGBUS)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
524 address addr = JNI_FastGetField::find_slowcase_pc(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
525 if (addr != (address)-1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
526 stub = addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
527 }
a61af66fc99e Initial load
duke
parents:
diff changeset
528 }
a61af66fc99e Initial load
duke
parents:
diff changeset
529
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // Check to see if we caught the safepoint code in the
a61af66fc99e Initial load
duke
parents:
diff changeset
531 // process of write protecting the memory serialization page.
a61af66fc99e Initial load
duke
parents:
diff changeset
532 // It write enables the page immediately after protecting it
a61af66fc99e Initial load
duke
parents:
diff changeset
533 // so we can just return to retry the write.
a61af66fc99e Initial load
duke
parents:
diff changeset
534 if ((sig == SIGSEGV) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
535 os::is_memory_serialize_page(thread, (address)info->si_addr)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
536 // Block current thread until the memory serialize page permission restored.
a61af66fc99e Initial load
duke
parents:
diff changeset
537 os::block_on_serialize_page_trap();
a61af66fc99e Initial load
duke
parents:
diff changeset
538 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
539 }
a61af66fc99e Initial load
duke
parents:
diff changeset
540 }
a61af66fc99e Initial load
duke
parents:
diff changeset
541
a61af66fc99e Initial load
duke
parents:
diff changeset
542 // Execution protection violation
a61af66fc99e Initial load
duke
parents:
diff changeset
543 //
a61af66fc99e Initial load
duke
parents:
diff changeset
544 // Preventative code for future versions of Solaris which may
a61af66fc99e Initial load
duke
parents:
diff changeset
545 // enable execution protection when running the 32-bit VM on AMD64.
a61af66fc99e Initial load
duke
parents:
diff changeset
546 //
a61af66fc99e Initial load
duke
parents:
diff changeset
547 // This should be kept as the last step in the triage. We don't
a61af66fc99e Initial load
duke
parents:
diff changeset
548 // have a dedicated trap number for a no-execute fault, so be
a61af66fc99e Initial load
duke
parents:
diff changeset
549 // conservative and allow other handlers the first shot.
a61af66fc99e Initial load
duke
parents:
diff changeset
550 //
a61af66fc99e Initial load
duke
parents:
diff changeset
551 // Note: We don't test that info->si_code == SEGV_ACCERR here.
a61af66fc99e Initial load
duke
parents:
diff changeset
552 // this si_code is so generic that it is almost meaningless; and
a61af66fc99e Initial load
duke
parents:
diff changeset
553 // the si_code for this condition may change in the future.
a61af66fc99e Initial load
duke
parents:
diff changeset
554 // Furthermore, a false-positive should be harmless.
a61af66fc99e Initial load
duke
parents:
diff changeset
555 if (UnguardOnExecutionViolation > 0 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
556 (sig == SIGSEGV || sig == SIGBUS) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
557 uc->uc_mcontext.gregs[TRAPNO] == T_PGFLT) { // page fault
a61af66fc99e Initial load
duke
parents:
diff changeset
558 int page_size = os::vm_page_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
559 address addr = (address) info->si_addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
560 address pc = (address) uc->uc_mcontext.gregs[REG_PC];
a61af66fc99e Initial load
duke
parents:
diff changeset
561 // Make sure the pc and the faulting address are sane.
a61af66fc99e Initial load
duke
parents:
diff changeset
562 //
a61af66fc99e Initial load
duke
parents:
diff changeset
563 // If an instruction spans a page boundary, and the page containing
a61af66fc99e Initial load
duke
parents:
diff changeset
564 // the beginning of the instruction is executable but the following
a61af66fc99e Initial load
duke
parents:
diff changeset
565 // page is not, the pc and the faulting address might be slightly
a61af66fc99e Initial load
duke
parents:
diff changeset
566 // different - we still want to unguard the 2nd page in this case.
a61af66fc99e Initial load
duke
parents:
diff changeset
567 //
a61af66fc99e Initial load
duke
parents:
diff changeset
568 // 15 bytes seems to be a (very) safe value for max instruction size.
a61af66fc99e Initial load
duke
parents:
diff changeset
569 bool pc_is_near_addr =
a61af66fc99e Initial load
duke
parents:
diff changeset
570 (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);
a61af66fc99e Initial load
duke
parents:
diff changeset
571 bool instr_spans_page_boundary =
a61af66fc99e Initial load
duke
parents:
diff changeset
572 (align_size_down((intptr_t) pc ^ (intptr_t) addr,
a61af66fc99e Initial load
duke
parents:
diff changeset
573 (intptr_t) page_size) > 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
574
a61af66fc99e Initial load
duke
parents:
diff changeset
575 if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
576 static volatile address last_addr =
a61af66fc99e Initial load
duke
parents:
diff changeset
577 (address) os::non_memory_address_word();
a61af66fc99e Initial load
duke
parents:
diff changeset
578
a61af66fc99e Initial load
duke
parents:
diff changeset
579 // In conservative mode, don't unguard unless the address is in the VM
a61af66fc99e Initial load
duke
parents:
diff changeset
580 if (addr != last_addr &&
a61af66fc99e Initial load
duke
parents:
diff changeset
581 (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
582
477
24fda36852ce 6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents: 472
diff changeset
583 // Make memory rwx and retry
0
a61af66fc99e Initial load
duke
parents:
diff changeset
584 address page_start =
a61af66fc99e Initial load
duke
parents:
diff changeset
585 (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: 472
diff changeset
586 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: 472
diff changeset
587 os::MEM_PROT_RWX);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
588
a61af66fc99e Initial load
duke
parents:
diff changeset
589 if (PrintMiscellaneous && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
590 char buf[256];
a61af66fc99e Initial load
duke
parents:
diff changeset
591 jio_snprintf(buf, sizeof(buf), "Execution protection violation "
a61af66fc99e Initial load
duke
parents:
diff changeset
592 "at " INTPTR_FORMAT
a61af66fc99e Initial load
duke
parents:
diff changeset
593 ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr,
a61af66fc99e Initial load
duke
parents:
diff changeset
594 page_start, (res ? "success" : "failed"), errno);
a61af66fc99e Initial load
duke
parents:
diff changeset
595 tty->print_raw_cr(buf);
a61af66fc99e Initial load
duke
parents:
diff changeset
596 }
a61af66fc99e Initial load
duke
parents:
diff changeset
597 stub = pc;
a61af66fc99e Initial load
duke
parents:
diff changeset
598
a61af66fc99e Initial load
duke
parents:
diff changeset
599 // Set last_addr so if we fault again at the same address, we don't end
a61af66fc99e Initial load
duke
parents:
diff changeset
600 // up in an endless loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
601 //
a61af66fc99e Initial load
duke
parents:
diff changeset
602 // There are two potential complications here. Two threads trapping at
a61af66fc99e Initial load
duke
parents:
diff changeset
603 // the same address at the same time could cause one of the threads to
a61af66fc99e Initial load
duke
parents:
diff changeset
604 // think it already unguarded, and abort the VM. Likely very rare.
a61af66fc99e Initial load
duke
parents:
diff changeset
605 //
a61af66fc99e Initial load
duke
parents:
diff changeset
606 // The other race involves two threads alternately trapping at
a61af66fc99e Initial load
duke
parents:
diff changeset
607 // different addresses and failing to unguard the page, resulting in
a61af66fc99e Initial load
duke
parents:
diff changeset
608 // an endless loop. This condition is probably even more unlikely than
a61af66fc99e Initial load
duke
parents:
diff changeset
609 // the first.
a61af66fc99e Initial load
duke
parents:
diff changeset
610 //
a61af66fc99e Initial load
duke
parents:
diff changeset
611 // Although both cases could be avoided by using locks or thread local
a61af66fc99e Initial load
duke
parents:
diff changeset
612 // last_addr, these solutions are unnecessary complication: this
a61af66fc99e Initial load
duke
parents:
diff changeset
613 // handler is a best-effort safety net, not a complete solution. It is
a61af66fc99e Initial load
duke
parents:
diff changeset
614 // disabled by default and should only be used as a workaround in case
a61af66fc99e Initial load
duke
parents:
diff changeset
615 // we missed any no-execute-unsafe VM code.
a61af66fc99e Initial load
duke
parents:
diff changeset
616
a61af66fc99e Initial load
duke
parents:
diff changeset
617 last_addr = addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
618 }
a61af66fc99e Initial load
duke
parents:
diff changeset
619 }
a61af66fc99e Initial load
duke
parents:
diff changeset
620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
621
a61af66fc99e Initial load
duke
parents:
diff changeset
622 if (stub != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
623 // save all thread context in case we need to restore it
a61af66fc99e Initial load
duke
parents:
diff changeset
624
a61af66fc99e Initial load
duke
parents:
diff changeset
625 if (thread != NULL) thread->set_saved_exception_pc(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
626 // 12/02/99: On Sparc it appears that the full context is also saved
a61af66fc99e Initial load
duke
parents:
diff changeset
627 // but as yet, no one looks at or restores that saved context
a61af66fc99e Initial load
duke
parents:
diff changeset
628 // factor me: setPC
a61af66fc99e Initial load
duke
parents:
diff changeset
629 uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub;
a61af66fc99e Initial load
duke
parents:
diff changeset
630 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
632
a61af66fc99e Initial load
duke
parents:
diff changeset
633 // signal-chaining
a61af66fc99e Initial load
duke
parents:
diff changeset
634 if (os::Solaris::chained_handler(sig, info, ucVoid)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
635 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
636 }
a61af66fc99e Initial load
duke
parents:
diff changeset
637
a61af66fc99e Initial load
duke
parents:
diff changeset
638 #ifndef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
639 // Workaround (bug 4900493) for Solaris kernel bug 4966651.
a61af66fc99e Initial load
duke
parents:
diff changeset
640 // Handle an undefined selector caused by an attempt to assign
a61af66fc99e Initial load
duke
parents:
diff changeset
641 // fs in libthread getipriptr(). With the current libthread design every 512
a61af66fc99e Initial load
duke
parents:
diff changeset
642 // thread creations the LDT for a private thread data structure is extended
a61af66fc99e Initial load
duke
parents:
diff changeset
643 // and thre is a hazard that and another thread attempting a thread creation
a61af66fc99e Initial load
duke
parents:
diff changeset
644 // will use a stale LDTR that doesn't reflect the structure's growth,
a61af66fc99e Initial load
duke
parents:
diff changeset
645 // causing a GP fault.
a61af66fc99e Initial load
duke
parents:
diff changeset
646 // Enforce the probable limit of passes through here to guard against an
a61af66fc99e Initial load
duke
parents:
diff changeset
647 // infinite loop if some other move to fs caused the GP fault. Note that
a61af66fc99e Initial load
duke
parents:
diff changeset
648 // this loop counter is ultimately a heuristic as it is possible for
a61af66fc99e Initial load
duke
parents:
diff changeset
649 // more than one thread to generate this fault at a time in an MP system.
a61af66fc99e Initial load
duke
parents:
diff changeset
650 // In the case of the loop count being exceeded or if the poll fails
a61af66fc99e Initial load
duke
parents:
diff changeset
651 // just fall through to a fatal error.
a61af66fc99e Initial load
duke
parents:
diff changeset
652 // If there is some other source of T_GPFLT traps and the text at EIP is
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // unreadable this code will loop infinitely until the stack is exausted.
a61af66fc99e Initial load
duke
parents:
diff changeset
654 // The key to diagnosis in this case is to look for the bottom signal handler
a61af66fc99e Initial load
duke
parents:
diff changeset
655 // frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
656
a61af66fc99e Initial load
duke
parents:
diff changeset
657 if(! IgnoreLibthreadGPFault) {
a61af66fc99e Initial load
duke
parents:
diff changeset
658 if (sig == SIGSEGV && uc->uc_mcontext.gregs[TRAPNO] == T_GPFLT) {
a61af66fc99e Initial load
duke
parents:
diff changeset
659 const unsigned char *p =
a61af66fc99e Initial load
duke
parents:
diff changeset
660 (unsigned const char *) uc->uc_mcontext.gregs[EIP];
a61af66fc99e Initial load
duke
parents:
diff changeset
661
a61af66fc99e Initial load
duke
parents:
diff changeset
662 // Expected instruction?
a61af66fc99e Initial load
duke
parents:
diff changeset
663
a61af66fc99e Initial load
duke
parents:
diff changeset
664 if(p[0] == movlfs[0] && p[1] == movlfs[1]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
665
a61af66fc99e Initial load
duke
parents:
diff changeset
666 Atomic::inc(&ldtr_refresh);
a61af66fc99e Initial load
duke
parents:
diff changeset
667
a61af66fc99e Initial load
duke
parents:
diff changeset
668 // Infinite loop?
a61af66fc99e Initial load
duke
parents:
diff changeset
669
a61af66fc99e Initial load
duke
parents:
diff changeset
670 if(ldtr_refresh < ((2 << 16) / PAGESIZE)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
671
a61af66fc99e Initial load
duke
parents:
diff changeset
672 // No, force scheduling to get a fresh view of the LDTR
a61af66fc99e Initial load
duke
parents:
diff changeset
673
a61af66fc99e Initial load
duke
parents:
diff changeset
674 if(poll(NULL, 0, 10) == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
675
a61af66fc99e Initial load
duke
parents:
diff changeset
676 // Retry the move
a61af66fc99e Initial load
duke
parents:
diff changeset
677
a61af66fc99e Initial load
duke
parents:
diff changeset
678 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
679 }
a61af66fc99e Initial load
duke
parents:
diff changeset
680 }
a61af66fc99e Initial load
duke
parents:
diff changeset
681 }
a61af66fc99e Initial load
duke
parents:
diff changeset
682 }
a61af66fc99e Initial load
duke
parents:
diff changeset
683 }
a61af66fc99e Initial load
duke
parents:
diff changeset
684 #endif // !AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
685
a61af66fc99e Initial load
duke
parents:
diff changeset
686 if (!abort_if_unrecognized) {
a61af66fc99e Initial load
duke
parents:
diff changeset
687 // caller wants another chance, so give it to him
a61af66fc99e Initial load
duke
parents:
diff changeset
688 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
689 }
a61af66fc99e Initial load
duke
parents:
diff changeset
690
a61af66fc99e Initial load
duke
parents:
diff changeset
691 if (!os::Solaris::libjsig_is_loaded) {
a61af66fc99e Initial load
duke
parents:
diff changeset
692 struct sigaction oldAct;
a61af66fc99e Initial load
duke
parents:
diff changeset
693 sigaction(sig, (struct sigaction *)0, &oldAct);
a61af66fc99e Initial load
duke
parents:
diff changeset
694 if (oldAct.sa_sigaction != signalHandler) {
a61af66fc99e Initial load
duke
parents:
diff changeset
695 void* sighand = oldAct.sa_sigaction ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction)
a61af66fc99e Initial load
duke
parents:
diff changeset
696 : CAST_FROM_FN_PTR(void*, oldAct.sa_handler);
605
98cb887364d3 6810672: Comment typos
twisti
parents: 585
diff changeset
697 warning("Unexpected Signal %d occurred under user-defined signal handler %#lx", sig, (long)sighand);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
698 }
a61af66fc99e Initial load
duke
parents:
diff changeset
699 }
a61af66fc99e Initial load
duke
parents:
diff changeset
700
a61af66fc99e Initial load
duke
parents:
diff changeset
701 if (pc == NULL && uc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
702 pc = (address) uc->uc_mcontext.gregs[REG_PC];
a61af66fc99e Initial load
duke
parents:
diff changeset
703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
704
a61af66fc99e Initial load
duke
parents:
diff changeset
705 // unmask current signal
a61af66fc99e Initial load
duke
parents:
diff changeset
706 sigset_t newset;
a61af66fc99e Initial load
duke
parents:
diff changeset
707 sigemptyset(&newset);
a61af66fc99e Initial load
duke
parents:
diff changeset
708 sigaddset(&newset, sig);
a61af66fc99e Initial load
duke
parents:
diff changeset
709 sigprocmask(SIG_UNBLOCK, &newset, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
710
a61af66fc99e Initial load
duke
parents:
diff changeset
711 VMError err(t, sig, pc, info, ucVoid);
a61af66fc99e Initial load
duke
parents:
diff changeset
712 err.report_and_die();
a61af66fc99e Initial load
duke
parents:
diff changeset
713
a61af66fc99e Initial load
duke
parents:
diff changeset
714 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
716
a61af66fc99e Initial load
duke
parents:
diff changeset
717 void os::print_context(outputStream *st, void *context) {
a61af66fc99e Initial load
duke
parents:
diff changeset
718 if (context == NULL) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
719
a61af66fc99e Initial load
duke
parents:
diff changeset
720 ucontext_t *uc = (ucontext_t*)context;
a61af66fc99e Initial load
duke
parents:
diff changeset
721 st->print_cr("Registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
722 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
723 st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
724 st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
725 st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
726 st->print(", RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
727 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
728 st->print( "RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
729 st->print(", RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
730 st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
a61af66fc99e Initial load
duke
parents:
diff changeset
731 st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
a61af66fc99e Initial load
duke
parents:
diff changeset
732 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
733 st->print(", R8=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
a61af66fc99e Initial load
duke
parents:
diff changeset
734 st->print(", R9=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
a61af66fc99e Initial load
duke
parents:
diff changeset
735 st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
a61af66fc99e Initial load
duke
parents:
diff changeset
736 st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
a61af66fc99e Initial load
duke
parents:
diff changeset
737 st->print(", R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
a61af66fc99e Initial load
duke
parents:
diff changeset
738 st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
a61af66fc99e Initial load
duke
parents:
diff changeset
739 st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
a61af66fc99e Initial load
duke
parents:
diff changeset
740 st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
a61af66fc99e Initial load
duke
parents:
diff changeset
741 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
742 st->print( "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
743 st->print(", RFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RFL]);
a61af66fc99e Initial load
duke
parents:
diff changeset
744 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
745 st->print( "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EAX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
746 st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
747 st->print(", ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ECX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
748 st->print(", EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDX]);
a61af66fc99e Initial load
duke
parents:
diff changeset
749 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
750 st->print( "ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[UESP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
751 st->print(", EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
752 st->print(", ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ESI]);
a61af66fc99e Initial load
duke
parents:
diff changeset
753 st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDI]);
a61af66fc99e Initial load
duke
parents:
diff changeset
754 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
755 st->print( "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EIP]);
a61af66fc99e Initial load
duke
parents:
diff changeset
756 st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EFL]);
a61af66fc99e Initial load
duke
parents:
diff changeset
757 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
758 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
759 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
760
a61af66fc99e Initial load
duke
parents:
diff changeset
761 intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
762 st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
a61af66fc99e Initial load
duke
parents:
diff changeset
763 print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t));
a61af66fc99e Initial load
duke
parents:
diff changeset
764 st->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
765
a61af66fc99e Initial load
duke
parents:
diff changeset
766 // Note: it may be unsafe to inspect memory near pc. For example, pc may
a61af66fc99e Initial load
duke
parents:
diff changeset
767 // point to garbage if entry point in an nmethod is corrupted. Leave
a61af66fc99e Initial load
duke
parents:
diff changeset
768 // this at the end, and hope for the best.
a61af66fc99e Initial load
duke
parents:
diff changeset
769 ExtendedPC epc = os::Solaris::ucontext_get_ExtendedPC(uc);
a61af66fc99e Initial load
duke
parents:
diff changeset
770 address pc = epc.pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
771 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
772 print_hex_dump(st, pc - 16, pc + 16, sizeof(char));
a61af66fc99e Initial load
duke
parents:
diff changeset
773 }
a61af66fc99e Initial load
duke
parents:
diff changeset
774
a61af66fc99e Initial load
duke
parents:
diff changeset
775 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
776 void os::Solaris::init_thread_fpu_state(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
777 // Nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
778 }
a61af66fc99e Initial load
duke
parents:
diff changeset
779 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
780 // From solaris_i486.s
a61af66fc99e Initial load
duke
parents:
diff changeset
781 extern "C" void fixcw();
a61af66fc99e Initial load
duke
parents:
diff changeset
782
a61af66fc99e Initial load
duke
parents:
diff changeset
783 void os::Solaris::init_thread_fpu_state(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
784 // Set fpu to 53 bit precision. This happens too early to use a stub.
a61af66fc99e Initial load
duke
parents:
diff changeset
785 fixcw();
a61af66fc99e Initial load
duke
parents:
diff changeset
786 }
a61af66fc99e Initial load
duke
parents:
diff changeset
787
a61af66fc99e Initial load
duke
parents:
diff changeset
788 // These routines are the initial value of atomic_xchg_entry(),
a61af66fc99e Initial load
duke
parents:
diff changeset
789 // atomic_cmpxchg_entry(), atomic_inc_entry() and fence_entry()
a61af66fc99e Initial load
duke
parents:
diff changeset
790 // until initialization is complete.
a61af66fc99e Initial load
duke
parents:
diff changeset
791 // TODO - replace with .il implementation when compiler supports it.
a61af66fc99e Initial load
duke
parents:
diff changeset
792
a61af66fc99e Initial load
duke
parents:
diff changeset
793 typedef jint xchg_func_t (jint, volatile jint*);
a61af66fc99e Initial load
duke
parents:
diff changeset
794 typedef jint cmpxchg_func_t (jint, volatile jint*, jint);
a61af66fc99e Initial load
duke
parents:
diff changeset
795 typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong);
a61af66fc99e Initial load
duke
parents:
diff changeset
796 typedef jint add_func_t (jint, volatile jint*);
a61af66fc99e Initial load
duke
parents:
diff changeset
797
a61af66fc99e Initial load
duke
parents:
diff changeset
798 jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) {
a61af66fc99e Initial load
duke
parents:
diff changeset
799 // try to use the stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
800 xchg_func_t* func = CAST_TO_FN_PTR(xchg_func_t*, StubRoutines::atomic_xchg_entry());
a61af66fc99e Initial load
duke
parents:
diff changeset
801
a61af66fc99e Initial load
duke
parents:
diff changeset
802 if (func != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
803 os::atomic_xchg_func = func;
a61af66fc99e Initial load
duke
parents:
diff changeset
804 return (*func)(exchange_value, dest);
a61af66fc99e Initial load
duke
parents:
diff changeset
805 }
a61af66fc99e Initial load
duke
parents:
diff changeset
806 assert(Threads::number_of_threads() == 0, "for bootstrap only");
a61af66fc99e Initial load
duke
parents:
diff changeset
807
a61af66fc99e Initial load
duke
parents:
diff changeset
808 jint old_value = *dest;
a61af66fc99e Initial load
duke
parents:
diff changeset
809 *dest = exchange_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
810 return old_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
812
a61af66fc99e Initial load
duke
parents:
diff changeset
813 jint os::atomic_cmpxchg_bootstrap(jint exchange_value, volatile jint* dest, jint compare_value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
814 // try to use the stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
815 cmpxchg_func_t* func = CAST_TO_FN_PTR(cmpxchg_func_t*, StubRoutines::atomic_cmpxchg_entry());
a61af66fc99e Initial load
duke
parents:
diff changeset
816
a61af66fc99e Initial load
duke
parents:
diff changeset
817 if (func != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
818 os::atomic_cmpxchg_func = func;
a61af66fc99e Initial load
duke
parents:
diff changeset
819 return (*func)(exchange_value, dest, compare_value);
a61af66fc99e Initial load
duke
parents:
diff changeset
820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
821 assert(Threads::number_of_threads() == 0, "for bootstrap only");
a61af66fc99e Initial load
duke
parents:
diff changeset
822
a61af66fc99e Initial load
duke
parents:
diff changeset
823 jint old_value = *dest;
a61af66fc99e Initial load
duke
parents:
diff changeset
824 if (old_value == compare_value)
a61af66fc99e Initial load
duke
parents:
diff changeset
825 *dest = exchange_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
826 return old_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
827 }
a61af66fc99e Initial load
duke
parents:
diff changeset
828
a61af66fc99e Initial load
duke
parents:
diff changeset
829 jlong os::atomic_cmpxchg_long_bootstrap(jlong exchange_value, volatile jlong* dest, jlong compare_value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
830 // try to use the stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
831 cmpxchg_long_func_t* func = CAST_TO_FN_PTR(cmpxchg_long_func_t*, StubRoutines::atomic_cmpxchg_long_entry());
a61af66fc99e Initial load
duke
parents:
diff changeset
832
a61af66fc99e Initial load
duke
parents:
diff changeset
833 if (func != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
834 os::atomic_cmpxchg_long_func = func;
a61af66fc99e Initial load
duke
parents:
diff changeset
835 return (*func)(exchange_value, dest, compare_value);
a61af66fc99e Initial load
duke
parents:
diff changeset
836 }
a61af66fc99e Initial load
duke
parents:
diff changeset
837 assert(Threads::number_of_threads() == 0, "for bootstrap only");
a61af66fc99e Initial load
duke
parents:
diff changeset
838
a61af66fc99e Initial load
duke
parents:
diff changeset
839 jlong old_value = *dest;
a61af66fc99e Initial load
duke
parents:
diff changeset
840 if (old_value == compare_value)
a61af66fc99e Initial load
duke
parents:
diff changeset
841 *dest = exchange_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
842 return old_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
843 }
a61af66fc99e Initial load
duke
parents:
diff changeset
844
a61af66fc99e Initial load
duke
parents:
diff changeset
845 jint os::atomic_add_bootstrap(jint add_value, volatile jint* dest) {
a61af66fc99e Initial load
duke
parents:
diff changeset
846 // try to use the stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
847 add_func_t* func = CAST_TO_FN_PTR(add_func_t*, StubRoutines::atomic_add_entry());
a61af66fc99e Initial load
duke
parents:
diff changeset
848
a61af66fc99e Initial load
duke
parents:
diff changeset
849 if (func != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
850 os::atomic_add_func = func;
a61af66fc99e Initial load
duke
parents:
diff changeset
851 return (*func)(add_value, dest);
a61af66fc99e Initial load
duke
parents:
diff changeset
852 }
a61af66fc99e Initial load
duke
parents:
diff changeset
853 assert(Threads::number_of_threads() == 0, "for bootstrap only");
a61af66fc99e Initial load
duke
parents:
diff changeset
854
a61af66fc99e Initial load
duke
parents:
diff changeset
855 return (*dest) += add_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
856 }
a61af66fc99e Initial load
duke
parents:
diff changeset
857
a61af66fc99e Initial load
duke
parents:
diff changeset
858 xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap;
a61af66fc99e Initial load
duke
parents:
diff changeset
859 cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap;
a61af66fc99e Initial load
duke
parents:
diff changeset
860 cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
a61af66fc99e Initial load
duke
parents:
diff changeset
861 add_func_t* os::atomic_add_func = os::atomic_add_bootstrap;
a61af66fc99e Initial load
duke
parents:
diff changeset
862
a61af66fc99e Initial load
duke
parents:
diff changeset
863 extern "C" _solaris_raw_setup_fpu(address ptr);
a61af66fc99e Initial load
duke
parents:
diff changeset
864 void os::setup_fpu() {
a61af66fc99e Initial load
duke
parents:
diff changeset
865 address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std();
a61af66fc99e Initial load
duke
parents:
diff changeset
866 _solaris_raw_setup_fpu(fpu_cntrl);
a61af66fc99e Initial load
duke
parents:
diff changeset
867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
868 #endif // AMD64