Mercurial > hg > truffle
annotate src/os/bsd/vm/os_bsd.cpp @ 12233:40136aa2cdb1
8010722: assert: failed: heap size is too big for compressed oops
Summary: Use conservative assumptions of required alignment for the various garbage collector components into account when determining the maximum heap size that supports compressed oops. Using this conservative value avoids several circular dependencies in the calculation.
Reviewed-by: stefank, dholmes
author | tschatzl |
---|---|
date | Wed, 11 Sep 2013 16:25:02 +0200 |
parents | 4c84d351cca9 |
children | cefad50507d8 2bd38d594b9a |
rev | line source |
---|---|
3960 | 1 /* |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
3960 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 * | |
23 */ | |
24 | |
25 // no precompiled headers | |
26 #include "classfile/classLoader.hpp" | |
27 #include "classfile/systemDictionary.hpp" | |
28 #include "classfile/vmSymbols.hpp" | |
29 #include "code/icBuffer.hpp" | |
30 #include "code/vtableStubs.hpp" | |
31 #include "compiler/compileBroker.hpp" | |
7199
cd3d6a6b95d9
8003240: x86: move MacroAssembler into separate file
twisti
parents:
6966
diff
changeset
|
32 #include "compiler/disassembler.hpp" |
3960 | 33 #include "interpreter/interpreter.hpp" |
34 #include "jvm_bsd.h" | |
35 #include "memory/allocation.inline.hpp" | |
36 #include "memory/filemap.hpp" | |
37 #include "mutex_bsd.inline.hpp" | |
38 #include "oops/oop.inline.hpp" | |
39 #include "os_share_bsd.hpp" | |
40 #include "prims/jniFastGetField.hpp" | |
41 #include "prims/jvm.h" | |
42 #include "prims/jvm_misc.hpp" | |
43 #include "runtime/arguments.hpp" | |
44 #include "runtime/extendedPC.hpp" | |
45 #include "runtime/globals.hpp" | |
46 #include "runtime/interfaceSupport.hpp" | |
47 #include "runtime/java.hpp" | |
48 #include "runtime/javaCalls.hpp" | |
49 #include "runtime/mutexLocker.hpp" | |
50 #include "runtime/objectMonitor.hpp" | |
51 #include "runtime/osThread.hpp" | |
52 #include "runtime/perfMemory.hpp" | |
53 #include "runtime/sharedRuntime.hpp" | |
54 #include "runtime/statSampler.hpp" | |
55 #include "runtime/stubRoutines.hpp" | |
7180
f34d701e952e
8003935: Simplify the needed includes for using Thread::current()
stefank
parents:
6966
diff
changeset
|
56 #include "runtime/thread.inline.hpp" |
3960 | 57 #include "runtime/threadCritical.hpp" |
58 #include "runtime/timer.hpp" | |
59 #include "services/attachListener.hpp" | |
8711
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
60 #include "services/memTracker.hpp" |
3960 | 61 #include "services/runtimeService.hpp" |
62 #include "utilities/decoder.hpp" | |
63 #include "utilities/defaultStream.hpp" | |
64 #include "utilities/events.hpp" | |
65 #include "utilities/growableArray.hpp" | |
66 #include "utilities/vmError.hpp" | |
67 | |
68 // put OS-includes here | |
69 # include <sys/types.h> | |
70 # include <sys/mman.h> | |
71 # include <sys/stat.h> | |
72 # include <sys/select.h> | |
73 # include <pthread.h> | |
74 # include <signal.h> | |
75 # include <errno.h> | |
76 # include <dlfcn.h> | |
77 # include <stdio.h> | |
78 # include <unistd.h> | |
79 # include <sys/resource.h> | |
80 # include <pthread.h> | |
81 # include <sys/stat.h> | |
82 # include <sys/time.h> | |
83 # include <sys/times.h> | |
84 # include <sys/utsname.h> | |
85 # include <sys/socket.h> | |
86 # include <sys/wait.h> | |
87 # include <time.h> | |
88 # include <pwd.h> | |
89 # include <poll.h> | |
90 # include <semaphore.h> | |
91 # include <fcntl.h> | |
92 # include <string.h> | |
93 # include <sys/param.h> | |
94 # include <sys/sysctl.h> | |
95 # include <sys/ipc.h> | |
96 # include <sys/shm.h> | |
97 #ifndef __APPLE__ | |
98 # include <link.h> | |
99 #endif | |
100 # include <stdint.h> | |
101 # include <inttypes.h> | |
102 # include <sys/ioctl.h> | |
103 | |
104 #if defined(__FreeBSD__) || defined(__NetBSD__) | |
105 # include <elf.h> | |
106 #endif | |
107 | |
108 #ifdef __APPLE__ | |
4006 | 109 # include <mach/mach.h> // semaphore_* API |
110 # include <mach-o/dyld.h> | |
111 # include <sys/proc_info.h> | |
112 # include <objc/objc-auto.h> | |
3960 | 113 #endif |
114 | |
115 #ifndef MAP_ANONYMOUS | |
116 #define MAP_ANONYMOUS MAP_ANON | |
117 #endif | |
118 | |
119 #define MAX_PATH (2 * K) | |
120 | |
121 // for timer info max values which include all bits | |
122 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) | |
123 | |
124 #define LARGEPAGES_BIT (1 << 6) | |
125 //////////////////////////////////////////////////////////////////////////////// | |
126 // global variables | |
127 julong os::Bsd::_physical_memory = 0; | |
128 | |
129 | |
130 int (*os::Bsd::_clock_gettime)(clockid_t, struct timespec *) = NULL; | |
131 pthread_t os::Bsd::_main_thread; | |
132 int os::Bsd::_page_size = -1; | |
133 | |
134 static jlong initial_time_count=0; | |
135 | |
136 static int clock_tics_per_sec = 100; | |
137 | |
138 // For diagnostics to print a message once. see run_periodic_checks | |
139 static sigset_t check_signal_done; | |
6918 | 140 static bool check_signals = true; |
3960 | 141 |
142 static pid_t _initial_pid = 0; | |
143 | |
144 /* Signal number used to suspend/resume a thread */ | |
145 | |
146 /* do not use any signal number less than SIGSEGV, see 4355769 */ | |
147 static int SR_signum = SIGUSR2; | |
148 sigset_t SR_sigset; | |
149 | |
150 | |
151 //////////////////////////////////////////////////////////////////////////////// | |
152 // utility functions | |
153 | |
154 static int SR_initialize(); | |
155 | |
156 julong os::available_memory() { | |
157 return Bsd::available_memory(); | |
158 } | |
159 | |
160 julong os::Bsd::available_memory() { | |
161 // XXXBSD: this is just a stopgap implementation | |
162 return physical_memory() >> 2; | |
163 } | |
164 | |
165 julong os::physical_memory() { | |
166 return Bsd::physical_memory(); | |
167 } | |
168 | |
169 //////////////////////////////////////////////////////////////////////////////// | |
170 // environment support | |
171 | |
172 bool os::getenv(const char* name, char* buf, int len) { | |
173 const char* val = ::getenv(name); | |
174 if (val != NULL && strlen(val) < (size_t)len) { | |
175 strcpy(buf, val); | |
176 return true; | |
177 } | |
178 if (len > 0) buf[0] = 0; // return a null string | |
179 return false; | |
180 } | |
181 | |
182 | |
183 // Return true if user is running as root. | |
184 | |
185 bool os::have_special_privileges() { | |
186 static bool init = false; | |
187 static bool privileges = false; | |
188 if (!init) { | |
189 privileges = (getuid() != geteuid()) || (getgid() != getegid()); | |
190 init = true; | |
191 } | |
192 return privileges; | |
193 } | |
194 | |
195 | |
196 | |
197 // Cpu architecture string | |
198 #if defined(ZERO) | |
199 static char cpu_arch[] = ZERO_LIBARCH; | |
200 #elif defined(IA64) | |
201 static char cpu_arch[] = "ia64"; | |
202 #elif defined(IA32) | |
203 static char cpu_arch[] = "i386"; | |
204 #elif defined(AMD64) | |
205 static char cpu_arch[] = "amd64"; | |
206 #elif defined(ARM) | |
207 static char cpu_arch[] = "arm"; | |
208 #elif defined(PPC) | |
209 static char cpu_arch[] = "ppc"; | |
210 #elif defined(SPARC) | |
211 # ifdef _LP64 | |
212 static char cpu_arch[] = "sparcv9"; | |
213 # else | |
214 static char cpu_arch[] = "sparc"; | |
215 # endif | |
216 #else | |
217 #error Add appropriate cpu_arch setting | |
218 #endif | |
219 | |
4846 | 220 // Compiler variant |
221 #ifdef COMPILER2 | |
222 #define COMPILER_VARIANT "server" | |
223 #else | |
224 #define COMPILER_VARIANT "client" | |
225 #endif | |
3960 | 226 |
6918 | 227 |
3960 | 228 void os::Bsd::initialize_system_info() { |
229 int mib[2]; | |
230 size_t len; | |
231 int cpu_val; | |
7626
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
232 julong mem_val; |
3960 | 233 |
234 /* get processors count via hw.ncpus sysctl */ | |
235 mib[0] = CTL_HW; | |
236 mib[1] = HW_NCPU; | |
237 len = sizeof(cpu_val); | |
238 if (sysctl(mib, 2, &cpu_val, &len, NULL, 0) != -1 && cpu_val >= 1) { | |
7626
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
239 assert(len == sizeof(cpu_val), "unexpected data size"); |
3960 | 240 set_processor_count(cpu_val); |
241 } | |
242 else { | |
243 set_processor_count(1); // fallback | |
244 } | |
245 | |
7626
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
246 /* get physical memory via hw.memsize sysctl (hw.memsize is used |
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
247 * since it returns a 64 bit value) |
3960 | 248 */ |
249 mib[0] = CTL_HW; | |
7626
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
250 mib[1] = HW_MEMSIZE; |
3960 | 251 len = sizeof(mem_val); |
7626
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
252 if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) { |
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
253 assert(len == sizeof(mem_val), "unexpected data size"); |
3960 | 254 _physical_memory = mem_val; |
7626
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
255 } else { |
3960 | 256 _physical_memory = 256*1024*1024; // fallback (XXXBSD?) |
7626
c07c102cbad7
8006431: os::Bsd::initialize_system_info() sets _physical_memory too large
brutisso
parents:
7456
diff
changeset
|
257 } |
3960 | 258 |
259 #ifdef __OpenBSD__ | |
260 { | |
261 // limit _physical_memory memory view on OpenBSD since | |
262 // datasize rlimit restricts us anyway. | |
263 struct rlimit limits; | |
264 getrlimit(RLIMIT_DATA, &limits); | |
265 _physical_memory = MIN2(_physical_memory, (julong)limits.rlim_cur); | |
266 } | |
267 #endif | |
268 } | |
269 | |
4006 | 270 #ifdef __APPLE__ |
271 static const char *get_home() { | |
272 const char *home_dir = ::getenv("HOME"); | |
273 if ((home_dir == NULL) || (*home_dir == '\0')) { | |
274 struct passwd *passwd_info = getpwuid(geteuid()); | |
275 if (passwd_info != NULL) { | |
276 home_dir = passwd_info->pw_dir; | |
277 } | |
278 } | |
279 | |
280 return home_dir; | |
281 } | |
282 #endif | |
283 | |
3960 | 284 void os::init_system_properties_values() { |
285 // char arch[12]; | |
286 // sysinfo(SI_ARCHITECTURE, arch, sizeof(arch)); | |
287 | |
288 // The next steps are taken in the product version: | |
289 // | |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
290 // Obtain the JAVA_HOME value from the location of libjvm.so. |
3960 | 291 // This library should be located at: |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
292 // <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm.so. |
3960 | 293 // |
294 // If "/jre/lib/" appears at the right place in the path, then we | |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
295 // assume libjvm.so is installed in a JDK and we use this path. |
3960 | 296 // |
297 // Otherwise exit with message: "Could not create the Java virtual machine." | |
298 // | |
299 // The following extra steps are taken in the debugging version: | |
300 // | |
301 // If "/jre/lib/" does NOT appear at the right place in the path | |
302 // instead of exit check for $JAVA_HOME environment variable. | |
303 // | |
304 // If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>, | |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
305 // then we append a fake suffix "hotspot/libjvm.so" to this path so |
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
306 // it looks like libjvm.so is installed there |
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
307 // <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm.so. |
3960 | 308 // |
309 // Otherwise exit. | |
310 // | |
311 // Important note: if the location of libjvm.so changes this | |
312 // code needs to be changed accordingly. | |
313 | |
314 // The next few definitions allow the code to be verbatim: | |
6197 | 315 #define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal) |
3960 | 316 #define getenv(n) ::getenv(n) |
317 | |
318 /* | |
319 * See ld(1): | |
320 * The linker uses the following search paths to locate required | |
321 * shared libraries: | |
322 * 1: ... | |
323 * ... | |
324 * 7: The default directories, normally /lib and /usr/lib. | |
325 */ | |
326 #ifndef DEFAULT_LIBPATH | |
327 #define DEFAULT_LIBPATH "/lib:/usr/lib" | |
328 #endif | |
329 | |
330 #define EXTENSIONS_DIR "/lib/ext" | |
331 #define ENDORSED_DIR "/lib/endorsed" | |
332 #define REG_DIR "/usr/java/packages" | |
333 | |
4006 | 334 #ifdef __APPLE__ |
335 #define SYS_EXTENSIONS_DIR "/Library/Java/Extensions" | |
336 #define SYS_EXTENSIONS_DIRS SYS_EXTENSIONS_DIR ":/Network" SYS_EXTENSIONS_DIR ":/System" SYS_EXTENSIONS_DIR ":/usr/lib/java" | |
337 const char *user_home_dir = get_home(); | |
338 // the null in SYS_EXTENSIONS_DIRS counts for the size of the colon after user_home_dir | |
339 int system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) + | |
340 sizeof(SYS_EXTENSIONS_DIRS); | |
341 #endif | |
342 | |
3960 | 343 { |
344 /* sysclasspath, java_home, dll_dir */ | |
345 { | |
346 char *home_path; | |
347 char *dll_path; | |
348 char *pslash; | |
349 char buf[MAXPATHLEN]; | |
350 os::jvm_path(buf, sizeof(buf)); | |
351 | |
352 // Found the full path to libjvm.so. | |
353 // Now cut the path to <java_home>/jre if we can. | |
354 *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */ | |
355 pslash = strrchr(buf, '/'); | |
356 if (pslash != NULL) | |
357 *pslash = '\0'; /* get rid of /{client|server|hotspot} */ | |
358 dll_path = malloc(strlen(buf) + 1); | |
359 if (dll_path == NULL) | |
360 return; | |
361 strcpy(dll_path, buf); | |
362 Arguments::set_dll_dir(dll_path); | |
363 | |
364 if (pslash != NULL) { | |
365 pslash = strrchr(buf, '/'); | |
366 if (pslash != NULL) { | |
4006 | 367 *pslash = '\0'; /* get rid of /<arch> (/lib on macosx) */ |
368 #ifndef __APPLE__ | |
3960 | 369 pslash = strrchr(buf, '/'); |
370 if (pslash != NULL) | |
371 *pslash = '\0'; /* get rid of /lib */ | |
4006 | 372 #endif |
3960 | 373 } |
374 } | |
375 | |
376 home_path = malloc(strlen(buf) + 1); | |
377 if (home_path == NULL) | |
378 return; | |
379 strcpy(home_path, buf); | |
380 Arguments::set_java_home(home_path); | |
381 | |
382 if (!set_boot_path('/', ':')) | |
383 return; | |
384 } | |
385 | |
386 /* | |
387 * Where to look for native libraries | |
388 * | |
389 * Note: Due to a legacy implementation, most of the library path | |
390 * is set in the launcher. This was to accomodate linking restrictions | |
391 * on legacy Bsd implementations (which are no longer supported). | |
392 * Eventually, all the library path setting will be done here. | |
393 * | |
394 * However, to prevent the proliferation of improperly built native | |
395 * libraries, the new path component /usr/java/packages is added here. | |
396 * Eventually, all the library path setting will be done here. | |
397 */ | |
398 { | |
399 char *ld_library_path; | |
400 | |
401 /* | |
402 * Construct the invariant part of ld_library_path. Note that the | |
403 * space for the colon and the trailing null are provided by the | |
404 * nulls included by the sizeof operator (so actually we allocate | |
405 * a byte more than necessary). | |
406 */ | |
4006 | 407 #ifdef __APPLE__ |
408 ld_library_path = (char *) malloc(system_ext_size); | |
409 sprintf(ld_library_path, "%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS, user_home_dir); | |
410 #else | |
3960 | 411 ld_library_path = (char *) malloc(sizeof(REG_DIR) + sizeof("/lib/") + |
412 strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH)); | |
413 sprintf(ld_library_path, REG_DIR "/lib/%s:" DEFAULT_LIBPATH, cpu_arch); | |
4006 | 414 #endif |
3960 | 415 |
416 /* | |
417 * Get the user setting of LD_LIBRARY_PATH, and prepended it. It | |
418 * should always exist (until the legacy problem cited above is | |
419 * addressed). | |
420 */ | |
421 #ifdef __APPLE__ | |
4006 | 422 // Prepend the default path with the JAVA_LIBRARY_PATH so that the app launcher code can specify a directory inside an app wrapper |
423 char *l = getenv("JAVA_LIBRARY_PATH"); | |
424 if (l != NULL) { | |
425 char *t = ld_library_path; | |
426 /* That's +1 for the colon and +1 for the trailing '\0' */ | |
427 ld_library_path = (char *) malloc(strlen(l) + 1 + strlen(t) + 1); | |
428 sprintf(ld_library_path, "%s:%s", l, t); | |
429 free(t); | |
430 } | |
431 | |
3960 | 432 char *v = getenv("DYLD_LIBRARY_PATH"); |
433 #else | |
434 char *v = getenv("LD_LIBRARY_PATH"); | |
435 #endif | |
436 if (v != NULL) { | |
437 char *t = ld_library_path; | |
438 /* That's +1 for the colon and +1 for the trailing '\0' */ | |
439 ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1); | |
440 sprintf(ld_library_path, "%s:%s", v, t); | |
4006 | 441 free(t); |
3960 | 442 } |
4960
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
443 |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
444 #ifdef __APPLE__ |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
445 // Apple's Java6 has "." at the beginning of java.library.path. |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
446 // OpenJDK on Windows has "." at the end of java.library.path. |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
447 // OpenJDK on Linux and Solaris don't have "." in java.library.path |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
448 // at all. To ease the transition from Apple's Java6 to OpenJDK7, |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
449 // "." is appended to the end of java.library.path. Yes, this |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
450 // could cause a change in behavior, but Apple's Java6 behavior |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
451 // can be achieved by putting "." at the beginning of the |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
452 // JAVA_LIBRARY_PATH environment variable. |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
453 { |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
454 char *t = ld_library_path; |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
455 // that's +3 for appending ":." and the trailing '\0' |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
456 ld_library_path = (char *) malloc(strlen(t) + 3); |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
457 sprintf(ld_library_path, "%s:%s", t, "."); |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
458 free(t); |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
459 } |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
460 #endif |
86ce3208eb18
7145798: System.loadLibrary does not search current working directory
dcubed
parents:
4854
diff
changeset
|
461 |
3960 | 462 Arguments::set_library_path(ld_library_path); |
463 } | |
464 | |
465 /* | |
466 * Extensions directories. | |
467 * | |
468 * Note that the space for the colon and the trailing null are provided | |
469 * by the nulls included by the sizeof operator (so actually one byte more | |
470 * than necessary is allocated). | |
471 */ | |
472 { | |
4006 | 473 #ifdef __APPLE__ |
474 char *buf = malloc(strlen(Arguments::get_java_home()) + | |
475 sizeof(EXTENSIONS_DIR) + system_ext_size); | |
476 sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" | |
477 SYS_EXTENSIONS_DIRS, user_home_dir, Arguments::get_java_home()); | |
478 #else | |
3960 | 479 char *buf = malloc(strlen(Arguments::get_java_home()) + |
480 sizeof(EXTENSIONS_DIR) + sizeof(REG_DIR) + sizeof(EXTENSIONS_DIR)); | |
481 sprintf(buf, "%s" EXTENSIONS_DIR ":" REG_DIR EXTENSIONS_DIR, | |
482 Arguments::get_java_home()); | |
4006 | 483 #endif |
484 | |
3960 | 485 Arguments::set_ext_dirs(buf); |
486 } | |
487 | |
488 /* Endorsed standards default directory. */ | |
489 { | |
490 char * buf; | |
491 buf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR)); | |
492 sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home()); | |
493 Arguments::set_endorsed_dirs(buf); | |
494 } | |
495 } | |
496 | |
4006 | 497 #ifdef __APPLE__ |
498 #undef SYS_EXTENSIONS_DIR | |
499 #endif | |
3960 | 500 #undef malloc |
501 #undef getenv | |
502 #undef EXTENSIONS_DIR | |
503 #undef ENDORSED_DIR | |
504 | |
505 // Done | |
506 return; | |
507 } | |
508 | |
509 //////////////////////////////////////////////////////////////////////////////// | |
510 // breakpoint support | |
511 | |
512 void os::breakpoint() { | |
513 BREAKPOINT; | |
514 } | |
515 | |
516 extern "C" void breakpoint() { | |
517 // use debugger to set breakpoint here | |
518 } | |
519 | |
520 //////////////////////////////////////////////////////////////////////////////// | |
521 // signal support | |
522 | |
523 debug_only(static bool signal_sets_initialized = false); | |
524 static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs; | |
525 | |
526 bool os::Bsd::is_sig_ignored(int sig) { | |
527 struct sigaction oact; | |
528 sigaction(sig, (struct sigaction*)NULL, &oact); | |
529 void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction) | |
530 : CAST_FROM_FN_PTR(void*, oact.sa_handler); | |
531 if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN)) | |
532 return true; | |
533 else | |
534 return false; | |
535 } | |
536 | |
537 void os::Bsd::signal_sets_init() { | |
538 // Should also have an assertion stating we are still single-threaded. | |
539 assert(!signal_sets_initialized, "Already initialized"); | |
540 // Fill in signals that are necessarily unblocked for all threads in | |
541 // the VM. Currently, we unblock the following signals: | |
542 // SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden | |
543 // by -Xrs (=ReduceSignalUsage)); | |
544 // BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all | |
545 // other threads. The "ReduceSignalUsage" boolean tells us not to alter | |
546 // the dispositions or masks wrt these signals. | |
547 // Programs embedding the VM that want to use the above signals for their | |
548 // own purposes must, at this time, use the "-Xrs" option to prevent | |
549 // interference with shutdown hooks and BREAK_SIGNAL thread dumping. | |
550 // (See bug 4345157, and other related bugs). | |
551 // In reality, though, unblocking these signals is really a nop, since | |
552 // these signals are not blocked by default. | |
553 sigemptyset(&unblocked_sigs); | |
554 sigemptyset(&allowdebug_blocked_sigs); | |
555 sigaddset(&unblocked_sigs, SIGILL); | |
556 sigaddset(&unblocked_sigs, SIGSEGV); | |
557 sigaddset(&unblocked_sigs, SIGBUS); | |
558 sigaddset(&unblocked_sigs, SIGFPE); | |
559 sigaddset(&unblocked_sigs, SR_signum); | |
560 | |
561 if (!ReduceSignalUsage) { | |
562 if (!os::Bsd::is_sig_ignored(SHUTDOWN1_SIGNAL)) { | |
563 sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL); | |
564 sigaddset(&allowdebug_blocked_sigs, SHUTDOWN1_SIGNAL); | |
565 } | |
566 if (!os::Bsd::is_sig_ignored(SHUTDOWN2_SIGNAL)) { | |
567 sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL); | |
568 sigaddset(&allowdebug_blocked_sigs, SHUTDOWN2_SIGNAL); | |
569 } | |
570 if (!os::Bsd::is_sig_ignored(SHUTDOWN3_SIGNAL)) { | |
571 sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL); | |
572 sigaddset(&allowdebug_blocked_sigs, SHUTDOWN3_SIGNAL); | |
573 } | |
574 } | |
575 // Fill in signals that are blocked by all but the VM thread. | |
576 sigemptyset(&vm_sigs); | |
577 if (!ReduceSignalUsage) | |
578 sigaddset(&vm_sigs, BREAK_SIGNAL); | |
579 debug_only(signal_sets_initialized = true); | |
580 | |
581 } | |
582 | |
583 // These are signals that are unblocked while a thread is running Java. | |
584 // (For some reason, they get blocked by default.) | |
585 sigset_t* os::Bsd::unblocked_signals() { | |
586 assert(signal_sets_initialized, "Not initialized"); | |
587 return &unblocked_sigs; | |
588 } | |
589 | |
590 // These are the signals that are blocked while a (non-VM) thread is | |
591 // running Java. Only the VM thread handles these signals. | |
592 sigset_t* os::Bsd::vm_signals() { | |
593 assert(signal_sets_initialized, "Not initialized"); | |
594 return &vm_sigs; | |
595 } | |
596 | |
597 // These are signals that are blocked during cond_wait to allow debugger in | |
598 sigset_t* os::Bsd::allowdebug_blocked_signals() { | |
599 assert(signal_sets_initialized, "Not initialized"); | |
600 return &allowdebug_blocked_sigs; | |
601 } | |
602 | |
603 void os::Bsd::hotspot_sigmask(Thread* thread) { | |
604 | |
605 //Save caller's signal mask before setting VM signal mask | |
606 sigset_t caller_sigmask; | |
607 pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask); | |
608 | |
609 OSThread* osthread = thread->osthread(); | |
610 osthread->set_caller_sigmask(caller_sigmask); | |
611 | |
612 pthread_sigmask(SIG_UNBLOCK, os::Bsd::unblocked_signals(), NULL); | |
613 | |
614 if (!ReduceSignalUsage) { | |
615 if (thread->is_VM_thread()) { | |
616 // Only the VM thread handles BREAK_SIGNAL ... | |
617 pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL); | |
618 } else { | |
619 // ... all other threads block BREAK_SIGNAL | |
620 pthread_sigmask(SIG_BLOCK, vm_signals(), NULL); | |
621 } | |
622 } | |
623 } | |
624 | |
625 | |
626 ////////////////////////////////////////////////////////////////////////////// | |
627 // create new thread | |
628 | |
629 // check if it's safe to start a new thread | |
630 static bool _thread_safety_check(Thread* thread) { | |
6918 | 631 return true; |
3960 | 632 } |
633 | |
4006 | 634 #ifdef __APPLE__ |
635 // library handle for calling objc_registerThreadWithCollector() | |
636 // without static linking to the libobjc library | |
637 #define OBJC_LIB "/usr/lib/libobjc.dylib" | |
638 #define OBJC_GCREGISTER "objc_registerThreadWithCollector" | |
639 typedef void (*objc_registerThreadWithCollector_t)(); | |
640 extern "C" objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction; | |
641 objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL; | |
642 #endif | |
643 | |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
644 #ifdef __APPLE__ |
12095 | 645 static uint64_t locate_unique_thread_id(mach_port_t mach_thread_port) { |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
646 // Additional thread_id used to correlate threads in SA |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
647 thread_identifier_info_data_t m_ident_info; |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
648 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
649 |
12095 | 650 thread_info(mach_thread_port, THREAD_IDENTIFIER_INFO, |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
651 (thread_info_t) &m_ident_info, &count); |
12095 | 652 |
8023
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
653 return m_ident_info.thread_id; |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
654 } |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
655 #endif |
758935f7c23f
8006423: SA: NullPointerException in sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:67)
sla
parents:
7629
diff
changeset
|
656 |
3960 | 657 // Thread start routine for all newly created threads |
658 static void *java_start(Thread *thread) { | |
659 // Try to randomize the cache line index of hot stack frames. | |
660 // This helps when threads of the same stack traces evict each other's | |
661 // cache lines. The threads can be either from the same JVM instance, or | |
662 // from different JVM instances. The benefit is especially true for | |
663 // processors with hyperthreading technology. | |
664 static int counter = 0; | |
665 int pid = os::current_process_id(); | |
666 alloca(((pid ^ counter++) & 7) * 128); | |
667 | |
668 ThreadLocalStorage::set_thread(thread); | |
669 | |
670 OSThread* osthread = thread->osthread(); | |
671 Monitor* sync = osthread->startThread_lock(); | |
672 | |
673 // non floating stack BsdThreads needs extra check, see above | |
674 if (!_thread_safety_check(thread)) { | |
675 // notify parent thread | |
676 MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); | |
677 osthread->set_state(ZOMBIE); | |
678 sync->notify_all(); | |
679 return NULL; | |
680 } | |
681 | |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
682 #ifdef __APPLE__ |
12095 | 683 // thread_id is mach thread on macos, which pthreads graciously caches and provides for us |
684 mach_port_t thread_id = ::pthread_mach_thread_np(::pthread_self()); | |
685 guarantee(thread_id != 0, "thread id missing from pthreads"); | |
686 osthread->set_thread_id(thread_id); | |
687 | |
688 uint64_t unique_thread_id = locate_unique_thread_id(thread_id); | |
689 guarantee(unique_thread_id != 0, "unique thread id was not found"); | |
690 osthread->set_unique_thread_id(unique_thread_id); | |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
691 #else |
3960 | 692 // thread_id is pthread_id on BSD |
693 osthread->set_thread_id(::pthread_self()); | |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
694 #endif |
3960 | 695 // initialize signal mask for this thread |
696 os::Bsd::hotspot_sigmask(thread); | |
697 | |
698 // initialize floating point control register | |
699 os::Bsd::init_thread_fpu_state(); | |
700 | |
4006 | 701 #ifdef __APPLE__ |
702 // register thread with objc gc | |
703 if (objc_registerThreadWithCollectorFunction != NULL) { | |
704 objc_registerThreadWithCollectorFunction(); | |
705 } | |
706 #endif | |
707 | |
3960 | 708 // handshaking with parent thread |
709 { | |
710 MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); | |
711 | |
712 // notify parent thread | |
713 osthread->set_state(INITIALIZED); | |
714 sync->notify_all(); | |
715 | |
716 // wait until os::start_thread() | |
717 while (osthread->get_state() == INITIALIZED) { | |
718 sync->wait(Mutex::_no_safepoint_check_flag); | |
719 } | |
720 } | |
721 | |
722 // call one more level start routine | |
723 thread->run(); | |
724 | |
725 return 0; | |
726 } | |
727 | |
728 bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { | |
729 assert(thread->osthread() == NULL, "caller responsible"); | |
730 | |
731 // Allocate the OSThread object | |
732 OSThread* osthread = new OSThread(NULL, NULL); | |
733 if (osthread == NULL) { | |
734 return false; | |
735 } | |
736 | |
737 // set the correct thread state | |
738 osthread->set_thread_type(thr_type); | |
739 | |
740 // Initial state is ALLOCATED but not INITIALIZED | |
741 osthread->set_state(ALLOCATED); | |
742 | |
743 thread->set_osthread(osthread); | |
744 | |
745 // init thread attributes | |
746 pthread_attr_t attr; | |
747 pthread_attr_init(&attr); | |
748 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | |
749 | |
750 // stack size | |
751 if (os::Bsd::supports_variable_stack_size()) { | |
752 // calculate stack size if it's not specified by caller | |
753 if (stack_size == 0) { | |
754 stack_size = os::Bsd::default_stack_size(thr_type); | |
755 | |
756 switch (thr_type) { | |
757 case os::java_thread: | |
758 // Java threads use ThreadStackSize which default value can be | |
759 // changed with the flag -Xss | |
760 assert (JavaThread::stack_size_at_create() > 0, "this should be set"); | |
761 stack_size = JavaThread::stack_size_at_create(); | |
762 break; | |
763 case os::compiler_thread: | |
764 if (CompilerThreadStackSize > 0) { | |
765 stack_size = (size_t)(CompilerThreadStackSize * K); | |
766 break; | |
767 } // else fall through: | |
768 // use VMThreadStackSize if CompilerThreadStackSize is not defined | |
769 case os::vm_thread: | |
770 case os::pgc_thread: | |
771 case os::cgc_thread: | |
772 case os::watcher_thread: | |
773 if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); | |
774 break; | |
775 } | |
776 } | |
777 | |
778 stack_size = MAX2(stack_size, os::Bsd::min_stack_allowed); | |
779 pthread_attr_setstacksize(&attr, stack_size); | |
780 } else { | |
781 // let pthread_create() pick the default value. | |
782 } | |
783 | |
784 ThreadState state; | |
785 | |
786 { | |
787 pthread_t tid; | |
788 int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); | |
789 | |
790 pthread_attr_destroy(&attr); | |
791 | |
792 if (ret != 0) { | |
793 if (PrintMiscellaneous && (Verbose || WizardMode)) { | |
794 perror("pthread_create()"); | |
795 } | |
796 // Need to clean up stuff we've allocated so far | |
797 thread->set_osthread(NULL); | |
798 delete osthread; | |
799 return false; | |
800 } | |
801 | |
802 // Store pthread info into the OSThread | |
803 osthread->set_pthread_id(tid); | |
804 | |
805 // Wait until child thread is either initialized or aborted | |
806 { | |
807 Monitor* sync_with_child = osthread->startThread_lock(); | |
808 MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); | |
809 while ((state = osthread->get_state()) == ALLOCATED) { | |
810 sync_with_child->wait(Mutex::_no_safepoint_check_flag); | |
811 } | |
812 } | |
813 | |
814 } | |
815 | |
816 // Aborted due to thread limit being reached | |
817 if (state == ZOMBIE) { | |
818 thread->set_osthread(NULL); | |
819 delete osthread; | |
820 return false; | |
821 } | |
822 | |
823 // The thread is returned suspended (in state INITIALIZED), | |
824 // and is started higher up in the call chain | |
825 assert(state == INITIALIZED, "race condition"); | |
826 return true; | |
827 } | |
828 | |
829 ///////////////////////////////////////////////////////////////////////////// | |
830 // attach existing thread | |
831 | |
832 // bootstrap the main thread | |
833 bool os::create_main_thread(JavaThread* thread) { | |
834 assert(os::Bsd::_main_thread == pthread_self(), "should be called inside main thread"); | |
835 return create_attached_thread(thread); | |
836 } | |
837 | |
838 bool os::create_attached_thread(JavaThread* thread) { | |
839 #ifdef ASSERT | |
840 thread->verify_not_published(); | |
841 #endif | |
842 | |
843 // Allocate the OSThread object | |
844 OSThread* osthread = new OSThread(NULL, NULL); | |
845 | |
846 if (osthread == NULL) { | |
847 return false; | |
848 } | |
849 | |
850 // Store pthread info into the OSThread | |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
851 #ifdef __APPLE__ |
12095 | 852 // thread_id is mach thread on macos, which pthreads graciously caches and provides for us |
853 mach_port_t thread_id = ::pthread_mach_thread_np(::pthread_self()); | |
854 guarantee(thread_id != 0, "just checking"); | |
855 osthread->set_thread_id(thread_id); | |
856 | |
857 uint64_t unique_thread_id = locate_unique_thread_id(thread_id); | |
858 guarantee(unique_thread_id != 0, "just checking"); | |
859 osthread->set_unique_thread_id(unique_thread_id); | |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
860 #else |
3960 | 861 osthread->set_thread_id(::pthread_self()); |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
862 #endif |
3960 | 863 osthread->set_pthread_id(::pthread_self()); |
864 | |
865 // initialize floating point control register | |
866 os::Bsd::init_thread_fpu_state(); | |
867 | |
868 // Initial thread state is RUNNABLE | |
869 osthread->set_state(RUNNABLE); | |
870 | |
871 thread->set_osthread(osthread); | |
872 | |
873 // initialize signal mask for this thread | |
874 // and save the caller's signal mask | |
875 os::Bsd::hotspot_sigmask(thread); | |
876 | |
877 return true; | |
878 } | |
879 | |
880 void os::pd_start_thread(Thread* thread) { | |
881 OSThread * osthread = thread->osthread(); | |
882 assert(osthread->get_state() != INITIALIZED, "just checking"); | |
883 Monitor* sync_with_child = osthread->startThread_lock(); | |
884 MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); | |
885 sync_with_child->notify(); | |
886 } | |
887 | |
888 // Free Bsd resources related to the OSThread | |
889 void os::free_thread(OSThread* osthread) { | |
890 assert(osthread != NULL, "osthread not set"); | |
891 | |
892 if (Thread::current()->osthread() == osthread) { | |
893 // Restore caller's signal mask | |
894 sigset_t sigmask = osthread->caller_sigmask(); | |
895 pthread_sigmask(SIG_SETMASK, &sigmask, NULL); | |
896 } | |
897 | |
898 delete osthread; | |
899 } | |
900 | |
901 ////////////////////////////////////////////////////////////////////////////// | |
902 // thread local storage | |
903 | |
904 int os::allocate_thread_local_storage() { | |
905 pthread_key_t key; | |
906 int rslt = pthread_key_create(&key, NULL); | |
907 assert(rslt == 0, "cannot allocate thread local storage"); | |
908 return (int)key; | |
909 } | |
910 | |
911 // Note: This is currently not used by VM, as we don't destroy TLS key | |
912 // on VM exit. | |
913 void os::free_thread_local_storage(int index) { | |
914 int rslt = pthread_key_delete((pthread_key_t)index); | |
915 assert(rslt == 0, "invalid index"); | |
916 } | |
917 | |
918 void os::thread_local_storage_at_put(int index, void* value) { | |
919 int rslt = pthread_setspecific((pthread_key_t)index, value); | |
920 assert(rslt == 0, "pthread_setspecific failed"); | |
921 } | |
922 | |
923 extern "C" Thread* get_thread() { | |
924 return ThreadLocalStorage::thread(); | |
925 } | |
926 | |
927 | |
928 //////////////////////////////////////////////////////////////////////////////// | |
929 // time support | |
930 | |
931 // Time since start-up in seconds to a fine granularity. | |
932 // Used by VMSelfDestructTimer and the MemProfiler. | |
933 double os::elapsedTime() { | |
934 | |
935 return (double)(os::elapsed_counter()) * 0.000001; | |
936 } | |
937 | |
938 jlong os::elapsed_counter() { | |
939 timeval time; | |
940 int status = gettimeofday(&time, NULL); | |
941 return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count; | |
942 } | |
943 | |
944 jlong os::elapsed_frequency() { | |
945 return (1000 * 1000); | |
946 } | |
947 | |
10372
e72f7eecc96d
8013895: G1: G1SummarizeRSetStats output on Linux needs improvemen
tschatzl
parents:
10208
diff
changeset
|
948 bool os::supports_vtime() { return true; } |
3960 | 949 bool os::enable_vtime() { return false; } |
950 bool os::vtime_enabled() { return false; } | |
10372
e72f7eecc96d
8013895: G1: G1SummarizeRSetStats output on Linux needs improvemen
tschatzl
parents:
10208
diff
changeset
|
951 |
3960 | 952 double os::elapsedVTime() { |
953 // better than nothing, but not much | |
954 return elapsedTime(); | |
955 } | |
956 | |
957 jlong os::javaTimeMillis() { | |
958 timeval time; | |
959 int status = gettimeofday(&time, NULL); | |
960 assert(status != -1, "bsd error"); | |
961 return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000); | |
962 } | |
963 | |
964 #ifndef CLOCK_MONOTONIC | |
965 #define CLOCK_MONOTONIC (1) | |
966 #endif | |
967 | |
968 #ifdef __APPLE__ | |
969 void os::Bsd::clock_init() { | |
970 // XXXDARWIN: Investigate replacement monotonic clock | |
971 } | |
6918 | 972 #else |
3960 | 973 void os::Bsd::clock_init() { |
974 struct timespec res; | |
975 struct timespec tp; | |
976 if (::clock_getres(CLOCK_MONOTONIC, &res) == 0 && | |
977 ::clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { | |
978 // yes, monotonic clock is supported | |
979 _clock_gettime = ::clock_gettime; | |
980 } | |
981 } | |
982 #endif | |
983 | |
984 | |
985 jlong os::javaTimeNanos() { | |
986 if (Bsd::supports_monotonic_clock()) { | |
987 struct timespec tp; | |
988 int status = Bsd::clock_gettime(CLOCK_MONOTONIC, &tp); | |
989 assert(status == 0, "gettime error"); | |
990 jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec); | |
991 return result; | |
992 } else { | |
993 timeval time; | |
994 int status = gettimeofday(&time, NULL); | |
995 assert(status != -1, "bsd error"); | |
996 jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec); | |
997 return 1000 * usecs; | |
998 } | |
999 } | |
1000 | |
1001 void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { | |
1002 if (Bsd::supports_monotonic_clock()) { | |
1003 info_ptr->max_value = ALL_64_BITS; | |
1004 | |
1005 // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past | |
1006 info_ptr->may_skip_backward = false; // not subject to resetting or drifting | |
1007 info_ptr->may_skip_forward = false; // not subject to resetting or drifting | |
1008 } else { | |
1009 // gettimeofday - based on time in seconds since the Epoch thus does not wrap | |
1010 info_ptr->max_value = ALL_64_BITS; | |
1011 | |
1012 // gettimeofday is a real time clock so it skips | |
1013 info_ptr->may_skip_backward = true; | |
1014 info_ptr->may_skip_forward = true; | |
1015 } | |
1016 | |
1017 info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time | |
1018 } | |
1019 | |
1020 // Return the real, user, and system times in seconds from an | |
1021 // arbitrary fixed point in the past. | |
1022 bool os::getTimesSecs(double* process_real_time, | |
1023 double* process_user_time, | |
1024 double* process_system_time) { | |
1025 struct tms ticks; | |
1026 clock_t real_ticks = times(&ticks); | |
1027 | |
1028 if (real_ticks == (clock_t) (-1)) { | |
1029 return false; | |
1030 } else { | |
1031 double ticks_per_second = (double) clock_tics_per_sec; | |
1032 *process_user_time = ((double) ticks.tms_utime) / ticks_per_second; | |
1033 *process_system_time = ((double) ticks.tms_stime) / ticks_per_second; | |
1034 *process_real_time = ((double) real_ticks) / ticks_per_second; | |
1035 | |
1036 return true; | |
1037 } | |
1038 } | |
1039 | |
1040 | |
1041 char * os::local_time_string(char *buf, size_t buflen) { | |
1042 struct tm t; | |
1043 time_t long_time; | |
1044 time(&long_time); | |
1045 localtime_r(&long_time, &t); | |
1046 jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d", | |
1047 t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, | |
1048 t.tm_hour, t.tm_min, t.tm_sec); | |
1049 return buf; | |
1050 } | |
1051 | |
1052 struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { | |
1053 return localtime_r(clock, res); | |
1054 } | |
1055 | |
1056 //////////////////////////////////////////////////////////////////////////////// | |
1057 // runtime exit support | |
1058 | |
1059 // Note: os::shutdown() might be called very early during initialization, or | |
1060 // called from signal handler. Before adding something to os::shutdown(), make | |
1061 // sure it is async-safe and can handle partially initialized VM. | |
1062 void os::shutdown() { | |
1063 | |
1064 // allow PerfMemory to attempt cleanup of any persistent resources | |
1065 perfMemory_exit(); | |
1066 | |
1067 // needs to remove object in file system | |
1068 AttachListener::abort(); | |
1069 | |
1070 // flush buffered output, finish log files | |
1071 ostream_abort(); | |
1072 | |
1073 // Check for abort hook | |
1074 abort_hook_t abort_hook = Arguments::abort_hook(); | |
1075 if (abort_hook != NULL) { | |
1076 abort_hook(); | |
1077 } | |
1078 | |
1079 } | |
1080 | |
1081 // Note: os::abort() might be called very early during initialization, or | |
1082 // called from signal handler. Before adding something to os::abort(), make | |
1083 // sure it is async-safe and can handle partially initialized VM. | |
1084 void os::abort(bool dump_core) { | |
1085 os::shutdown(); | |
1086 if (dump_core) { | |
1087 #ifndef PRODUCT | |
1088 fdStream out(defaultStream::output_fd()); | |
1089 out.print_raw("Current thread is "); | |
1090 char buf[16]; | |
1091 jio_snprintf(buf, sizeof(buf), UINTX_FORMAT, os::current_thread_id()); | |
1092 out.print_raw_cr(buf); | |
1093 out.print_raw_cr("Dumping core ..."); | |
1094 #endif | |
1095 ::abort(); // dump core | |
1096 } | |
1097 | |
1098 ::exit(1); | |
1099 } | |
1100 | |
1101 // Die immediately, no exit hook, no abort hook, no cleanup. | |
1102 void os::die() { | |
1103 // _exit() on BsdThreads only kills current thread | |
1104 ::abort(); | |
1105 } | |
1106 | |
1107 // unused on bsd for now. | |
1108 void os::set_error_file(const char *logfile) {} | |
1109 | |
1110 | |
1111 // This method is a copy of JDK's sysGetLastErrorString | |
1112 // from src/solaris/hpi/src/system_md.c | |
1113 | |
1114 size_t os::lasterror(char *buf, size_t len) { | |
1115 | |
1116 if (errno == 0) return 0; | |
1117 | |
1118 const char *s = ::strerror(errno); | |
1119 size_t n = ::strlen(s); | |
1120 if (n >= len) { | |
1121 n = len - 1; | |
1122 } | |
1123 ::strncpy(buf, s, n); | |
1124 buf[n] = '\0'; | |
1125 return n; | |
1126 } | |
1127 | |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
1128 intx os::current_thread_id() { |
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
1129 #ifdef __APPLE__ |
12095 | 1130 return (intx)::pthread_mach_thread_np(::pthread_self()); |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
1131 #else |
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
1132 return (intx)::pthread_self(); |
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
1133 #endif |
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
1134 } |
3960 | 1135 int os::current_process_id() { |
1136 | |
1137 // Under the old bsd thread library, bsd gives each thread | |
1138 // its own process id. Because of this each thread will return | |
1139 // a different pid if this method were to return the result | |
1140 // of getpid(2). Bsd provides no api that returns the pid | |
1141 // of the launcher thread for the vm. This implementation | |
1142 // returns a unique pid, the pid of the launcher thread | |
1143 // that starts the vm 'process'. | |
1144 | |
1145 // Under the NPTL, getpid() returns the same pid as the | |
1146 // launcher thread rather than a unique pid per thread. | |
1147 // Use gettid() if you want the old pre NPTL behaviour. | |
1148 | |
1149 // if you are looking for the result of a call to getpid() that | |
1150 // returns a unique pid for the calling thread, then look at the | |
1151 // OSThread::thread_id() method in osThread_bsd.hpp file | |
1152 | |
1153 return (int)(_initial_pid ? _initial_pid : getpid()); | |
1154 } | |
1155 | |
1156 // DLL functions | |
1157 | |
1158 #define JNI_LIB_PREFIX "lib" | |
1159 #ifdef __APPLE__ | |
1160 #define JNI_LIB_SUFFIX ".dylib" | |
1161 #else | |
1162 #define JNI_LIB_SUFFIX ".so" | |
1163 #endif | |
1164 | |
1165 const char* os::dll_file_extension() { return JNI_LIB_SUFFIX; } | |
1166 | |
1167 // This must be hard coded because it's the system's temporary | |
1168 // directory not the java application's temp directory, ala java.io.tmpdir. | |
4006 | 1169 #ifdef __APPLE__ |
1170 // macosx has a secure per-user temporary directory | |
1171 char temp_path_storage[PATH_MAX]; | |
1172 const char* os::get_temp_directory() { | |
1173 static char *temp_path = NULL; | |
1174 if (temp_path == NULL) { | |
1175 int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, temp_path_storage, PATH_MAX); | |
1176 if (pathSize == 0 || pathSize > PATH_MAX) { | |
1177 strlcpy(temp_path_storage, "/tmp/", sizeof(temp_path_storage)); | |
1178 } | |
1179 temp_path = temp_path_storage; | |
1180 } | |
1181 return temp_path; | |
1182 } | |
1183 #else /* __APPLE__ */ | |
3960 | 1184 const char* os::get_temp_directory() { return "/tmp"; } |
4006 | 1185 #endif /* __APPLE__ */ |
3960 | 1186 |
1187 static bool file_exists(const char* filename) { | |
1188 struct stat statbuf; | |
1189 if (filename == NULL || strlen(filename) == 0) { | |
1190 return false; | |
1191 } | |
1192 return os::stat(filename, &statbuf) == 0; | |
1193 } | |
1194 | |
6966
6cb0d32b828b
8001185: parsing of sun.boot.library.path in os::dll_build_name somewhat broken
bpittore
parents:
6918
diff
changeset
|
1195 bool os::dll_build_name(char* buffer, size_t buflen, |
3960 | 1196 const char* pname, const char* fname) { |
6966
6cb0d32b828b
8001185: parsing of sun.boot.library.path in os::dll_build_name somewhat broken
bpittore
parents:
6918
diff
changeset
|
1197 bool retval = false; |
3960 | 1198 // Copied from libhpi |
1199 const size_t pnamelen = pname ? strlen(pname) : 0; | |
1200 | |
6966
6cb0d32b828b
8001185: parsing of sun.boot.library.path in os::dll_build_name somewhat broken
bpittore
parents:
6918
diff
changeset
|
1201 // Return error on buffer overflow. |
3960 | 1202 if (pnamelen + strlen(fname) + strlen(JNI_LIB_PREFIX) + strlen(JNI_LIB_SUFFIX) + 2 > buflen) { |
6966
6cb0d32b828b
8001185: parsing of sun.boot.library.path in os::dll_build_name somewhat broken
bpittore
parents:
6918
diff
changeset
|
1203 return retval; |
3960 | 1204 } |
1205 | |
1206 if (pnamelen == 0) { | |
1207 snprintf(buffer, buflen, JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, fname); | |
6966
6cb0d32b828b
8001185: parsing of sun.boot.library.path in os::dll_build_name somewhat broken
bpittore
parents:
6918
diff
changeset
|
1208 retval = true; |
3960 | 1209 } else if (strchr(pname, *os::path_separator()) != NULL) { |
1210 int n; | |
1211 char** pelements = split_path(pname, &n); | |
9059
17bf4d428955
8006103: [parfait] Possible null pointer dereference at hotspot/src/os/linux/vm/os_linux.cpp; os_windows.cpp; os_solaris.cpp; os_bsd.cpp
ccheung
parents:
8713
diff
changeset
|
1212 if (pelements == NULL) { |
9062 | 1213 return false; |
9059
17bf4d428955
8006103: [parfait] Possible null pointer dereference at hotspot/src/os/linux/vm/os_linux.cpp; os_windows.cpp; os_solaris.cpp; os_bsd.cpp
ccheung
parents:
8713
diff
changeset
|
1214 } |
3960 | 1215 for (int i = 0 ; i < n ; i++) { |
1216 // Really shouldn't be NULL, but check can't hurt | |
1217 if (pelements[i] == NULL || strlen(pelements[i]) == 0) { | |
1218 continue; // skip the empty path values | |
1219 } | |
1220 snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, | |
1221 pelements[i], fname); | |
1222 if (file_exists(buffer)) { | |
6966
6cb0d32b828b
8001185: parsing of sun.boot.library.path in os::dll_build_name somewhat broken
bpittore
parents:
6918
diff
changeset
|
1223 retval = true; |
3960 | 1224 break; |
1225 } | |
1226 } | |
1227 // release the storage | |
1228 for (int i = 0 ; i < n ; i++) { | |
1229 if (pelements[i] != NULL) { | |
6197 | 1230 FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal); |
3960 | 1231 } |
1232 } | |
1233 if (pelements != NULL) { | |
6197 | 1234 FREE_C_HEAP_ARRAY(char*, pelements, mtInternal); |
3960 | 1235 } |
1236 } else { | |
1237 snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pname, fname); | |
6966
6cb0d32b828b
8001185: parsing of sun.boot.library.path in os::dll_build_name somewhat broken
bpittore
parents:
6918
diff
changeset
|
1238 retval = true; |
3960 | 1239 } |
6966
6cb0d32b828b
8001185: parsing of sun.boot.library.path in os::dll_build_name somewhat broken
bpittore
parents:
6918
diff
changeset
|
1240 return retval; |
3960 | 1241 } |
1242 | |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
1243 // check if addr is inside libjvm.so |
3960 | 1244 bool os::address_is_in_vm(address addr) { |
1245 static address libjvm_base_addr; | |
1246 Dl_info dlinfo; | |
1247 | |
1248 if (libjvm_base_addr == NULL) { | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1249 if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1250 libjvm_base_addr = (address)dlinfo.dli_fbase; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1251 } |
3960 | 1252 assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm"); |
1253 } | |
1254 | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1255 if (dladdr((void *)addr, &dlinfo) != 0) { |
3960 | 1256 if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true; |
1257 } | |
1258 | |
1259 return false; | |
1260 } | |
1261 | |
6258 | 1262 |
1263 #define MACH_MAXSYMLEN 256 | |
1264 | |
3960 | 1265 bool os::dll_address_to_function_name(address addr, char *buf, |
1266 int buflen, int *offset) { | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1267 // buf is not optional, but offset is optional |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1268 assert(buf != NULL, "sanity check"); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1269 |
3960 | 1270 Dl_info dlinfo; |
6258 | 1271 char localbuf[MACH_MAXSYMLEN]; |
1272 | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1273 if (dladdr((void*)addr, &dlinfo) != 0) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1274 // see if we have a matching symbol |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1275 if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1276 if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { |
3960 | 1277 jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); |
1278 } | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1279 if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1280 return true; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1281 } |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1282 // no matching symbol so try for just file info |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1283 if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1284 if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1285 buf, buflen, offset, dlinfo.dli_fname)) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1286 return true; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1287 } |
3960 | 1288 } |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1289 |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1290 // Handle non-dynamic manually: |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1291 if (dlinfo.dli_fbase != NULL && |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1292 Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1293 dlinfo.dli_fbase)) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1294 if (!Decoder::demangle(localbuf, buf, buflen)) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1295 jio_snprintf(buf, buflen, "%s", localbuf); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1296 } |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1297 return true; |
3960 | 1298 } |
1299 } | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1300 buf[0] = '\0'; |
3960 | 1301 if (offset != NULL) *offset = -1; |
1302 return false; | |
1303 } | |
1304 | |
1305 // ported from solaris version | |
1306 bool os::dll_address_to_library_name(address addr, char* buf, | |
1307 int buflen, int* offset) { | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1308 // buf is not optional, but offset is optional |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1309 assert(buf != NULL, "sanity check"); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1310 |
3960 | 1311 Dl_info dlinfo; |
1312 | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1313 if (dladdr((void*)addr, &dlinfo) != 0) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1314 if (dlinfo.dli_fname != NULL) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1315 jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1316 } |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1317 if (dlinfo.dli_fbase != NULL && offset != NULL) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1318 *offset = addr - (address)dlinfo.dli_fbase; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1319 } |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1320 return true; |
3960 | 1321 } |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1322 |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1323 buf[0] = '\0'; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1324 if (offset) *offset = -1; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1325 return false; |
3960 | 1326 } |
6918 | 1327 |
1328 // Loads .dll/.so and | |
1329 // in case of error it checks if .dll/.so was built for the | |
1330 // same architecture as Hotspot is running on | |
3960 | 1331 |
1332 #ifdef __APPLE__ | |
1333 void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { | |
1334 void * result= ::dlopen(filename, RTLD_LAZY); | |
1335 if (result != NULL) { | |
1336 // Successful loading | |
1337 return result; | |
1338 } | |
1339 | |
1340 // Read system error message into ebuf | |
1341 ::strncpy(ebuf, ::dlerror(), ebuflen-1); | |
1342 ebuf[ebuflen-1]='\0'; | |
1343 | |
1344 return NULL; | |
1345 } | |
1346 #else | |
1347 void * os::dll_load(const char *filename, char *ebuf, int ebuflen) | |
1348 { | |
1349 void * result= ::dlopen(filename, RTLD_LAZY); | |
1350 if (result != NULL) { | |
1351 // Successful loading | |
1352 return result; | |
1353 } | |
1354 | |
1355 Elf32_Ehdr elf_head; | |
1356 | |
1357 // Read system error message into ebuf | |
1358 // It may or may not be overwritten below | |
1359 ::strncpy(ebuf, ::dlerror(), ebuflen-1); | |
1360 ebuf[ebuflen-1]='\0'; | |
1361 int diag_msg_max_length=ebuflen-strlen(ebuf); | |
1362 char* diag_msg_buf=ebuf+strlen(ebuf); | |
1363 | |
1364 if (diag_msg_max_length==0) { | |
1365 // No more space in ebuf for additional diagnostics message | |
1366 return NULL; | |
1367 } | |
1368 | |
1369 | |
1370 int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK); | |
1371 | |
1372 if (file_descriptor < 0) { | |
1373 // Can't open library, report dlerror() message | |
1374 return NULL; | |
1375 } | |
1376 | |
1377 bool failed_to_read_elf_head= | |
1378 (sizeof(elf_head)!= | |
1379 (::read(file_descriptor, &elf_head,sizeof(elf_head)))) ; | |
1380 | |
1381 ::close(file_descriptor); | |
1382 if (failed_to_read_elf_head) { | |
1383 // file i/o error - report dlerror() msg | |
1384 return NULL; | |
1385 } | |
1386 | |
1387 typedef struct { | |
1388 Elf32_Half code; // Actual value as defined in elf.h | |
1389 Elf32_Half compat_class; // Compatibility of archs at VM's sense | |
1390 char elf_class; // 32 or 64 bit | |
1391 char endianess; // MSB or LSB | |
1392 char* name; // String representation | |
1393 } arch_t; | |
1394 | |
1395 #ifndef EM_486 | |
1396 #define EM_486 6 /* Intel 80486 */ | |
1397 #endif | |
1398 | |
1399 #ifndef EM_MIPS_RS3_LE | |
1400 #define EM_MIPS_RS3_LE 10 /* MIPS */ | |
1401 #endif | |
1402 | |
1403 #ifndef EM_PPC64 | |
1404 #define EM_PPC64 21 /* PowerPC64 */ | |
1405 #endif | |
1406 | |
1407 #ifndef EM_S390 | |
1408 #define EM_S390 22 /* IBM System/390 */ | |
1409 #endif | |
1410 | |
1411 #ifndef EM_IA_64 | |
1412 #define EM_IA_64 50 /* HP/Intel IA-64 */ | |
1413 #endif | |
1414 | |
1415 #ifndef EM_X86_64 | |
1416 #define EM_X86_64 62 /* AMD x86-64 */ | |
1417 #endif | |
1418 | |
1419 static const arch_t arch_array[]={ | |
1420 {EM_386, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"}, | |
1421 {EM_486, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"}, | |
1422 {EM_IA_64, EM_IA_64, ELFCLASS64, ELFDATA2LSB, (char*)"IA 64"}, | |
1423 {EM_X86_64, EM_X86_64, ELFCLASS64, ELFDATA2LSB, (char*)"AMD 64"}, | |
1424 {EM_SPARC, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"}, | |
1425 {EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"}, | |
1426 {EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"}, | |
1427 {EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"}, | |
1428 {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"}, | |
1429 {EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"}, | |
1430 {EM_S390, EM_S390, ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"}, | |
1431 {EM_ALPHA, EM_ALPHA, ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"}, | |
1432 {EM_MIPS_RS3_LE, EM_MIPS_RS3_LE, ELFCLASS32, ELFDATA2LSB, (char*)"MIPSel"}, | |
1433 {EM_MIPS, EM_MIPS, ELFCLASS32, ELFDATA2MSB, (char*)"MIPS"}, | |
1434 {EM_PARISC, EM_PARISC, ELFCLASS32, ELFDATA2MSB, (char*)"PARISC"}, | |
1435 {EM_68K, EM_68K, ELFCLASS32, ELFDATA2MSB, (char*)"M68k"} | |
1436 }; | |
1437 | |
1438 #if (defined IA32) | |
1439 static Elf32_Half running_arch_code=EM_386; | |
1440 #elif (defined AMD64) | |
1441 static Elf32_Half running_arch_code=EM_X86_64; | |
1442 #elif (defined IA64) | |
1443 static Elf32_Half running_arch_code=EM_IA_64; | |
1444 #elif (defined __sparc) && (defined _LP64) | |
1445 static Elf32_Half running_arch_code=EM_SPARCV9; | |
1446 #elif (defined __sparc) && (!defined _LP64) | |
1447 static Elf32_Half running_arch_code=EM_SPARC; | |
1448 #elif (defined __powerpc64__) | |
1449 static Elf32_Half running_arch_code=EM_PPC64; | |
1450 #elif (defined __powerpc__) | |
1451 static Elf32_Half running_arch_code=EM_PPC; | |
1452 #elif (defined ARM) | |
1453 static Elf32_Half running_arch_code=EM_ARM; | |
1454 #elif (defined S390) | |
1455 static Elf32_Half running_arch_code=EM_S390; | |
1456 #elif (defined ALPHA) | |
1457 static Elf32_Half running_arch_code=EM_ALPHA; | |
1458 #elif (defined MIPSEL) | |
1459 static Elf32_Half running_arch_code=EM_MIPS_RS3_LE; | |
1460 #elif (defined PARISC) | |
1461 static Elf32_Half running_arch_code=EM_PARISC; | |
1462 #elif (defined MIPS) | |
1463 static Elf32_Half running_arch_code=EM_MIPS; | |
1464 #elif (defined M68K) | |
1465 static Elf32_Half running_arch_code=EM_68K; | |
1466 #else | |
1467 #error Method os::dll_load requires that one of following is defined:\ | |
1468 IA32, AMD64, IA64, __sparc, __powerpc__, ARM, S390, ALPHA, MIPS, MIPSEL, PARISC, M68K | |
1469 #endif | |
1470 | |
1471 // Identify compatability class for VM's architecture and library's architecture | |
1472 // Obtain string descriptions for architectures | |
1473 | |
1474 arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL}; | |
1475 int running_arch_index=-1; | |
1476 | |
1477 for (unsigned int i=0 ; i < ARRAY_SIZE(arch_array) ; i++ ) { | |
1478 if (running_arch_code == arch_array[i].code) { | |
1479 running_arch_index = i; | |
1480 } | |
1481 if (lib_arch.code == arch_array[i].code) { | |
1482 lib_arch.compat_class = arch_array[i].compat_class; | |
1483 lib_arch.name = arch_array[i].name; | |
1484 } | |
1485 } | |
1486 | |
1487 assert(running_arch_index != -1, | |
1488 "Didn't find running architecture code (running_arch_code) in arch_array"); | |
1489 if (running_arch_index == -1) { | |
1490 // Even though running architecture detection failed | |
1491 // we may still continue with reporting dlerror() message | |
1492 return NULL; | |
1493 } | |
1494 | |
1495 if (lib_arch.endianess != arch_array[running_arch_index].endianess) { | |
1496 ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)"); | |
1497 return NULL; | |
1498 } | |
1499 | |
1500 #ifndef S390 | |
1501 if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) { | |
1502 ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: architecture word width mismatch)"); | |
1503 return NULL; | |
1504 } | |
1505 #endif // !S390 | |
1506 | |
1507 if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) { | |
1508 if ( lib_arch.name!=NULL ) { | |
1509 ::snprintf(diag_msg_buf, diag_msg_max_length-1, | |
1510 " (Possible cause: can't load %s-bit .so on a %s-bit platform)", | |
1511 lib_arch.name, arch_array[running_arch_index].name); | |
1512 } else { | |
1513 ::snprintf(diag_msg_buf, diag_msg_max_length-1, | |
1514 " (Possible cause: can't load this .so (machine code=0x%x) on a %s-bit platform)", | |
1515 lib_arch.code, | |
1516 arch_array[running_arch_index].name); | |
1517 } | |
1518 } | |
1519 | |
1520 return NULL; | |
1521 } | |
1522 #endif /* !__APPLE__ */ | |
1523 | |
1524 // XXX: Do we need a lock around this as per Linux? | |
1525 void* os::dll_lookup(void* handle, const char* name) { | |
1526 return dlsym(handle, name); | |
1527 } | |
1528 | |
1529 | |
1530 static bool _print_ascii_file(const char* filename, outputStream* st) { | |
1531 int fd = ::open(filename, O_RDONLY); | |
1532 if (fd == -1) { | |
1533 return false; | |
1534 } | |
1535 | |
1536 char buf[32]; | |
1537 int bytes; | |
1538 while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) { | |
1539 st->print_raw(buf, bytes); | |
1540 } | |
1541 | |
1542 ::close(fd); | |
1543 | |
1544 return true; | |
1545 } | |
1546 | |
1547 void os::print_dll_info(outputStream *st) { | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1548 st->print_cr("Dynamic libraries:"); |
3960 | 1549 #ifdef RTLD_DI_LINKMAP |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1550 Dl_info dli; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1551 void *handle; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1552 Link_map *map; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1553 Link_map *p; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1554 |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1555 if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 || |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1556 dli.dli_fname == NULL) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1557 st->print_cr("Error: Cannot print dynamic libraries."); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1558 return; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1559 } |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1560 handle = dlopen(dli.dli_fname, RTLD_LAZY); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1561 if (handle == NULL) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1562 st->print_cr("Error: Cannot print dynamic libraries."); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1563 return; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1564 } |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1565 dlinfo(handle, RTLD_DI_LINKMAP, &map); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1566 if (map == NULL) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1567 st->print_cr("Error: Cannot print dynamic libraries."); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1568 return; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1569 } |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1570 |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1571 while (map->l_prev != NULL) |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1572 map = map->l_prev; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1573 |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1574 while (map != NULL) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1575 st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1576 map = map->l_next; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1577 } |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1578 |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1579 dlclose(handle); |
3960 | 1580 #elif defined(__APPLE__) |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1581 uint32_t count; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1582 uint32_t i; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1583 |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1584 count = _dyld_image_count(); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1585 for (i = 1; i < count; i++) { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1586 const char *name = _dyld_get_image_name(i); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1587 intptr_t slide = _dyld_get_image_vmaddr_slide(i); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1588 st->print_cr(PTR_FORMAT " \t%s", slide, name); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1589 } |
3960 | 1590 #else |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1591 st->print_cr("Error: Cannot print dynamic libraries."); |
3960 | 1592 #endif |
1593 } | |
1594 | |
6080
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1595 void os::print_os_info_brief(outputStream* st) { |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1596 st->print("Bsd"); |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1597 |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1598 os::Posix::print_uname_info(st); |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1599 } |
3960 | 1600 |
1601 void os::print_os_info(outputStream* st) { | |
1602 st->print("OS:"); | |
6080
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1603 st->print("Bsd"); |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1604 |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1605 os::Posix::print_uname_info(st); |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1606 |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1607 os::Posix::print_rlimit_info(st); |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1608 |
7432b9db36ff
7165755: OS Information much longer on linux than other platforms
nloodin
parents:
5921
diff
changeset
|
1609 os::Posix::print_load_average(st); |
3960 | 1610 } |
1611 | |
1612 void os::pd_print_cpu_info(outputStream* st) { | |
1613 // Nothing to do for now. | |
1614 } | |
1615 | |
1616 void os::print_memory_info(outputStream* st) { | |
1617 | |
1618 st->print("Memory:"); | |
1619 st->print(" %dk page", os::vm_page_size()>>10); | |
1620 | |
1621 st->print(", physical " UINT64_FORMAT "k", | |
1622 os::physical_memory() >> 10); | |
1623 st->print("(" UINT64_FORMAT "k free)", | |
1624 os::available_memory() >> 10); | |
1625 st->cr(); | |
1626 | |
1627 // meminfo | |
1628 st->print("\n/proc/meminfo:\n"); | |
1629 _print_ascii_file("/proc/meminfo", st); | |
1630 st->cr(); | |
1631 } | |
1632 | |
1633 // Taken from /usr/include/bits/siginfo.h Supposed to be architecture specific | |
1634 // but they're the same for all the bsd arch that we support | |
1635 // and they're the same for solaris but there's no common place to put this. | |
1636 const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR", | |
1637 "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG", | |
1638 "ILL_COPROC", "ILL_BADSTK" }; | |
1639 | |
1640 const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV", | |
1641 "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES", | |
1642 "FPE_FLTINV", "FPE_FLTSUB", "FPE_FLTDEN" }; | |
1643 | |
1644 const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" }; | |
1645 | |
1646 const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" }; | |
1647 | |
1648 void os::print_siginfo(outputStream* st, void* siginfo) { | |
1649 st->print("siginfo:"); | |
1650 | |
1651 const int buflen = 100; | |
1652 char buf[buflen]; | |
1653 siginfo_t *si = (siginfo_t*)siginfo; | |
1654 st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen)); | |
1655 if (si->si_errno != 0 && strerror_r(si->si_errno, buf, buflen) == 0) { | |
1656 st->print("si_errno=%s", buf); | |
1657 } else { | |
1658 st->print("si_errno=%d", si->si_errno); | |
1659 } | |
1660 const int c = si->si_code; | |
1661 assert(c > 0, "unexpected si_code"); | |
1662 switch (si->si_signo) { | |
1663 case SIGILL: | |
1664 st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]); | |
1665 st->print(", si_addr=" PTR_FORMAT, si->si_addr); | |
1666 break; | |
1667 case SIGFPE: | |
1668 st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]); | |
1669 st->print(", si_addr=" PTR_FORMAT, si->si_addr); | |
1670 break; | |
1671 case SIGSEGV: | |
1672 st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]); | |
1673 st->print(", si_addr=" PTR_FORMAT, si->si_addr); | |
1674 break; | |
1675 case SIGBUS: | |
1676 st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]); | |
1677 st->print(", si_addr=" PTR_FORMAT, si->si_addr); | |
1678 break; | |
1679 default: | |
1680 st->print(", si_code=%d", si->si_code); | |
1681 // no si_addr | |
1682 } | |
1683 | |
1684 if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && | |
1685 UseSharedSpaces) { | |
1686 FileMapInfo* mapinfo = FileMapInfo::current_info(); | |
1687 if (mapinfo->is_in_shared_space(si->si_addr)) { | |
1688 st->print("\n\nError accessing class data sharing archive." \ | |
1689 " Mapped file inaccessible during execution, " \ | |
1690 " possible disk/network problem."); | |
1691 } | |
1692 } | |
1693 st->cr(); | |
1694 } | |
1695 | |
1696 | |
1697 static void print_signal_handler(outputStream* st, int sig, | |
1698 char* buf, size_t buflen); | |
1699 | |
1700 void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { | |
1701 st->print_cr("Signal Handlers:"); | |
1702 print_signal_handler(st, SIGSEGV, buf, buflen); | |
1703 print_signal_handler(st, SIGBUS , buf, buflen); | |
1704 print_signal_handler(st, SIGFPE , buf, buflen); | |
1705 print_signal_handler(st, SIGPIPE, buf, buflen); | |
1706 print_signal_handler(st, SIGXFSZ, buf, buflen); | |
1707 print_signal_handler(st, SIGILL , buf, buflen); | |
1708 print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen); | |
1709 print_signal_handler(st, SR_signum, buf, buflen); | |
1710 print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen); | |
1711 print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); | |
1712 print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen); | |
1713 print_signal_handler(st, BREAK_SIGNAL, buf, buflen); | |
1714 } | |
1715 | |
1716 static char saved_jvm_path[MAXPATHLEN] = {0}; | |
1717 | |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
1718 // Find the full path to the current module, libjvm |
3960 | 1719 void os::jvm_path(char *buf, jint buflen) { |
1720 // Error checking. | |
1721 if (buflen < MAXPATHLEN) { | |
1722 assert(false, "must use a large-enough buffer"); | |
1723 buf[0] = '\0'; | |
1724 return; | |
1725 } | |
1726 // Lazy resolve the path to current module. | |
1727 if (saved_jvm_path[0] != 0) { | |
1728 strcpy(buf, saved_jvm_path); | |
1729 return; | |
1730 } | |
1731 | |
1732 char dli_fname[MAXPATHLEN]; | |
1733 bool ret = dll_address_to_library_name( | |
1734 CAST_FROM_FN_PTR(address, os::jvm_path), | |
1735 dli_fname, sizeof(dli_fname), NULL); | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1736 assert(ret, "cannot locate libjvm"); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1737 char *rp = NULL; |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1738 if (ret && dli_fname[0] != '\0') { |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1739 rp = realpath(dli_fname, buf); |
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
1740 } |
3960 | 1741 if (rp == NULL) |
1742 return; | |
1743 | |
1744 if (Arguments::created_by_gamma_launcher()) { | |
1745 // Support for the gamma launcher. Typical value for buf is | |
4846 | 1746 // "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm". If "/jre/lib/" appears at |
3960 | 1747 // the right place in the string, then assume we are installed in a JDK and |
4846 | 1748 // we're done. Otherwise, check for a JAVA_HOME environment variable and |
1749 // construct a path to the JVM being overridden. | |
1750 | |
3960 | 1751 const char *p = buf + strlen(buf) - 1; |
1752 for (int count = 0; p > buf && count < 5; ++count) { | |
1753 for (--p; p > buf && *p != '/'; --p) | |
1754 /* empty */ ; | |
1755 } | |
1756 | |
1757 if (strncmp(p, "/jre/lib/", 9) != 0) { | |
1758 // Look for JAVA_HOME in the environment. | |
1759 char* java_home_var = ::getenv("JAVA_HOME"); | |
1760 if (java_home_var != NULL && java_home_var[0] != 0) { | |
1761 char* jrelib_p; | |
1762 int len; | |
1763 | |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
1764 // Check the current module name "libjvm" |
3960 | 1765 p = strrchr(buf, '/'); |
1766 assert(strstr(p, "/libjvm") == p, "invalid library name"); | |
1767 | |
1768 rp = realpath(java_home_var, buf); | |
1769 if (rp == NULL) | |
1770 return; | |
1771 | |
1772 // determine if this is a legacy image or modules image | |
1773 // modules image doesn't have "jre" subdirectory | |
1774 len = strlen(buf); | |
1775 jrelib_p = buf + len; | |
4846 | 1776 |
1777 // Add the appropriate library subdir | |
1778 snprintf(jrelib_p, buflen-len, "/jre/lib"); | |
3960 | 1779 if (0 != access(buf, F_OK)) { |
4846 | 1780 snprintf(jrelib_p, buflen-len, "/lib"); |
3960 | 1781 } |
1782 | |
4846 | 1783 // Add the appropriate client or server subdir |
1784 len = strlen(buf); | |
1785 jrelib_p = buf + len; | |
1786 snprintf(jrelib_p, buflen-len, "/%s", COMPILER_VARIANT); | |
1787 if (0 != access(buf, F_OK)) { | |
1788 snprintf(jrelib_p, buflen-len, ""); | |
1789 } | |
1790 | |
1791 // If the path exists within JAVA_HOME, add the JVM library name | |
1792 // to complete the path to JVM being overridden. Otherwise fallback | |
1793 // to the path to the current library. | |
3960 | 1794 if (0 == access(buf, F_OK)) { |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
1795 // Use current module name "libjvm" |
3960 | 1796 len = strlen(buf); |
7456
7d42f3b08300
8005044: remove crufty '_g' support from HS runtime code
dcubed
parents:
7206
diff
changeset
|
1797 snprintf(buf + len, buflen-len, "/libjvm%s", JNI_LIB_SUFFIX); |
3960 | 1798 } else { |
4846 | 1799 // Fall back to path of current library |
3960 | 1800 rp = realpath(dli_fname, buf); |
1801 if (rp == NULL) | |
1802 return; | |
1803 } | |
1804 } | |
1805 } | |
1806 } | |
1807 | |
1808 strcpy(saved_jvm_path, buf); | |
1809 } | |
1810 | |
1811 void os::print_jni_name_prefix_on(outputStream* st, int args_size) { | |
1812 // no prefix required, not even "_" | |
1813 } | |
1814 | |
1815 void os::print_jni_name_suffix_on(outputStream* st, int args_size) { | |
1816 // no suffix required | |
1817 } | |
1818 | |
1819 //////////////////////////////////////////////////////////////////////////////// | |
1820 // sun.misc.Signal support | |
1821 | |
1822 static volatile jint sigint_count = 0; | |
1823 | |
1824 static void | |
1825 UserHandler(int sig, void *siginfo, void *context) { | |
1826 // 4511530 - sem_post is serialized and handled by the manager thread. When | |
1827 // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We | |
1828 // don't want to flood the manager thread with sem_post requests. | |
1829 if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) | |
1830 return; | |
1831 | |
1832 // Ctrl-C is pressed during error reporting, likely because the error | |
1833 // handler fails to abort. Let VM die immediately. | |
1834 if (sig == SIGINT && is_error_reported()) { | |
1835 os::die(); | |
1836 } | |
1837 | |
1838 os::signal_notify(sig); | |
1839 } | |
1840 | |
1841 void* os::user_handler() { | |
1842 return CAST_FROM_FN_PTR(void*, UserHandler); | |
1843 } | |
1844 | |
1845 extern "C" { | |
1846 typedef void (*sa_handler_t)(int); | |
1847 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); | |
1848 } | |
1849 | |
1850 void* os::signal(int signal_number, void* handler) { | |
1851 struct sigaction sigAct, oldSigAct; | |
1852 | |
1853 sigfillset(&(sigAct.sa_mask)); | |
1854 sigAct.sa_flags = SA_RESTART|SA_SIGINFO; | |
1855 sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler); | |
1856 | |
1857 if (sigaction(signal_number, &sigAct, &oldSigAct)) { | |
1858 // -1 means registration failed | |
1859 return (void *)-1; | |
1860 } | |
1861 | |
1862 return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler); | |
1863 } | |
1864 | |
1865 void os::signal_raise(int signal_number) { | |
1866 ::raise(signal_number); | |
1867 } | |
1868 | |
1869 /* | |
1870 * The following code is moved from os.cpp for making this | |
1871 * code platform specific, which it is by its very nature. | |
1872 */ | |
1873 | |
1874 // Will be modified when max signal is changed to be dynamic | |
1875 int os::sigexitnum_pd() { | |
1876 return NSIG; | |
1877 } | |
1878 | |
1879 // a counter for each possible signal value | |
1880 static volatile jint pending_signals[NSIG+1] = { 0 }; | |
1881 | |
1882 // Bsd(POSIX) specific hand shaking semaphore. | |
1883 #ifdef __APPLE__ | |
10405 | 1884 typedef semaphore_t os_semaphore_t; |
3960 | 1885 #define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value) |
10405 | 1886 #define SEM_WAIT(sem) semaphore_wait(sem) |
1887 #define SEM_POST(sem) semaphore_signal(sem) | |
1888 #define SEM_DESTROY(sem) semaphore_destroy(mach_task_self(), sem) | |
3960 | 1889 #else |
10405 | 1890 typedef sem_t os_semaphore_t; |
3960 | 1891 #define SEM_INIT(sem, value) sem_init(&sem, 0, value) |
10405 | 1892 #define SEM_WAIT(sem) sem_wait(&sem) |
1893 #define SEM_POST(sem) sem_post(&sem) | |
1894 #define SEM_DESTROY(sem) sem_destroy(&sem) | |
3960 | 1895 #endif |
1896 | |
10405 | 1897 class Semaphore : public StackObj { |
1898 public: | |
1899 Semaphore(); | |
1900 ~Semaphore(); | |
1901 void signal(); | |
1902 void wait(); | |
1903 bool trywait(); | |
1904 bool timedwait(unsigned int sec, int nsec); | |
1905 private: | |
1906 jlong currenttime() const; | |
1907 semaphore_t _semaphore; | |
1908 }; | |
1909 | |
1910 Semaphore::Semaphore() : _semaphore(0) { | |
1911 SEM_INIT(_semaphore, 0); | |
1912 } | |
1913 | |
1914 Semaphore::~Semaphore() { | |
1915 SEM_DESTROY(_semaphore); | |
1916 } | |
1917 | |
1918 void Semaphore::signal() { | |
1919 SEM_POST(_semaphore); | |
1920 } | |
1921 | |
1922 void Semaphore::wait() { | |
1923 SEM_WAIT(_semaphore); | |
1924 } | |
1925 | |
1926 jlong Semaphore::currenttime() const { | |
1927 struct timeval tv; | |
1928 gettimeofday(&tv, NULL); | |
1929 return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); | |
1930 } | |
1931 | |
1932 #ifdef __APPLE__ | |
1933 bool Semaphore::trywait() { | |
1934 return timedwait(0, 0); | |
1935 } | |
1936 | |
1937 bool Semaphore::timedwait(unsigned int sec, int nsec) { | |
1938 kern_return_t kr = KERN_ABORTED; | |
1939 mach_timespec_t waitspec; | |
1940 waitspec.tv_sec = sec; | |
1941 waitspec.tv_nsec = nsec; | |
1942 | |
1943 jlong starttime = currenttime(); | |
1944 | |
1945 kr = semaphore_timedwait(_semaphore, waitspec); | |
1946 while (kr == KERN_ABORTED) { | |
1947 jlong totalwait = (sec * NANOSECS_PER_SEC) + nsec; | |
1948 | |
1949 jlong current = currenttime(); | |
1950 jlong passedtime = current - starttime; | |
1951 | |
1952 if (passedtime >= totalwait) { | |
1953 waitspec.tv_sec = 0; | |
1954 waitspec.tv_nsec = 0; | |
1955 } else { | |
1956 jlong waittime = totalwait - (current - starttime); | |
1957 waitspec.tv_sec = waittime / NANOSECS_PER_SEC; | |
1958 waitspec.tv_nsec = waittime % NANOSECS_PER_SEC; | |
1959 } | |
1960 | |
1961 kr = semaphore_timedwait(_semaphore, waitspec); | |
1962 } | |
1963 | |
1964 return kr == KERN_SUCCESS; | |
1965 } | |
1966 | |
1967 #else | |
1968 | |
1969 bool Semaphore::trywait() { | |
1970 return sem_trywait(&_semaphore) == 0; | |
1971 } | |
1972 | |
1973 bool Semaphore::timedwait(unsigned int sec, int nsec) { | |
1974 struct timespec ts; | |
1975 jlong endtime = unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); | |
1976 | |
1977 while (1) { | |
1978 int result = sem_timedwait(&_semaphore, &ts); | |
1979 if (result == 0) { | |
1980 return true; | |
1981 } else if (errno == EINTR) { | |
1982 continue; | |
1983 } else if (errno == ETIMEDOUT) { | |
1984 return false; | |
1985 } else { | |
1986 return false; | |
1987 } | |
1988 } | |
1989 } | |
1990 | |
1991 #endif // __APPLE__ | |
1992 | |
1993 static os_semaphore_t sig_sem; | |
1994 static Semaphore sr_semaphore; | |
1995 | |
3960 | 1996 void os::signal_init_pd() { |
1997 // Initialize signal structures | |
1998 ::memset((void*)pending_signals, 0, sizeof(pending_signals)); | |
1999 | |
2000 // Initialize signal semaphore | |
2001 ::SEM_INIT(sig_sem, 0); | |
2002 } | |
2003 | |
2004 void os::signal_notify(int sig) { | |
2005 Atomic::inc(&pending_signals[sig]); | |
2006 ::SEM_POST(sig_sem); | |
2007 } | |
2008 | |
2009 static int check_pending_signals(bool wait) { | |
2010 Atomic::store(0, &sigint_count); | |
2011 for (;;) { | |
2012 for (int i = 0; i < NSIG + 1; i++) { | |
2013 jint n = pending_signals[i]; | |
2014 if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) { | |
2015 return i; | |
2016 } | |
2017 } | |
2018 if (!wait) { | |
2019 return -1; | |
2020 } | |
2021 JavaThread *thread = JavaThread::current(); | |
2022 ThreadBlockInVM tbivm(thread); | |
2023 | |
2024 bool threadIsSuspended; | |
2025 do { | |
2026 thread->set_suspend_equivalent(); | |
2027 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() | |
2028 ::SEM_WAIT(sig_sem); | |
2029 | |
2030 // were we externally suspended while we were waiting? | |
2031 threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); | |
2032 if (threadIsSuspended) { | |
2033 // | |
2034 // The semaphore has been incremented, but while we were waiting | |
2035 // another thread suspended us. We don't want to continue running | |
2036 // while suspended because that would surprise the thread that | |
2037 // suspended us. | |
2038 // | |
2039 ::SEM_POST(sig_sem); | |
2040 | |
2041 thread->java_suspend_self(); | |
2042 } | |
2043 } while (threadIsSuspended); | |
2044 } | |
2045 } | |
2046 | |
2047 int os::signal_lookup() { | |
2048 return check_pending_signals(false); | |
2049 } | |
2050 | |
2051 int os::signal_wait() { | |
2052 return check_pending_signals(true); | |
2053 } | |
2054 | |
2055 //////////////////////////////////////////////////////////////////////////////// | |
2056 // Virtual Memory | |
2057 | |
2058 int os::vm_page_size() { | |
2059 // Seems redundant as all get out | |
2060 assert(os::Bsd::page_size() != -1, "must call os::init"); | |
2061 return os::Bsd::page_size(); | |
2062 } | |
2063 | |
2064 // Solaris allocates memory by pages. | |
2065 int os::vm_allocation_granularity() { | |
2066 assert(os::Bsd::page_size() != -1, "must call os::init"); | |
2067 return os::Bsd::page_size(); | |
2068 } | |
2069 | |
2070 // Rationale behind this function: | |
2071 // current (Mon Apr 25 20:12:18 MSD 2005) oprofile drops samples without executable | |
2072 // mapping for address (see lookup_dcookie() in the kernel module), thus we cannot get | |
2073 // samples for JITted code. Here we create private executable mapping over the code cache | |
2074 // and then we can use standard (well, almost, as mapping can change) way to provide | |
2075 // info for the reporting script by storing timestamp and location of symbol | |
2076 void bsd_wrap_code(char* base, size_t size) { | |
2077 static volatile jint cnt = 0; | |
2078 | |
2079 if (!UseOprofile) { | |
2080 return; | |
2081 } | |
2082 | |
2083 char buf[PATH_MAX + 1]; | |
2084 int num = Atomic::add(1, &cnt); | |
2085 | |
2086 snprintf(buf, PATH_MAX + 1, "%s/hs-vm-%d-%d", | |
2087 os::get_temp_directory(), os::current_process_id(), num); | |
2088 unlink(buf); | |
2089 | |
2090 int fd = ::open(buf, O_CREAT | O_RDWR, S_IRWXU); | |
2091 | |
2092 if (fd != -1) { | |
2093 off_t rv = ::lseek(fd, size-2, SEEK_SET); | |
2094 if (rv != (off_t)-1) { | |
2095 if (::write(fd, "", 1) == 1) { | |
2096 mmap(base, size, | |
2097 PROT_READ|PROT_WRITE|PROT_EXEC, | |
2098 MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0); | |
2099 } | |
2100 } | |
2101 ::close(fd); | |
2102 unlink(buf); | |
2103 } | |
2104 } | |
2105 | |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2106 static void warn_fail_commit_memory(char* addr, size_t size, bool exec, |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2107 int err) { |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2108 warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2109 ", %d) failed; error='%s' (errno=%d)", addr, size, exec, |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2110 strerror(err), err); |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2111 } |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2112 |
3960 | 2113 // NOTE: Bsd kernel does not really reserve the pages for us. |
2114 // All it does is to check if there are enough free pages | |
2115 // left at the time of mmap(). This could be a potential | |
2116 // problem. | |
6197 | 2117 bool os::pd_commit_memory(char* addr, size_t size, bool exec) { |
3960 | 2118 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; |
2119 #ifdef __OpenBSD__ | |
2120 // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD | |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2121 if (::mprotect(addr, size, prot) == 0) { |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2122 return true; |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2123 } |
3960 | 2124 #else |
2125 uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, | |
2126 MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); | |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2127 if (res != (uintptr_t) MAP_FAILED) { |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2128 return true; |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2129 } |
3960 | 2130 #endif |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2131 |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2132 // Warn about any commit errors we see in non-product builds just |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2133 // in case mmap() doesn't work as described on the man page. |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2134 NOT_PRODUCT(warn_fail_commit_memory(addr, size, exec, errno);) |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2135 |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2136 return false; |
3960 | 2137 } |
2138 | |
6197 | 2139 bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, |
3960 | 2140 bool exec) { |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2141 // alignment_hint is ignored on this OS |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2142 return pd_commit_memory(addr, size, exec); |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2143 } |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2144 |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2145 void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec, |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2146 const char* mesg) { |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2147 assert(mesg != NULL, "mesg must be specified"); |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2148 if (!pd_commit_memory(addr, size, exec)) { |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2149 // add extra info in product mode for vm_exit_out_of_memory(): |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2150 PRODUCT_ONLY(warn_fail_commit_memory(addr, size, exec, errno);) |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2151 vm_exit_out_of_memory(size, OOM_MMAP_ERROR, mesg); |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2152 } |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2153 } |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2154 |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2155 void os::pd_commit_memory_or_exit(char* addr, size_t size, |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2156 size_t alignment_hint, bool exec, |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2157 const char* mesg) { |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2158 // alignment_hint is ignored on this OS |
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2159 pd_commit_memory_or_exit(addr, size, exec, mesg); |
3960 | 2160 } |
2161 | |
6197 | 2162 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { |
3960 | 2163 } |
2164 | |
6197 | 2165 void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { |
3960 | 2166 ::madvise(addr, bytes, MADV_DONTNEED); |
2167 } | |
2168 | |
2169 void os::numa_make_global(char *addr, size_t bytes) { | |
2170 } | |
2171 | |
2172 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { | |
2173 } | |
2174 | |
2175 bool os::numa_topology_changed() { return false; } | |
2176 | |
2177 size_t os::numa_get_groups_num() { | |
2178 return 1; | |
2179 } | |
2180 | |
2181 int os::numa_get_group_id() { | |
2182 return 0; | |
2183 } | |
2184 | |
2185 size_t os::numa_get_leaf_groups(int *ids, size_t size) { | |
2186 if (size > 0) { | |
2187 ids[0] = 0; | |
2188 return 1; | |
2189 } | |
2190 return 0; | |
2191 } | |
2192 | |
2193 bool os::get_page_info(char *start, page_info* info) { | |
2194 return false; | |
2195 } | |
2196 | |
2197 char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) { | |
2198 return end; | |
2199 } | |
2200 | |
2201 | |
6197 | 2202 bool os::pd_uncommit_memory(char* addr, size_t size) { |
3960 | 2203 #ifdef __OpenBSD__ |
2204 // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD | |
2205 return ::mprotect(addr, size, PROT_NONE) == 0; | |
2206 #else | |
2207 uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE, | |
2208 MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); | |
2209 return res != (uintptr_t) MAP_FAILED; | |
2210 #endif | |
2211 } | |
2212 | |
6197 | 2213 bool os::pd_create_stack_guard_pages(char* addr, size_t size) { |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
2214 return os::commit_memory(addr, size, !ExecMem); |
3960 | 2215 } |
2216 | |
2217 // If this is a growable mapping, remove the guard pages entirely by | |
2218 // munmap()ping them. If not, just call uncommit_memory(). | |
2219 bool os::remove_stack_guard_pages(char* addr, size_t size) { | |
2220 return os::uncommit_memory(addr, size); | |
2221 } | |
2222 | |
2223 static address _highest_vm_reserved_address = NULL; | |
2224 | |
2225 // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory | |
2226 // at 'requested_addr'. If there are existing memory mappings at the same | |
2227 // location, however, they will be overwritten. If 'fixed' is false, | |
2228 // 'requested_addr' is only treated as a hint, the return value may or | |
2229 // may not start from the requested address. Unlike Bsd mmap(), this | |
2230 // function returns NULL to indicate failure. | |
2231 static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) { | |
2232 char * addr; | |
2233 int flags; | |
2234 | |
2235 flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS; | |
2236 if (fixed) { | |
2237 assert((uintptr_t)requested_addr % os::Bsd::page_size() == 0, "unaligned address"); | |
2238 flags |= MAP_FIXED; | |
2239 } | |
2240 | |
10157 | 2241 // Map reserved/uncommitted pages PROT_NONE so we fail early if we |
2242 // touch an uncommitted page. Otherwise, the read/write might | |
2243 // succeed if we have enough swap space to back the physical page. | |
2244 addr = (char*)::mmap(requested_addr, bytes, PROT_NONE, | |
3960 | 2245 flags, -1, 0); |
2246 | |
2247 if (addr != MAP_FAILED) { | |
2248 // anon_mmap() should only get called during VM initialization, | |
2249 // don't need lock (actually we can skip locking even it can be called | |
2250 // from multiple threads, because _highest_vm_reserved_address is just a | |
2251 // hint about the upper limit of non-stack memory regions.) | |
2252 if ((address)addr + bytes > _highest_vm_reserved_address) { | |
2253 _highest_vm_reserved_address = (address)addr + bytes; | |
2254 } | |
2255 } | |
2256 | |
2257 return addr == MAP_FAILED ? NULL : addr; | |
2258 } | |
2259 | |
2260 // Don't update _highest_vm_reserved_address, because there might be memory | |
2261 // regions above addr + size. If so, releasing a memory region only creates | |
2262 // a hole in the address space, it doesn't help prevent heap-stack collision. | |
2263 // | |
2264 static int anon_munmap(char * addr, size_t size) { | |
2265 return ::munmap(addr, size) == 0; | |
2266 } | |
2267 | |
6197 | 2268 char* os::pd_reserve_memory(size_t bytes, char* requested_addr, |
3960 | 2269 size_t alignment_hint) { |
2270 return anon_mmap(requested_addr, bytes, (requested_addr != NULL)); | |
2271 } | |
2272 | |
6197 | 2273 bool os::pd_release_memory(char* addr, size_t size) { |
3960 | 2274 return anon_munmap(addr, size); |
2275 } | |
2276 | |
2277 static bool bsd_mprotect(char* addr, size_t size, int prot) { | |
2278 // Bsd wants the mprotect address argument to be page aligned. | |
2279 char* bottom = (char*)align_size_down((intptr_t)addr, os::Bsd::page_size()); | |
2280 | |
2281 // According to SUSv3, mprotect() should only be used with mappings | |
2282 // established by mmap(), and mmap() always maps whole pages. Unaligned | |
2283 // 'addr' likely indicates problem in the VM (e.g. trying to change | |
2284 // protection of malloc'ed or statically allocated memory). Check the | |
2285 // caller if you hit this assert. | |
2286 assert(addr == bottom, "sanity check"); | |
2287 | |
2288 size = align_size_up(pointer_delta(addr, bottom, 1) + size, os::Bsd::page_size()); | |
2289 return ::mprotect(bottom, size, prot) == 0; | |
2290 } | |
2291 | |
2292 // Set protections specified | |
2293 bool os::protect_memory(char* addr, size_t bytes, ProtType prot, | |
2294 bool is_committed) { | |
2295 unsigned int p = 0; | |
2296 switch (prot) { | |
2297 case MEM_PROT_NONE: p = PROT_NONE; break; | |
2298 case MEM_PROT_READ: p = PROT_READ; break; | |
2299 case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break; | |
2300 case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break; | |
2301 default: | |
2302 ShouldNotReachHere(); | |
2303 } | |
2304 // is_committed is unused. | |
2305 return bsd_mprotect(addr, bytes, p); | |
2306 } | |
2307 | |
2308 bool os::guard_memory(char* addr, size_t size) { | |
2309 return bsd_mprotect(addr, size, PROT_NONE); | |
2310 } | |
2311 | |
2312 bool os::unguard_memory(char* addr, size_t size) { | |
2313 return bsd_mprotect(addr, size, PROT_READ|PROT_WRITE); | |
2314 } | |
2315 | |
2316 bool os::Bsd::hugetlbfs_sanity_check(bool warn, size_t page_size) { | |
6918 | 2317 return false; |
3960 | 2318 } |
2319 | |
2320 // Large page support | |
2321 | |
2322 static size_t _large_page_size = 0; | |
2323 | |
2324 void os::large_page_init() { | |
2325 } | |
2326 | |
2327 | |
12110
4c84d351cca9
8007074: SIGSEGV at ParMarkBitMap::verify_clear()
stefank
parents:
12096
diff
changeset
|
2328 char* os::reserve_memory_special(size_t bytes, size_t alignment, char* req_addr, bool exec) { |
4c84d351cca9
8007074: SIGSEGV at ParMarkBitMap::verify_clear()
stefank
parents:
12096
diff
changeset
|
2329 fatal("This code is not used or maintained."); |
4c84d351cca9
8007074: SIGSEGV at ParMarkBitMap::verify_clear()
stefank
parents:
12096
diff
changeset
|
2330 |
3960 | 2331 // "exec" is passed in but not used. Creating the shared image for |
2332 // the code cache doesn't have an SHM_X executable permission to check. | |
2333 assert(UseLargePages && UseSHM, "only for SHM large pages"); | |
2334 | |
2335 key_t key = IPC_PRIVATE; | |
2336 char *addr; | |
2337 | |
2338 bool warn_on_failure = UseLargePages && | |
2339 (!FLAG_IS_DEFAULT(UseLargePages) || | |
2340 !FLAG_IS_DEFAULT(LargePageSizeInBytes) | |
2341 ); | |
2342 char msg[128]; | |
2343 | |
2344 // Create a large shared memory region to attach to based on size. | |
2345 // Currently, size is the total size of the heap | |
2346 int shmid = shmget(key, bytes, IPC_CREAT|SHM_R|SHM_W); | |
2347 if (shmid == -1) { | |
2348 // Possible reasons for shmget failure: | |
2349 // 1. shmmax is too small for Java heap. | |
2350 // > check shmmax value: cat /proc/sys/kernel/shmmax | |
2351 // > increase shmmax value: echo "0xffffffff" > /proc/sys/kernel/shmmax | |
2352 // 2. not enough large page memory. | |
2353 // > check available large pages: cat /proc/meminfo | |
2354 // > increase amount of large pages: | |
2355 // echo new_value > /proc/sys/vm/nr_hugepages | |
2356 // Note 1: different Bsd may use different name for this property, | |
2357 // e.g. on Redhat AS-3 it is "hugetlb_pool". | |
2358 // Note 2: it's possible there's enough physical memory available but | |
2359 // they are so fragmented after a long run that they can't | |
2360 // coalesce into large pages. Try to reserve large pages when | |
2361 // the system is still "fresh". | |
2362 if (warn_on_failure) { | |
2363 jio_snprintf(msg, sizeof(msg), "Failed to reserve shared memory (errno = %d).", errno); | |
2364 warning(msg); | |
2365 } | |
2366 return NULL; | |
2367 } | |
2368 | |
2369 // attach to the region | |
2370 addr = (char*)shmat(shmid, req_addr, 0); | |
2371 int err = errno; | |
2372 | |
2373 // Remove shmid. If shmat() is successful, the actual shared memory segment | |
2374 // will be deleted when it's detached by shmdt() or when the process | |
2375 // terminates. If shmat() is not successful this will remove the shared | |
2376 // segment immediately. | |
2377 shmctl(shmid, IPC_RMID, NULL); | |
2378 | |
2379 if ((intptr_t)addr == -1) { | |
2380 if (warn_on_failure) { | |
2381 jio_snprintf(msg, sizeof(msg), "Failed to attach shared memory (errno = %d).", err); | |
2382 warning(msg); | |
2383 } | |
2384 return NULL; | |
2385 } | |
2386 | |
8711
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
2387 // The memory is committed |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10969
diff
changeset
|
2388 MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC); |
8711
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
2389 |
3960 | 2390 return addr; |
2391 } | |
2392 | |
2393 bool os::release_memory_special(char* base, size_t bytes) { | |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10969
diff
changeset
|
2394 MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); |
3960 | 2395 // detaching the SHM segment will also delete it, see reserve_memory_special() |
2396 int rslt = shmdt(base); | |
8711
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
2397 if (rslt == 0) { |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10969
diff
changeset
|
2398 tkr.record((address)base, bytes); |
8711
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
2399 return true; |
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
2400 } else { |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10969
diff
changeset
|
2401 tkr.discard(); |
8711
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
2402 return false; |
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
2403 } |
6b803ba47588
8008257: NMT: assert(new_rec->is_allocation_record()) failed when running with shared memory option
zgu
parents:
8675
diff
changeset
|
2404 |
3960 | 2405 } |
2406 | |
2407 size_t os::large_page_size() { | |
2408 return _large_page_size; | |
2409 } | |
2410 | |
2411 // HugeTLBFS allows application to commit large page memory on demand; | |
2412 // with SysV SHM the entire memory region must be allocated as shared | |
2413 // memory. | |
2414 bool os::can_commit_large_page_memory() { | |
2415 return UseHugeTLBFS; | |
2416 } | |
2417 | |
2418 bool os::can_execute_large_page_memory() { | |
2419 return UseHugeTLBFS; | |
2420 } | |
2421 | |
2422 // Reserve memory at an arbitrary address, only if that area is | |
2423 // available (and not reserved for something else). | |
2424 | |
6197 | 2425 char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { |
3960 | 2426 const int max_tries = 10; |
2427 char* base[max_tries]; | |
2428 size_t size[max_tries]; | |
2429 const size_t gap = 0x000000; | |
2430 | |
2431 // Assert only that the size is a multiple of the page size, since | |
2432 // that's all that mmap requires, and since that's all we really know | |
2433 // about at this low abstraction level. If we need higher alignment, | |
2434 // we can either pass an alignment to this method or verify alignment | |
2435 // in one of the methods further up the call chain. See bug 5044738. | |
2436 assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block"); | |
2437 | |
2438 // Repeatedly allocate blocks until the block is allocated at the | |
2439 // right spot. Give up after max_tries. Note that reserve_memory() will | |
2440 // automatically update _highest_vm_reserved_address if the call is | |
2441 // successful. The variable tracks the highest memory address every reserved | |
2442 // by JVM. It is used to detect heap-stack collision if running with | |
2443 // fixed-stack BsdThreads. Because here we may attempt to reserve more | |
2444 // space than needed, it could confuse the collision detecting code. To | |
2445 // solve the problem, save current _highest_vm_reserved_address and | |
2446 // calculate the correct value before return. | |
2447 address old_highest = _highest_vm_reserved_address; | |
2448 | |
2449 // Bsd mmap allows caller to pass an address as hint; give it a try first, | |
2450 // if kernel honors the hint then we can return immediately. | |
2451 char * addr = anon_mmap(requested_addr, bytes, false); | |
2452 if (addr == requested_addr) { | |
2453 return requested_addr; | |
2454 } | |
2455 | |
2456 if (addr != NULL) { | |
2457 // mmap() is successful but it fails to reserve at the requested address | |
2458 anon_munmap(addr, bytes); | |
2459 } | |
2460 | |
2461 int i; | |
2462 for (i = 0; i < max_tries; ++i) { | |
2463 base[i] = reserve_memory(bytes); | |
2464 | |
2465 if (base[i] != NULL) { | |
2466 // Is this the block we wanted? | |
2467 if (base[i] == requested_addr) { | |
2468 size[i] = bytes; | |
2469 break; | |
2470 } | |
2471 | |
2472 // Does this overlap the block we wanted? Give back the overlapped | |
2473 // parts and try again. | |
2474 | |
2475 size_t top_overlap = requested_addr + (bytes + gap) - base[i]; | |
2476 if (top_overlap >= 0 && top_overlap < bytes) { | |
2477 unmap_memory(base[i], top_overlap); | |
2478 base[i] += top_overlap; | |
2479 size[i] = bytes - top_overlap; | |
2480 } else { | |
2481 size_t bottom_overlap = base[i] + bytes - requested_addr; | |
2482 if (bottom_overlap >= 0 && bottom_overlap < bytes) { | |
2483 unmap_memory(requested_addr, bottom_overlap); | |
2484 size[i] = bytes - bottom_overlap; | |
2485 } else { | |
2486 size[i] = bytes; | |
2487 } | |
2488 } | |
2489 } | |
2490 } | |
2491 | |
2492 // Give back the unused reserved pieces. | |
2493 | |
2494 for (int j = 0; j < i; ++j) { | |
2495 if (base[j] != NULL) { | |
2496 unmap_memory(base[j], size[j]); | |
2497 } | |
2498 } | |
2499 | |
2500 if (i < max_tries) { | |
2501 _highest_vm_reserved_address = MAX2(old_highest, (address)requested_addr + bytes); | |
2502 return requested_addr; | |
2503 } else { | |
2504 _highest_vm_reserved_address = old_highest; | |
2505 return NULL; | |
2506 } | |
2507 } | |
2508 | |
2509 size_t os::read(int fd, void *buf, unsigned int nBytes) { | |
2510 RESTARTABLE_RETURN_INT(::read(fd, buf, nBytes)); | |
2511 } | |
2512 | |
2513 // TODO-FIXME: reconcile Solaris' os::sleep with the bsd variation. | |
2514 // Solaris uses poll(), bsd uses park(). | |
2515 // Poll() is likely a better choice, assuming that Thread.interrupt() | |
2516 // generates a SIGUSRx signal. Note that SIGUSR1 can interfere with | |
2517 // SIGSEGV, see 4355769. | |
2518 | |
2519 int os::sleep(Thread* thread, jlong millis, bool interruptible) { | |
2520 assert(thread == Thread::current(), "thread consistency check"); | |
2521 | |
2522 ParkEvent * const slp = thread->_SleepEvent ; | |
2523 slp->reset() ; | |
2524 OrderAccess::fence() ; | |
2525 | |
2526 if (interruptible) { | |
2527 jlong prevtime = javaTimeNanos(); | |
2528 | |
2529 for (;;) { | |
2530 if (os::is_interrupted(thread, true)) { | |
2531 return OS_INTRPT; | |
2532 } | |
2533 | |
2534 jlong newtime = javaTimeNanos(); | |
2535 | |
2536 if (newtime - prevtime < 0) { | |
2537 // time moving backwards, should only happen if no monotonic clock | |
2538 // not a guarantee() because JVM should not abort on kernel/glibc bugs | |
2539 assert(!Bsd::supports_monotonic_clock(), "time moving backwards"); | |
2540 } else { | |
4712
e7dead7e90af
7117303: VM uses non-monotonic time source and complains that it is non-monotonic
johnc
parents:
4082
diff
changeset
|
2541 millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; |
3960 | 2542 } |
2543 | |
2544 if(millis <= 0) { | |
2545 return OS_OK; | |
2546 } | |
2547 | |
2548 prevtime = newtime; | |
2549 | |
2550 { | |
2551 assert(thread->is_Java_thread(), "sanity check"); | |
2552 JavaThread *jt = (JavaThread *) thread; | |
2553 ThreadBlockInVM tbivm(jt); | |
2554 OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); | |
2555 | |
2556 jt->set_suspend_equivalent(); | |
2557 // cleared by handle_special_suspend_equivalent_condition() or | |
2558 // java_suspend_self() via check_and_wait_while_suspended() | |
2559 | |
2560 slp->park(millis); | |
2561 | |
2562 // were we externally suspended while we were waiting? | |
2563 jt->check_and_wait_while_suspended(); | |
2564 } | |
2565 } | |
2566 } else { | |
2567 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); | |
2568 jlong prevtime = javaTimeNanos(); | |
2569 | |
2570 for (;;) { | |
2571 // It'd be nice to avoid the back-to-back javaTimeNanos() calls on | |
2572 // the 1st iteration ... | |
2573 jlong newtime = javaTimeNanos(); | |
2574 | |
2575 if (newtime - prevtime < 0) { | |
2576 // time moving backwards, should only happen if no monotonic clock | |
2577 // not a guarantee() because JVM should not abort on kernel/glibc bugs | |
2578 assert(!Bsd::supports_monotonic_clock(), "time moving backwards"); | |
2579 } else { | |
4712
e7dead7e90af
7117303: VM uses non-monotonic time source and complains that it is non-monotonic
johnc
parents:
4082
diff
changeset
|
2580 millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; |
3960 | 2581 } |
2582 | |
2583 if(millis <= 0) break ; | |
2584 | |
2585 prevtime = newtime; | |
2586 slp->park(millis); | |
2587 } | |
2588 return OS_OK ; | |
2589 } | |
2590 } | |
2591 | |
2592 int os::naked_sleep() { | |
2593 // %% make the sleep time an integer flag. for now use 1 millisec. | |
2594 return os::sleep(Thread::current(), 1, false); | |
2595 } | |
2596 | |
2597 // Sleep forever; naked call to OS-specific sleep; use with CAUTION | |
2598 void os::infinite_sleep() { | |
2599 while (true) { // sleep forever ... | |
2600 ::sleep(100); // ... 100 seconds at a time | |
2601 } | |
2602 } | |
2603 | |
2604 // Used to convert frequent JVM_Yield() to nops | |
2605 bool os::dont_yield() { | |
2606 return DontYieldALot; | |
2607 } | |
2608 | |
2609 void os::yield() { | |
2610 sched_yield(); | |
2611 } | |
2612 | |
2613 os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN ;} | |
2614 | |
2615 void os::yield_all(int attempts) { | |
2616 // Yields to all threads, including threads with lower priorities | |
2617 // Threads on Bsd are all with same priority. The Solaris style | |
2618 // os::yield_all() with nanosleep(1ms) is not necessary. | |
2619 sched_yield(); | |
2620 } | |
2621 | |
2622 // Called from the tight loops to possibly influence time-sharing heuristics | |
2623 void os::loop_breaker(int attempts) { | |
2624 os::yield_all(attempts); | |
2625 } | |
2626 | |
2627 //////////////////////////////////////////////////////////////////////////////// | |
2628 // thread priority support | |
2629 | |
2630 // Note: Normal Bsd applications are run with SCHED_OTHER policy. SCHED_OTHER | |
2631 // only supports dynamic priority, static priority must be zero. For real-time | |
2632 // applications, Bsd supports SCHED_RR which allows static priority (1-99). | |
2633 // However, for large multi-threaded applications, SCHED_RR is not only slower | |
2634 // than SCHED_OTHER, but also very unstable (my volano tests hang hard 4 out | |
2635 // of 5 runs - Sep 2005). | |
2636 // | |
2637 // The following code actually changes the niceness of kernel-thread/LWP. It | |
2638 // has an assumption that setpriority() only modifies one kernel-thread/LWP, | |
2639 // not the entire user process, and user level threads are 1:1 mapped to kernel | |
2640 // threads. It has always been the case, but could change in the future. For | |
2641 // this reason, the code should not be used as default (ThreadPriorityPolicy=0). | |
2642 // It is only used when ThreadPriorityPolicy=1 and requires root privilege. | |
2643 | |
6918 | 2644 #if !defined(__APPLE__) |
4854
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2645 int os::java_to_os_priority[CriticalPriority + 1] = { |
3960 | 2646 19, // 0 Entry should never be used |
2647 | |
2648 0, // 1 MinPriority | |
2649 3, // 2 | |
2650 6, // 3 | |
2651 | |
4854
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2652 10, // 4 |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2653 15, // 5 NormPriority |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2654 18, // 6 |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2655 |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2656 21, // 7 |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2657 25, // 8 |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2658 28, // 9 NearMaxPriority |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2659 |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2660 31, // 10 MaxPriority |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2661 |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2662 31 // 11 CriticalPriority |
3960 | 2663 }; |
6918 | 2664 #else |
3960 | 2665 /* Using Mach high-level priority assignments */ |
4854
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2666 int os::java_to_os_priority[CriticalPriority + 1] = { |
3960 | 2667 0, // 0 Entry should never be used (MINPRI_USER) |
2668 | |
2669 27, // 1 MinPriority | |
2670 28, // 2 | |
2671 29, // 3 | |
2672 | |
2673 30, // 4 | |
2674 31, // 5 NormPriority (BASEPRI_DEFAULT) | |
2675 32, // 6 | |
2676 | |
2677 33, // 7 | |
2678 34, // 8 | |
2679 35, // 9 NearMaxPriority | |
2680 | |
4854
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2681 36, // 10 MaxPriority |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2682 |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2683 36 // 11 CriticalPriority |
3960 | 2684 }; |
2685 #endif | |
2686 | |
2687 static int prio_init() { | |
2688 if (ThreadPriorityPolicy == 1) { | |
2689 // Only root can raise thread priority. Don't allow ThreadPriorityPolicy=1 | |
2690 // if effective uid is not root. Perhaps, a more elegant way of doing | |
2691 // this is to test CAP_SYS_NICE capability, but that will require libcap.so | |
2692 if (geteuid() != 0) { | |
2693 if (!FLAG_IS_DEFAULT(ThreadPriorityPolicy)) { | |
2694 warning("-XX:ThreadPriorityPolicy requires root privilege on Bsd"); | |
2695 } | |
2696 ThreadPriorityPolicy = 0; | |
2697 } | |
2698 } | |
4854
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2699 if (UseCriticalJavaThreadPriority) { |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2700 os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority]; |
de268c8a8075
7082553: Interpret Thread.setPriority(Thread.MAX_PRIORITY) to mean FX60 on Solaris 10 and 11
phh
parents:
4846
diff
changeset
|
2701 } |
3960 | 2702 return 0; |
2703 } | |
2704 | |
2705 OSReturn os::set_native_priority(Thread* thread, int newpri) { | |
2706 if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) return OS_OK; | |
2707 | |
2708 #ifdef __OpenBSD__ | |
2709 // OpenBSD pthread_setprio starves low priority threads | |
2710 return OS_OK; | |
2711 #elif defined(__FreeBSD__) | |
2712 int ret = pthread_setprio(thread->osthread()->pthread_id(), newpri); | |
2713 #elif defined(__APPLE__) || defined(__NetBSD__) | |
2714 struct sched_param sp; | |
2715 int policy; | |
2716 pthread_t self = pthread_self(); | |
2717 | |
2718 if (pthread_getschedparam(self, &policy, &sp) != 0) | |
2719 return OS_ERR; | |
2720 | |
2721 sp.sched_priority = newpri; | |
2722 if (pthread_setschedparam(self, policy, &sp) != 0) | |
2723 return OS_ERR; | |
2724 | |
2725 return OS_OK; | |
2726 #else | |
2727 int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri); | |
2728 return (ret == 0) ? OS_OK : OS_ERR; | |
2729 #endif | |
2730 } | |
2731 | |
2732 OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) { | |
2733 if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) { | |
2734 *priority_ptr = java_to_os_priority[NormPriority]; | |
2735 return OS_OK; | |
2736 } | |
2737 | |
2738 errno = 0; | |
2739 #if defined(__OpenBSD__) || defined(__FreeBSD__) | |
2740 *priority_ptr = pthread_getprio(thread->osthread()->pthread_id()); | |
2741 #elif defined(__APPLE__) || defined(__NetBSD__) | |
2742 int policy; | |
2743 struct sched_param sp; | |
2744 | |
2745 pthread_getschedparam(pthread_self(), &policy, &sp); | |
2746 *priority_ptr = sp.sched_priority; | |
2747 #else | |
2748 *priority_ptr = getpriority(PRIO_PROCESS, thread->osthread()->thread_id()); | |
2749 #endif | |
2750 return (*priority_ptr != -1 || errno == 0 ? OS_OK : OS_ERR); | |
2751 } | |
2752 | |
2753 // Hint to the underlying OS that a task switch would not be good. | |
2754 // Void return because it's a hint and can fail. | |
2755 void os::hint_no_preempt() {} | |
2756 | |
2757 //////////////////////////////////////////////////////////////////////////////// | |
2758 // suspend/resume support | |
2759 | |
2760 // the low-level signal-based suspend/resume support is a remnant from the | |
2761 // old VM-suspension that used to be for java-suspension, safepoints etc, | |
2762 // within hotspot. Now there is a single use-case for this: | |
2763 // - calling get_thread_pc() on the VMThread by the flat-profiler task | |
2764 // that runs in the watcher thread. | |
2765 // The remaining code is greatly simplified from the more general suspension | |
2766 // code that used to be used. | |
2767 // | |
2768 // The protocol is quite simple: | |
2769 // - suspend: | |
2770 // - sends a signal to the target thread | |
2771 // - polls the suspend state of the osthread using a yield loop | |
2772 // - target thread signal handler (SR_handler) sets suspend state | |
2773 // and blocks in sigsuspend until continued | |
2774 // - resume: | |
2775 // - sets target osthread state to continue | |
2776 // - sends signal to end the sigsuspend loop in the SR_handler | |
2777 // | |
2778 // Note that the SR_lock plays no role in this suspend/resume protocol. | |
2779 // | |
2780 | |
2781 static void resume_clear_context(OSThread *osthread) { | |
2782 osthread->set_ucontext(NULL); | |
2783 osthread->set_siginfo(NULL); | |
2784 } | |
2785 | |
2786 static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) { | |
2787 osthread->set_ucontext(context); | |
2788 osthread->set_siginfo(siginfo); | |
2789 } | |
2790 | |
2791 // | |
2792 // Handler function invoked when a thread's execution is suspended or | |
2793 // resumed. We have to be careful that only async-safe functions are | |
2794 // called here (Note: most pthread functions are not async safe and | |
2795 // should be avoided.) | |
2796 // | |
2797 // Note: sigwait() is a more natural fit than sigsuspend() from an | |
2798 // interface point of view, but sigwait() prevents the signal hander | |
2799 // from being run. libpthread would get very confused by not having | |
2800 // its signal handlers run and prevents sigwait()'s use with the | |
2801 // mutex granting granting signal. | |
2802 // | |
10405 | 2803 // Currently only ever called on the VMThread or JavaThread |
3960 | 2804 // |
2805 static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { | |
2806 // Save and restore errno to avoid confusing native code with EINTR | |
2807 // after sigsuspend. | |
2808 int old_errno = errno; | |
2809 | |
2810 Thread* thread = Thread::current(); | |
2811 OSThread* osthread = thread->osthread(); | |
10405 | 2812 assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); |
2813 | |
2814 os::SuspendResume::State current = osthread->sr.state(); | |
2815 if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { | |
3960 | 2816 suspend_save_context(osthread, siginfo, context); |
2817 | |
10405 | 2818 // attempt to switch the state, we assume we had a SUSPEND_REQUEST |
2819 os::SuspendResume::State state = osthread->sr.suspended(); | |
2820 if (state == os::SuspendResume::SR_SUSPENDED) { | |
2821 sigset_t suspend_set; // signals for sigsuspend() | |
2822 | |
2823 // get current set of blocked signals and unblock resume signal | |
2824 pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); | |
2825 sigdelset(&suspend_set, SR_signum); | |
2826 | |
2827 sr_semaphore.signal(); | |
2828 // wait here until we are resumed | |
2829 while (1) { | |
2830 sigsuspend(&suspend_set); | |
2831 | |
2832 os::SuspendResume::State result = osthread->sr.running(); | |
2833 if (result == os::SuspendResume::SR_RUNNING) { | |
2834 sr_semaphore.signal(); | |
2835 break; | |
2836 } else if (result != os::SuspendResume::SR_SUSPENDED) { | |
2837 ShouldNotReachHere(); | |
2838 } | |
2839 } | |
2840 | |
2841 } else if (state == os::SuspendResume::SR_RUNNING) { | |
2842 // request was cancelled, continue | |
2843 } else { | |
2844 ShouldNotReachHere(); | |
2845 } | |
3960 | 2846 |
2847 resume_clear_context(osthread); | |
10405 | 2848 } else if (current == os::SuspendResume::SR_RUNNING) { |
2849 // request was cancelled, continue | |
2850 } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { | |
2851 // ignore | |
3960 | 2852 } else { |
10405 | 2853 // ignore |
3960 | 2854 } |
2855 | |
2856 errno = old_errno; | |
2857 } | |
2858 | |
2859 | |
2860 static int SR_initialize() { | |
2861 struct sigaction act; | |
2862 char *s; | |
2863 /* Get signal number to use for suspend/resume */ | |
2864 if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) { | |
2865 int sig = ::strtol(s, 0, 10); | |
2866 if (sig > 0 || sig < NSIG) { | |
2867 SR_signum = sig; | |
2868 } | |
2869 } | |
2870 | |
2871 assert(SR_signum > SIGSEGV && SR_signum > SIGBUS, | |
2872 "SR_signum must be greater than max(SIGSEGV, SIGBUS), see 4355769"); | |
2873 | |
2874 sigemptyset(&SR_sigset); | |
2875 sigaddset(&SR_sigset, SR_signum); | |
2876 | |
2877 /* Set up signal handler for suspend/resume */ | |
2878 act.sa_flags = SA_RESTART|SA_SIGINFO; | |
2879 act.sa_handler = (void (*)(int)) SR_handler; | |
2880 | |
2881 // SR_signum is blocked by default. | |
2882 // 4528190 - We also need to block pthread restart signal (32 on all | |
2883 // supported Bsd platforms). Note that BsdThreads need to block | |
2884 // this signal for all threads to work properly. So we don't have | |
2885 // to use hard-coded signal number when setting up the mask. | |
2886 pthread_sigmask(SIG_BLOCK, NULL, &act.sa_mask); | |
2887 | |
2888 if (sigaction(SR_signum, &act, 0) == -1) { | |
2889 return -1; | |
2890 } | |
2891 | |
2892 // Save signal flag | |
2893 os::Bsd::set_our_sigflags(SR_signum, act.sa_flags); | |
2894 return 0; | |
2895 } | |
2896 | |
10405 | 2897 static int sr_notify(OSThread* osthread) { |
2898 int status = pthread_kill(osthread->pthread_id(), SR_signum); | |
2899 assert_status(status == 0, status, "pthread_kill"); | |
2900 return status; | |
2901 } | |
2902 | |
2903 // "Randomly" selected value for how long we want to spin | |
2904 // before bailing out on suspending a thread, also how often | |
2905 // we send a signal to a thread we want to resume | |
2906 static const int RANDOMLY_LARGE_INTEGER = 1000000; | |
2907 static const int RANDOMLY_LARGE_INTEGER2 = 100; | |
3960 | 2908 |
2909 // returns true on success and false on error - really an error is fatal | |
2910 // but this seems the normal response to library errors | |
2911 static bool do_suspend(OSThread* osthread) { | |
10405 | 2912 assert(osthread->sr.is_running(), "thread should be running"); |
2913 assert(!sr_semaphore.trywait(), "semaphore has invalid state"); | |
2914 | |
3960 | 2915 // mark as suspended and send signal |
10405 | 2916 if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { |
2917 // failed to switch, state wasn't running? | |
2918 ShouldNotReachHere(); | |
3960 | 2919 return false; |
2920 } | |
10405 | 2921 |
2922 if (sr_notify(osthread) != 0) { | |
2923 ShouldNotReachHere(); | |
2924 } | |
2925 | |
2926 // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED | |
2927 while (true) { | |
2928 if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { | |
2929 break; | |
2930 } else { | |
2931 // timeout | |
2932 os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); | |
2933 if (cancelled == os::SuspendResume::SR_RUNNING) { | |
2934 return false; | |
2935 } else if (cancelled == os::SuspendResume::SR_SUSPENDED) { | |
2936 // make sure that we consume the signal on the semaphore as well | |
2937 sr_semaphore.wait(); | |
2938 break; | |
2939 } else { | |
2940 ShouldNotReachHere(); | |
2941 return false; | |
2942 } | |
2943 } | |
2944 } | |
2945 | |
2946 guarantee(osthread->sr.is_suspended(), "Must be suspended"); | |
2947 return true; | |
3960 | 2948 } |
2949 | |
2950 static void do_resume(OSThread* osthread) { | |
2951 assert(osthread->sr.is_suspended(), "thread should be suspended"); | |
10405 | 2952 assert(!sr_semaphore.trywait(), "invalid semaphore state"); |
2953 | |
2954 if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) { | |
2955 // failed to switch to WAKEUP_REQUEST | |
2956 ShouldNotReachHere(); | |
2957 return; | |
2958 } | |
2959 | |
2960 while (true) { | |
2961 if (sr_notify(osthread) == 0) { | |
2962 if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { | |
2963 if (osthread->sr.is_running()) { | |
2964 return; | |
2965 } | |
2966 } | |
2967 } else { | |
2968 ShouldNotReachHere(); | |
3960 | 2969 } |
2970 } | |
10405 | 2971 |
2972 guarantee(osthread->sr.is_running(), "Must be running!"); | |
3960 | 2973 } |
2974 | |
2975 //////////////////////////////////////////////////////////////////////////////// | |
2976 // interrupt support | |
2977 | |
2978 void os::interrupt(Thread* thread) { | |
2979 assert(Thread::current() == thread || Threads_lock->owned_by_self(), | |
2980 "possibility of dangling Thread pointer"); | |
2981 | |
2982 OSThread* osthread = thread->osthread(); | |
2983 | |
2984 if (!osthread->interrupted()) { | |
2985 osthread->set_interrupted(true); | |
2986 // More than one thread can get here with the same value of osthread, | |
2987 // resulting in multiple notifications. We do, however, want the store | |
2988 // to interrupted() to be visible to other threads before we execute unpark(). | |
2989 OrderAccess::fence(); | |
2990 ParkEvent * const slp = thread->_SleepEvent ; | |
2991 if (slp != NULL) slp->unpark() ; | |
2992 } | |
2993 | |
2994 // For JSR166. Unpark even if interrupt status already was set | |
2995 if (thread->is_Java_thread()) | |
2996 ((JavaThread*)thread)->parker()->unpark(); | |
2997 | |
2998 ParkEvent * ev = thread->_ParkEvent ; | |
2999 if (ev != NULL) ev->unpark() ; | |
3000 | |
3001 } | |
3002 | |
3003 bool os::is_interrupted(Thread* thread, bool clear_interrupted) { | |
3004 assert(Thread::current() == thread || Threads_lock->owned_by_self(), | |
3005 "possibility of dangling Thread pointer"); | |
3006 | |
3007 OSThread* osthread = thread->osthread(); | |
3008 | |
3009 bool interrupted = osthread->interrupted(); | |
3010 | |
3011 if (interrupted && clear_interrupted) { | |
3012 osthread->set_interrupted(false); | |
3013 // consider thread->_SleepEvent->reset() ... optional optimization | |
3014 } | |
3015 | |
3016 return interrupted; | |
3017 } | |
3018 | |
3019 /////////////////////////////////////////////////////////////////////////////////// | |
3020 // signal handling (except suspend/resume) | |
3021 | |
3022 // This routine may be used by user applications as a "hook" to catch signals. | |
3023 // The user-defined signal handler must pass unrecognized signals to this | |
3024 // routine, and if it returns true (non-zero), then the signal handler must | |
3025 // return immediately. If the flag "abort_if_unrecognized" is true, then this | |
3026 // routine will never retun false (zero), but instead will execute a VM panic | |
3027 // routine kill the process. | |
3028 // | |
3029 // If this routine returns false, it is OK to call it again. This allows | |
3030 // the user-defined signal handler to perform checks either before or after | |
3031 // the VM performs its own checks. Naturally, the user code would be making | |
3032 // a serious error if it tried to handle an exception (such as a null check | |
3033 // or breakpoint) that the VM was generating for its own correct operation. | |
3034 // | |
3035 // This routine may recognize any of the following kinds of signals: | |
3036 // SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1. | |
3037 // It should be consulted by handlers for any of those signals. | |
3038 // | |
3039 // The caller of this routine must pass in the three arguments supplied | |
3040 // to the function referred to in the "sa_sigaction" (not the "sa_handler") | |
3041 // field of the structure passed to sigaction(). This routine assumes that | |
3042 // the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART. | |
3043 // | |
3044 // Note that the VM will print warnings if it detects conflicting signal | |
3045 // handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers". | |
3046 // | |
3047 extern "C" JNIEXPORT int | |
3048 JVM_handle_bsd_signal(int signo, siginfo_t* siginfo, | |
3049 void* ucontext, int abort_if_unrecognized); | |
3050 | |
3051 void signalHandler(int sig, siginfo_t* info, void* uc) { | |
3052 assert(info != NULL && uc != NULL, "it must be old kernel"); | |
8067 | 3053 int orig_errno = errno; // Preserve errno value over signal handler. |
3960 | 3054 JVM_handle_bsd_signal(sig, info, uc, true); |
8067 | 3055 errno = orig_errno; |
3960 | 3056 } |
3057 | |
3058 | |
3059 // This boolean allows users to forward their own non-matching signals | |
3060 // to JVM_handle_bsd_signal, harmlessly. | |
3061 bool os::Bsd::signal_handlers_are_installed = false; | |
3062 | |
3063 // For signal-chaining | |
3064 struct sigaction os::Bsd::sigact[MAXSIGNUM]; | |
3065 unsigned int os::Bsd::sigs = 0; | |
3066 bool os::Bsd::libjsig_is_loaded = false; | |
3067 typedef struct sigaction *(*get_signal_t)(int); | |
3068 get_signal_t os::Bsd::get_signal_action = NULL; | |
3069 | |
3070 struct sigaction* os::Bsd::get_chained_signal_action(int sig) { | |
3071 struct sigaction *actp = NULL; | |
3072 | |
3073 if (libjsig_is_loaded) { | |
3074 // Retrieve the old signal handler from libjsig | |
3075 actp = (*get_signal_action)(sig); | |
3076 } | |
3077 if (actp == NULL) { | |
3078 // Retrieve the preinstalled signal handler from jvm | |
3079 actp = get_preinstalled_handler(sig); | |
3080 } | |
3081 | |
3082 return actp; | |
3083 } | |
3084 | |
3085 static bool call_chained_handler(struct sigaction *actp, int sig, | |
3086 siginfo_t *siginfo, void *context) { | |
3087 // Call the old signal handler | |
3088 if (actp->sa_handler == SIG_DFL) { | |
3089 // It's more reasonable to let jvm treat it as an unexpected exception | |
3090 // instead of taking the default action. | |
3091 return false; | |
3092 } else if (actp->sa_handler != SIG_IGN) { | |
3093 if ((actp->sa_flags & SA_NODEFER) == 0) { | |
3094 // automaticlly block the signal | |
3095 sigaddset(&(actp->sa_mask), sig); | |
3096 } | |
3097 | |
3098 sa_handler_t hand; | |
3099 sa_sigaction_t sa; | |
3100 bool siginfo_flag_set = (actp->sa_flags & SA_SIGINFO) != 0; | |
3101 // retrieve the chained handler | |
3102 if (siginfo_flag_set) { | |
3103 sa = actp->sa_sigaction; | |
3104 } else { | |
3105 hand = actp->sa_handler; | |
3106 } | |
3107 | |
3108 if ((actp->sa_flags & SA_RESETHAND) != 0) { | |
3109 actp->sa_handler = SIG_DFL; | |
3110 } | |
3111 | |
3112 // try to honor the signal mask | |
3113 sigset_t oset; | |
3114 pthread_sigmask(SIG_SETMASK, &(actp->sa_mask), &oset); | |
3115 | |
3116 // call into the chained handler | |
3117 if (siginfo_flag_set) { | |
3118 (*sa)(sig, siginfo, context); | |
3119 } else { | |
3120 (*hand)(sig); | |
3121 } | |
3122 | |
3123 // restore the signal mask | |
3124 pthread_sigmask(SIG_SETMASK, &oset, 0); | |
3125 } | |
3126 // Tell jvm's signal handler the signal is taken care of. | |
3127 return true; | |
3128 } | |
3129 | |
3130 bool os::Bsd::chained_handler(int sig, siginfo_t* siginfo, void* context) { | |
3131 bool chained = false; | |
3132 // signal-chaining | |
3133 if (UseSignalChaining) { | |
3134 struct sigaction *actp = get_chained_signal_action(sig); | |
3135 if (actp != NULL) { | |
3136 chained = call_chained_handler(actp, sig, siginfo, context); | |
3137 } | |
3138 } | |
3139 return chained; | |
3140 } | |
3141 | |
3142 struct sigaction* os::Bsd::get_preinstalled_handler(int sig) { | |
3143 if ((( (unsigned int)1 << sig ) & sigs) != 0) { | |
3144 return &sigact[sig]; | |
3145 } | |
3146 return NULL; | |
3147 } | |
3148 | |
3149 void os::Bsd::save_preinstalled_handler(int sig, struct sigaction& oldAct) { | |
3150 assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); | |
3151 sigact[sig] = oldAct; | |
3152 sigs |= (unsigned int)1 << sig; | |
3153 } | |
3154 | |
3155 // for diagnostic | |
3156 int os::Bsd::sigflags[MAXSIGNUM]; | |
3157 | |
3158 int os::Bsd::get_our_sigflags(int sig) { | |
3159 assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); | |
3160 return sigflags[sig]; | |
3161 } | |
3162 | |
3163 void os::Bsd::set_our_sigflags(int sig, int flags) { | |
3164 assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); | |
3165 sigflags[sig] = flags; | |
3166 } | |
3167 | |
3168 void os::Bsd::set_signal_handler(int sig, bool set_installed) { | |
3169 // Check for overwrite. | |
3170 struct sigaction oldAct; | |
3171 sigaction(sig, (struct sigaction*)NULL, &oldAct); | |
3172 | |
3173 void* oldhand = oldAct.sa_sigaction | |
3174 ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) | |
3175 : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); | |
3176 if (oldhand != CAST_FROM_FN_PTR(void*, SIG_DFL) && | |
3177 oldhand != CAST_FROM_FN_PTR(void*, SIG_IGN) && | |
3178 oldhand != CAST_FROM_FN_PTR(void*, (sa_sigaction_t)signalHandler)) { | |
3179 if (AllowUserSignalHandlers || !set_installed) { | |
3180 // Do not overwrite; user takes responsibility to forward to us. | |
3181 return; | |
3182 } else if (UseSignalChaining) { | |
3183 // save the old handler in jvm | |
3184 save_preinstalled_handler(sig, oldAct); | |
3185 // libjsig also interposes the sigaction() call below and saves the | |
3186 // old sigaction on it own. | |
3187 } else { | |
3188 fatal(err_msg("Encountered unexpected pre-existing sigaction handler " | |
3189 "%#lx for signal %d.", (long)oldhand, sig)); | |
3190 } | |
3191 } | |
3192 | |
3193 struct sigaction sigAct; | |
3194 sigfillset(&(sigAct.sa_mask)); | |
3195 sigAct.sa_handler = SIG_DFL; | |
3196 if (!set_installed) { | |
3197 sigAct.sa_flags = SA_SIGINFO|SA_RESTART; | |
3198 } else { | |
3199 sigAct.sa_sigaction = signalHandler; | |
3200 sigAct.sa_flags = SA_SIGINFO|SA_RESTART; | |
3201 } | |
10386
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3202 #if __APPLE__ |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3203 // Needed for main thread as XNU (Mac OS X kernel) will only deliver SIGSEGV |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3204 // (which starts as SIGBUS) on main thread with faulting address inside "stack+guard pages" |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3205 // if the signal handler declares it will handle it on alternate stack. |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3206 // Notice we only declare we will handle it on alt stack, but we are not |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3207 // actually going to use real alt stack - this is just a workaround. |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3208 // Please see ux_exception.c, method catch_mach_exception_raise for details |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3209 // link http://www.opensource.apple.com/source/xnu/xnu-2050.18.24/bsd/uxkern/ux_exception.c |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3210 if (sig == SIGSEGV) { |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3211 sigAct.sa_flags |= SA_ONSTACK; |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3212 } |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3213 #endif |
6bf8b8bb7c19
8009302: Mac OS X: JVM crash on infinite recursion on Appkit Thread
hseigel
parents:
10208
diff
changeset
|
3214 |
3960 | 3215 // Save flags, which are set by ours |
3216 assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); | |
3217 sigflags[sig] = sigAct.sa_flags; | |
3218 | |
3219 int ret = sigaction(sig, &sigAct, &oldAct); | |
3220 assert(ret == 0, "check"); | |
3221 | |
3222 void* oldhand2 = oldAct.sa_sigaction | |
3223 ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) | |
3224 : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); | |
3225 assert(oldhand2 == oldhand, "no concurrent signal handler installation"); | |
3226 } | |
3227 | |
3228 // install signal handlers for signals that HotSpot needs to | |
3229 // handle in order to support Java-level exception handling. | |
3230 | |
3231 void os::Bsd::install_signal_handlers() { | |
3232 if (!signal_handlers_are_installed) { | |
3233 signal_handlers_are_installed = true; | |
3234 | |
3235 // signal-chaining | |
3236 typedef void (*signal_setting_t)(); | |
3237 signal_setting_t begin_signal_setting = NULL; | |
3238 signal_setting_t end_signal_setting = NULL; | |
3239 begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t, | |
3240 dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting")); | |
3241 if (begin_signal_setting != NULL) { | |
3242 end_signal_setting = CAST_TO_FN_PTR(signal_setting_t, | |
3243 dlsym(RTLD_DEFAULT, "JVM_end_signal_setting")); | |
3244 get_signal_action = CAST_TO_FN_PTR(get_signal_t, | |
3245 dlsym(RTLD_DEFAULT, "JVM_get_signal_action")); | |
3246 libjsig_is_loaded = true; | |
3247 assert(UseSignalChaining, "should enable signal-chaining"); | |
3248 } | |
3249 if (libjsig_is_loaded) { | |
3250 // Tell libjsig jvm is setting signal handlers | |
3251 (*begin_signal_setting)(); | |
3252 } | |
3253 | |
3254 set_signal_handler(SIGSEGV, true); | |
3255 set_signal_handler(SIGPIPE, true); | |
3256 set_signal_handler(SIGBUS, true); | |
3257 set_signal_handler(SIGILL, true); | |
3258 set_signal_handler(SIGFPE, true); | |
3259 set_signal_handler(SIGXFSZ, true); | |
3260 | |
3261 #if defined(__APPLE__) | |
3262 // In Mac OS X 10.4, CrashReporter will write a crash log for all 'fatal' signals, including | |
3263 // signals caught and handled by the JVM. To work around this, we reset the mach task | |
3264 // signal handler that's placed on our process by CrashReporter. This disables | |
3265 // CrashReporter-based reporting. | |
3266 // | |
3267 // This work-around is not necessary for 10.5+, as CrashReporter no longer intercedes | |
3268 // on caught fatal signals. | |
3269 // | |
3270 // Additionally, gdb installs both standard BSD signal handlers, and mach exception | |
3271 // handlers. By replacing the existing task exception handler, we disable gdb's mach | |
3272 // exception handling, while leaving the standard BSD signal handlers functional. | |
3273 kern_return_t kr; | |
3274 kr = task_set_exception_ports(mach_task_self(), | |
3275 EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, | |
3276 MACH_PORT_NULL, | |
3277 EXCEPTION_STATE_IDENTITY, | |
3278 MACHINE_THREAD_STATE); | |
3279 | |
3280 assert(kr == KERN_SUCCESS, "could not set mach task signal handler"); | |
3281 #endif | |
3282 | |
3283 if (libjsig_is_loaded) { | |
3284 // Tell libjsig jvm finishes setting signal handlers | |
3285 (*end_signal_setting)(); | |
3286 } | |
3287 | |
3288 // We don't activate signal checker if libjsig is in place, we trust ourselves | |
3289 // and if UserSignalHandler is installed all bets are off | |
3290 if (CheckJNICalls) { | |
3291 if (libjsig_is_loaded) { | |
12096
3a57fa7a4cd0
7121403: [TESTBUG] runtime/7051189/Xchecksig.sh fails on 64bit solaris
hseigel
parents:
12095
diff
changeset
|
3292 if (PrintJNIResolving) { |
3a57fa7a4cd0
7121403: [TESTBUG] runtime/7051189/Xchecksig.sh fails on 64bit solaris
hseigel
parents:
12095
diff
changeset
|
3293 tty->print_cr("Info: libjsig is activated, all active signal checking is disabled"); |
3a57fa7a4cd0
7121403: [TESTBUG] runtime/7051189/Xchecksig.sh fails on 64bit solaris
hseigel
parents:
12095
diff
changeset
|
3294 } |
3960 | 3295 check_signals = false; |
3296 } | |
3297 if (AllowUserSignalHandlers) { | |
12096
3a57fa7a4cd0
7121403: [TESTBUG] runtime/7051189/Xchecksig.sh fails on 64bit solaris
hseigel
parents:
12095
diff
changeset
|
3298 if (PrintJNIResolving) { |
3a57fa7a4cd0
7121403: [TESTBUG] runtime/7051189/Xchecksig.sh fails on 64bit solaris
hseigel
parents:
12095
diff
changeset
|
3299 tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); |
3a57fa7a4cd0
7121403: [TESTBUG] runtime/7051189/Xchecksig.sh fails on 64bit solaris
hseigel
parents:
12095
diff
changeset
|
3300 } |
3960 | 3301 check_signals = false; |
3302 } | |
3303 } | |
3304 } | |
3305 } | |
3306 | |
3307 | |
3308 ///// | |
3309 // glibc on Bsd platform uses non-documented flag | |
3310 // to indicate, that some special sort of signal | |
3311 // trampoline is used. | |
3312 // We will never set this flag, and we should | |
3313 // ignore this flag in our diagnostic | |
3314 #ifdef SIGNIFICANT_SIGNAL_MASK | |
3315 #undef SIGNIFICANT_SIGNAL_MASK | |
3316 #endif | |
3317 #define SIGNIFICANT_SIGNAL_MASK (~0x04000000) | |
3318 | |
3319 static const char* get_signal_handler_name(address handler, | |
3320 char* buf, int buflen) { | |
3321 int offset; | |
3322 bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset); | |
3323 if (found) { | |
3324 // skip directory names | |
3325 const char *p1, *p2; | |
3326 p1 = buf; | |
3327 size_t len = strlen(os::file_separator()); | |
3328 while ((p2 = strstr(p1, os::file_separator())) != NULL) p1 = p2 + len; | |
3329 jio_snprintf(buf, buflen, "%s+0x%x", p1, offset); | |
3330 } else { | |
3331 jio_snprintf(buf, buflen, PTR_FORMAT, handler); | |
3332 } | |
3333 return buf; | |
3334 } | |
3335 | |
3336 static void print_signal_handler(outputStream* st, int sig, | |
3337 char* buf, size_t buflen) { | |
3338 struct sigaction sa; | |
3339 | |
3340 sigaction(sig, NULL, &sa); | |
3341 | |
3342 // See comment for SIGNIFICANT_SIGNAL_MASK define | |
3343 sa.sa_flags &= SIGNIFICANT_SIGNAL_MASK; | |
3344 | |
3345 st->print("%s: ", os::exception_name(sig, buf, buflen)); | |
3346 | |
3347 address handler = (sa.sa_flags & SA_SIGINFO) | |
3348 ? CAST_FROM_FN_PTR(address, sa.sa_sigaction) | |
3349 : CAST_FROM_FN_PTR(address, sa.sa_handler); | |
3350 | |
3351 if (handler == CAST_FROM_FN_PTR(address, SIG_DFL)) { | |
3352 st->print("SIG_DFL"); | |
3353 } else if (handler == CAST_FROM_FN_PTR(address, SIG_IGN)) { | |
3354 st->print("SIG_IGN"); | |
3355 } else { | |
3356 st->print("[%s]", get_signal_handler_name(handler, buf, buflen)); | |
3357 } | |
3358 | |
3359 st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask); | |
3360 | |
3361 address rh = VMError::get_resetted_sighandler(sig); | |
3362 // May be, handler was resetted by VMError? | |
3363 if(rh != NULL) { | |
3364 handler = rh; | |
3365 sa.sa_flags = VMError::get_resetted_sigflags(sig) & SIGNIFICANT_SIGNAL_MASK; | |
3366 } | |
3367 | |
3368 st->print(", sa_flags=" PTR32_FORMAT, sa.sa_flags); | |
3369 | |
3370 // Check: is it our handler? | |
3371 if(handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler) || | |
3372 handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler)) { | |
3373 // It is our signal handler | |
3374 // check for flags, reset system-used one! | |
3375 if((int)sa.sa_flags != os::Bsd::get_our_sigflags(sig)) { | |
3376 st->print( | |
3377 ", flags was changed from " PTR32_FORMAT ", consider using jsig library", | |
3378 os::Bsd::get_our_sigflags(sig)); | |
3379 } | |
3380 } | |
3381 st->cr(); | |
3382 } | |
3383 | |
3384 | |
3385 #define DO_SIGNAL_CHECK(sig) \ | |
3386 if (!sigismember(&check_signal_done, sig)) \ | |
3387 os::Bsd::check_signal_handler(sig) | |
3388 | |
3389 // This method is a periodic task to check for misbehaving JNI applications | |
3390 // under CheckJNI, we can add any periodic checks here | |
3391 | |
3392 void os::run_periodic_checks() { | |
3393 | |
3394 if (check_signals == false) return; | |
3395 | |
3396 // SEGV and BUS if overridden could potentially prevent | |
3397 // generation of hs*.log in the event of a crash, debugging | |
3398 // such a case can be very challenging, so we absolutely | |
3399 // check the following for a good measure: | |
3400 DO_SIGNAL_CHECK(SIGSEGV); | |
3401 DO_SIGNAL_CHECK(SIGILL); | |
3402 DO_SIGNAL_CHECK(SIGFPE); | |
3403 DO_SIGNAL_CHECK(SIGBUS); | |
3404 DO_SIGNAL_CHECK(SIGPIPE); | |
3405 DO_SIGNAL_CHECK(SIGXFSZ); | |
3406 | |
3407 | |
3408 // ReduceSignalUsage allows the user to override these handlers | |
3409 // see comments at the very top and jvm_solaris.h | |
3410 if (!ReduceSignalUsage) { | |
3411 DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL); | |
3412 DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL); | |
3413 DO_SIGNAL_CHECK(SHUTDOWN3_SIGNAL); | |
3414 DO_SIGNAL_CHECK(BREAK_SIGNAL); | |
3415 } | |
3416 | |
3417 DO_SIGNAL_CHECK(SR_signum); | |
3418 DO_SIGNAL_CHECK(INTERRUPT_SIGNAL); | |
3419 } | |
3420 | |
3421 typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *); | |
3422 | |
3423 static os_sigaction_t os_sigaction = NULL; | |
3424 | |
3425 void os::Bsd::check_signal_handler(int sig) { | |
3426 char buf[O_BUFLEN]; | |
3427 address jvmHandler = NULL; | |
3428 | |
3429 | |
3430 struct sigaction act; | |
3431 if (os_sigaction == NULL) { | |
3432 // only trust the default sigaction, in case it has been interposed | |
3433 os_sigaction = (os_sigaction_t)dlsym(RTLD_DEFAULT, "sigaction"); | |
3434 if (os_sigaction == NULL) return; | |
3435 } | |
3436 | |
3437 os_sigaction(sig, (struct sigaction*)NULL, &act); | |
3438 | |
3439 | |
3440 act.sa_flags &= SIGNIFICANT_SIGNAL_MASK; | |
3441 | |
3442 address thisHandler = (act.sa_flags & SA_SIGINFO) | |
3443 ? CAST_FROM_FN_PTR(address, act.sa_sigaction) | |
3444 : CAST_FROM_FN_PTR(address, act.sa_handler) ; | |
3445 | |
3446 | |
3447 switch(sig) { | |
3448 case SIGSEGV: | |
3449 case SIGBUS: | |
3450 case SIGFPE: | |
3451 case SIGPIPE: | |
3452 case SIGILL: | |
3453 case SIGXFSZ: | |
3454 jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler); | |
3455 break; | |
3456 | |
3457 case SHUTDOWN1_SIGNAL: | |
3458 case SHUTDOWN2_SIGNAL: | |
3459 case SHUTDOWN3_SIGNAL: | |
3460 case BREAK_SIGNAL: | |
3461 jvmHandler = (address)user_handler(); | |
3462 break; | |
3463 | |
3464 case INTERRUPT_SIGNAL: | |
3465 jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL); | |
3466 break; | |
3467 | |
3468 default: | |
3469 if (sig == SR_signum) { | |
3470 jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler); | |
3471 } else { | |
3472 return; | |
3473 } | |
3474 break; | |
3475 } | |
3476 | |
3477 if (thisHandler != jvmHandler) { | |
3478 tty->print("Warning: %s handler ", exception_name(sig, buf, O_BUFLEN)); | |
3479 tty->print("expected:%s", get_signal_handler_name(jvmHandler, buf, O_BUFLEN)); | |
3480 tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN)); | |
3481 // No need to check this sig any longer | |
3482 sigaddset(&check_signal_done, sig); | |
3483 } else if(os::Bsd::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Bsd::get_our_sigflags(sig)) { | |
3484 tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN)); | |
3485 tty->print("expected:" PTR32_FORMAT, os::Bsd::get_our_sigflags(sig)); | |
3486 tty->print_cr(" found:" PTR32_FORMAT, act.sa_flags); | |
3487 // No need to check this sig any longer | |
3488 sigaddset(&check_signal_done, sig); | |
3489 } | |
3490 | |
3491 // Dump all the signal | |
3492 if (sigismember(&check_signal_done, sig)) { | |
3493 print_signal_handlers(tty, buf, O_BUFLEN); | |
3494 } | |
3495 } | |
3496 | |
3497 extern void report_error(char* file_name, int line_no, char* title, char* format, ...); | |
3498 | |
3499 extern bool signal_name(int signo, char* buf, size_t len); | |
3500 | |
3501 const char* os::exception_name(int exception_code, char* buf, size_t size) { | |
3502 if (0 < exception_code && exception_code <= SIGRTMAX) { | |
3503 // signal | |
3504 if (!signal_name(exception_code, buf, size)) { | |
3505 jio_snprintf(buf, size, "SIG%d", exception_code); | |
3506 } | |
3507 return buf; | |
3508 } else { | |
3509 return NULL; | |
3510 } | |
3511 } | |
3512 | |
3513 // this is called _before_ the most of global arguments have been parsed | |
3514 void os::init(void) { | |
3515 char dummy; /* used to get a guess on initial stack address */ | |
3516 // first_hrtime = gethrtime(); | |
3517 | |
3518 // With BsdThreads the JavaMain thread pid (primordial thread) | |
3519 // is different than the pid of the java launcher thread. | |
3520 // So, on Bsd, the launcher thread pid is passed to the VM | |
3521 // via the sun.java.launcher.pid property. | |
3522 // Use this property instead of getpid() if it was correctly passed. | |
3523 // See bug 6351349. | |
3524 pid_t java_launcher_pid = (pid_t) Arguments::sun_java_launcher_pid(); | |
3525 | |
3526 _initial_pid = (java_launcher_pid > 0) ? java_launcher_pid : getpid(); | |
3527 | |
3528 clock_tics_per_sec = CLK_TCK; | |
3529 | |
3530 init_random(1234567); | |
3531 | |
3532 ThreadCritical::initialize(); | |
3533 | |
3534 Bsd::set_page_size(getpagesize()); | |
3535 if (Bsd::page_size() == -1) { | |
3536 fatal(err_msg("os_bsd.cpp: os::init: sysconf failed (%s)", | |
3537 strerror(errno))); | |
3538 } | |
3539 init_page_sizes((size_t) Bsd::page_size()); | |
3540 | |
3541 Bsd::initialize_system_info(); | |
3542 | |
3543 // main_thread points to the aboriginal thread | |
3544 Bsd::_main_thread = pthread_self(); | |
3545 | |
3546 Bsd::clock_init(); | |
3547 initial_time_count = os::elapsed_counter(); | |
3548 | |
3549 #ifdef __APPLE__ | |
3550 // XXXDARWIN | |
3551 // Work around the unaligned VM callbacks in hotspot's | |
3552 // sharedRuntime. The callbacks don't use SSE2 instructions, and work on | |
3553 // Linux, Solaris, and FreeBSD. On Mac OS X, dyld (rightly so) enforces | |
3554 // alignment when doing symbol lookup. To work around this, we force early | |
3555 // binding of all symbols now, thus binding when alignment is known-good. | |
3556 _dyld_bind_fully_image_containing_address((const void *) &os::init); | |
3557 #endif | |
3558 } | |
3559 | |
3560 // To install functions for atexit system call | |
3561 extern "C" { | |
3562 static void perfMemory_exit_helper() { | |
3563 perfMemory_exit(); | |
3564 } | |
3565 } | |
3566 | |
3567 // this is called _after_ the global arguments have been parsed | |
3568 jint os::init_2(void) | |
3569 { | |
3570 // Allocate a single page and mark it as readable for safepoint polling | |
3571 address polling_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | |
3572 guarantee( polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page" ); | |
3573 | |
3574 os::set_polling_page( polling_page ); | |
3575 | |
3576 #ifndef PRODUCT | |
3577 if(Verbose && PrintMiscellaneous) | |
3578 tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", (intptr_t)polling_page); | |
3579 #endif | |
3580 | |
3581 if (!UseMembar) { | |
3582 address mem_serialize_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
10405
diff
changeset
|
3583 guarantee( mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page"); |
3960 | 3584 os::set_memory_serialize_page( mem_serialize_page ); |
3585 | |
3586 #ifndef PRODUCT | |
3587 if(Verbose && PrintMiscellaneous) | |
3588 tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); | |
3589 #endif | |
3590 } | |
3591 | |
3592 // initialize suspend/resume support - must do this before signal_sets_init() | |
3593 if (SR_initialize() != 0) { | |
3594 perror("SR_initialize failed"); | |
3595 return JNI_ERR; | |
3596 } | |
3597 | |
3598 Bsd::signal_sets_init(); | |
3599 Bsd::install_signal_handlers(); | |
3600 | |
3601 // Check minimum allowable stack size for thread creation and to initialize | |
3602 // the java system classes, including StackOverflowError - depends on page | |
3603 // size. Add a page for compiler2 recursion in main thread. | |
3604 // Add in 2*BytesPerWord times page size to account for VM stack during | |
3605 // class initialization depending on 32 or 64 bit VM. | |
3606 os::Bsd::min_stack_allowed = MAX2(os::Bsd::min_stack_allowed, | |
3607 (size_t)(StackYellowPages+StackRedPages+StackShadowPages+ | |
3608 2*BytesPerWord COMPILER2_PRESENT(+1)) * Bsd::page_size()); | |
3609 | |
3610 size_t threadStackSizeInBytes = ThreadStackSize * K; | |
3611 if (threadStackSizeInBytes != 0 && | |
3612 threadStackSizeInBytes < os::Bsd::min_stack_allowed) { | |
3613 tty->print_cr("\nThe stack size specified is too small, " | |
3614 "Specify at least %dk", | |
3615 os::Bsd::min_stack_allowed/ K); | |
3616 return JNI_ERR; | |
3617 } | |
3618 | |
3619 // Make the stack size a multiple of the page size so that | |
3620 // the yellow/red zones can be guarded. | |
3621 JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, | |
3622 vm_page_size())); | |
3623 | |
3624 if (MaxFDLimit) { | |
3625 // set the number of file descriptors to max. print out error | |
3626 // if getrlimit/setrlimit fails but continue regardless. | |
3627 struct rlimit nbr_files; | |
3628 int status = getrlimit(RLIMIT_NOFILE, &nbr_files); | |
3629 if (status != 0) { | |
3630 if (PrintMiscellaneous && (Verbose || WizardMode)) | |
3631 perror("os::init_2 getrlimit failed"); | |
3632 } else { | |
3633 nbr_files.rlim_cur = nbr_files.rlim_max; | |
3634 | |
3635 #ifdef __APPLE__ | |
3636 // Darwin returns RLIM_INFINITY for rlim_max, but fails with EINVAL if | |
3637 // you attempt to use RLIM_INFINITY. As per setrlimit(2), OPEN_MAX must | |
3638 // be used instead | |
3639 nbr_files.rlim_cur = MIN(OPEN_MAX, nbr_files.rlim_cur); | |
3640 #endif | |
3641 | |
3642 status = setrlimit(RLIMIT_NOFILE, &nbr_files); | |
3643 if (status != 0) { | |
3644 if (PrintMiscellaneous && (Verbose || WizardMode)) | |
3645 perror("os::init_2 setrlimit failed"); | |
3646 } | |
3647 } | |
3648 } | |
3649 | |
3650 // at-exit methods are called in the reverse order of their registration. | |
3651 // atexit functions are called on return from main or as a result of a | |
3652 // call to exit(3C). There can be only 32 of these functions registered | |
3653 // and atexit() does not set errno. | |
3654 | |
3655 if (PerfAllowAtExitRegistration) { | |
3656 // only register atexit functions if PerfAllowAtExitRegistration is set. | |
3657 // atexit functions can be delayed until process exit time, which | |
3658 // can be problematic for embedded VM situations. Embedded VMs should | |
3659 // call DestroyJavaVM() to assure that VM resources are released. | |
3660 | |
3661 // note: perfMemory_exit_helper atexit function may be removed in | |
3662 // the future if the appropriate cleanup code can be added to the | |
3663 // VM_Exit VMOperation's doit method. | |
3664 if (atexit(perfMemory_exit_helper) != 0) { | |
3665 warning("os::init2 atexit(perfMemory_exit_helper) failed"); | |
3666 } | |
3667 } | |
3668 | |
3669 // initialize thread priority policy | |
3670 prio_init(); | |
3671 | |
4006 | 3672 #ifdef __APPLE__ |
3673 // dynamically link to objective c gc registration | |
3674 void *handleLibObjc = dlopen(OBJC_LIB, RTLD_LAZY); | |
3675 if (handleLibObjc != NULL) { | |
3676 objc_registerThreadWithCollectorFunction = (objc_registerThreadWithCollector_t) dlsym(handleLibObjc, OBJC_GCREGISTER); | |
3677 } | |
3678 #endif | |
3679 | |
3960 | 3680 return JNI_OK; |
3681 } | |
3682 | |
3683 // this is called at the end of vm_initialization | |
3684 void os::init_3(void) { } | |
3685 | |
3686 // Mark the polling page as unreadable | |
3687 void os::make_polling_page_unreadable(void) { | |
3688 if( !guard_memory((char*)_polling_page, Bsd::page_size()) ) | |
3689 fatal("Could not disable polling page"); | |
3690 }; | |
3691 | |
3692 // Mark the polling page as readable | |
3693 void os::make_polling_page_readable(void) { | |
3694 if( !bsd_mprotect((char *)_polling_page, Bsd::page_size(), PROT_READ)) { | |
3695 fatal("Could not enable polling page"); | |
3696 } | |
3697 }; | |
3698 | |
3699 int os::active_processor_count() { | |
3700 return _processor_count; | |
3701 } | |
3702 | |
4006 | 3703 void os::set_native_thread_name(const char *name) { |
3704 #if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 | |
3705 // This is only supported in Snow Leopard and beyond | |
3706 if (name != NULL) { | |
3707 // Add a "Java: " prefix to the name | |
3708 char buf[MAXTHREADNAMESIZE]; | |
3709 snprintf(buf, sizeof(buf), "Java: %s", name); | |
3710 pthread_setname_np(buf); | |
3711 } | |
3712 #endif | |
3713 } | |
3714 | |
3960 | 3715 bool os::distribute_processes(uint length, uint* distribution) { |
3716 // Not yet implemented. | |
3717 return false; | |
3718 } | |
3719 | |
3720 bool os::bind_to_processor(uint processor_id) { | |
3721 // Not yet implemented. | |
3722 return false; | |
3723 } | |
3724 | |
10405 | 3725 void os::SuspendedThreadTask::internal_do_task() { |
3726 if (do_suspend(_thread->osthread())) { | |
3727 SuspendedThreadTaskContext context(_thread, _thread->osthread()->ucontext()); | |
3728 do_task(context); | |
3729 do_resume(_thread->osthread()); | |
3730 } | |
3731 } | |
3732 | |
3960 | 3733 /// |
10405 | 3734 class PcFetcher : public os::SuspendedThreadTask { |
3735 public: | |
3736 PcFetcher(Thread* thread) : os::SuspendedThreadTask(thread) {} | |
3737 ExtendedPC result(); | |
3738 protected: | |
3739 void do_task(const os::SuspendedThreadTaskContext& context); | |
3740 private: | |
3741 ExtendedPC _epc; | |
3742 }; | |
3743 | |
3744 ExtendedPC PcFetcher::result() { | |
3745 guarantee(is_done(), "task is not done yet."); | |
3746 return _epc; | |
3747 } | |
3748 | |
3749 void PcFetcher::do_task(const os::SuspendedThreadTaskContext& context) { | |
3750 Thread* thread = context.thread(); | |
3751 OSThread* osthread = thread->osthread(); | |
3752 if (osthread->ucontext() != NULL) { | |
3753 _epc = os::Bsd::ucontext_get_pc((ucontext_t *) context.ucontext()); | |
3754 } else { | |
3755 // NULL context is unexpected, double-check this is the VMThread | |
3756 guarantee(thread->is_VM_thread(), "can only be called for VMThread"); | |
3757 } | |
3758 } | |
3960 | 3759 |
3760 // Suspends the target using the signal mechanism and then grabs the PC before | |
3761 // resuming the target. Used by the flat-profiler only | |
3762 ExtendedPC os::get_thread_pc(Thread* thread) { | |
3763 // Make sure that it is called by the watcher for the VMThread | |
3764 assert(Thread::current()->is_Watcher_thread(), "Must be watcher"); | |
3765 assert(thread->is_VM_thread(), "Can only be called for VMThread"); | |
3766 | |
10405 | 3767 PcFetcher fetcher(thread); |
3768 fetcher.run(); | |
3769 return fetcher.result(); | |
3960 | 3770 } |
3771 | |
3772 int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) | |
3773 { | |
3774 return pthread_cond_timedwait(_cond, _mutex, _abstime); | |
3775 } | |
3776 | |
3777 //////////////////////////////////////////////////////////////////////////////// | |
3778 // debug support | |
3779 | |
3780 bool os::find(address addr, outputStream* st) { | |
3781 Dl_info dlinfo; | |
3782 memset(&dlinfo, 0, sizeof(dlinfo)); | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
3783 if (dladdr(addr, &dlinfo) != 0) { |
3960 | 3784 st->print(PTR_FORMAT ": ", addr); |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
3785 if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) { |
3960 | 3786 st->print("%s+%#x", dlinfo.dli_sname, |
3787 addr - (intptr_t)dlinfo.dli_saddr); | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
3788 } else if (dlinfo.dli_fbase != NULL) { |
3960 | 3789 st->print("<offset %#x>", addr - (intptr_t)dlinfo.dli_fbase); |
3790 } else { | |
3791 st->print("<absolute address>"); | |
3792 } | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
3793 if (dlinfo.dli_fname != NULL) { |
3960 | 3794 st->print(" in %s", dlinfo.dli_fname); |
3795 } | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
3796 if (dlinfo.dli_fbase != NULL) { |
3960 | 3797 st->print(" at " PTR_FORMAT, dlinfo.dli_fbase); |
3798 } | |
3799 st->cr(); | |
3800 | |
3801 if (Verbose) { | |
3802 // decode some bytes around the PC | |
9060
cc32ccaaf47f
8003310: Enable -Wunused-function when compiling with gcc
mikael
parents:
9059
diff
changeset
|
3803 address begin = clamp_address_in_page(addr-40, addr, os::vm_page_size()); |
cc32ccaaf47f
8003310: Enable -Wunused-function when compiling with gcc
mikael
parents:
9059
diff
changeset
|
3804 address end = clamp_address_in_page(addr+40, addr, os::vm_page_size()); |
3960 | 3805 address lowest = (address) dlinfo.dli_sname; |
3806 if (!lowest) lowest = (address) dlinfo.dli_fbase; | |
3807 if (begin < lowest) begin = lowest; | |
3808 Dl_info dlinfo2; | |
11092
59b052799158
8015884: runThese crashed with SIGSEGV, hs_err has an error instead of stacktrace
dcubed
parents:
10986
diff
changeset
|
3809 if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr |
3960 | 3810 && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) |
3811 end = (address) dlinfo2.dli_saddr; | |
3812 Disassembler::decode(begin, end, st); | |
3813 } | |
3814 return true; | |
3815 } | |
3816 return false; | |
3817 } | |
3818 | |
3819 //////////////////////////////////////////////////////////////////////////////// | |
3820 // misc | |
3821 | |
3822 // This does not do anything on Bsd. This is basically a hook for being | |
3823 // able to use structured exception handling (thread-local exception filters) | |
3824 // on, e.g., Win32. | |
3825 void | |
3826 os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, | |
3827 JavaCallArguments* args, Thread* thread) { | |
3828 f(value, method, args, thread); | |
3829 } | |
3830 | |
3831 void os::print_statistics() { | |
3832 } | |
3833 | |
3834 int os::message_box(const char* title, const char* message) { | |
3835 int i; | |
3836 fdStream err(defaultStream::error_fd()); | |
3837 for (i = 0; i < 78; i++) err.print_raw("="); | |
3838 err.cr(); | |
3839 err.print_raw_cr(title); | |
3840 for (i = 0; i < 78; i++) err.print_raw("-"); | |
3841 err.cr(); | |
3842 err.print_raw_cr(message); | |
3843 for (i = 0; i < 78; i++) err.print_raw("="); | |
3844 err.cr(); | |
3845 | |
3846 char buf[16]; | |
3847 // Prevent process from exiting upon "read error" without consuming all CPU | |
3848 while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } | |
3849 | |
3850 return buf[0] == 'y' || buf[0] == 'Y'; | |
3851 } | |
3852 | |
3853 int os::stat(const char *path, struct stat *sbuf) { | |
3854 char pathbuf[MAX_PATH]; | |
3855 if (strlen(path) > MAX_PATH - 1) { | |
3856 errno = ENAMETOOLONG; | |
3857 return -1; | |
3858 } | |
3859 os::native_path(strcpy(pathbuf, path)); | |
3860 return ::stat(pathbuf, sbuf); | |
3861 } | |
3862 | |
3863 bool os::check_heap(bool force) { | |
3864 return true; | |
3865 } | |
3866 | |
3867 int local_vsnprintf(char* buf, size_t count, const char* format, va_list args) { | |
3868 return ::vsnprintf(buf, count, format, args); | |
3869 } | |
3870 | |
3871 // Is a (classpath) directory empty? | |
3872 bool os::dir_is_empty(const char* path) { | |
3873 DIR *dir = NULL; | |
3874 struct dirent *ptr; | |
3875 | |
3876 dir = opendir(path); | |
3877 if (dir == NULL) return true; | |
3878 | |
3879 /* Scan the directory */ | |
3880 bool result = true; | |
3881 char buf[sizeof(struct dirent) + MAX_PATH]; | |
3882 while (result && (ptr = ::readdir(dir)) != NULL) { | |
3883 if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { | |
3884 result = false; | |
3885 } | |
3886 } | |
3887 closedir(dir); | |
3888 return result; | |
3889 } | |
3890 | |
3891 // This code originates from JDK's sysOpen and open64_w | |
3892 // from src/solaris/hpi/src/system_md.c | |
3893 | |
3894 #ifndef O_DELETE | |
3895 #define O_DELETE 0x10000 | |
3896 #endif | |
3897 | |
3898 // Open a file. Unlink the file immediately after open returns | |
3899 // if the specified oflag has the O_DELETE flag set. | |
3900 // O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c | |
3901 | |
3902 int os::open(const char *path, int oflag, int mode) { | |
3903 | |
3904 if (strlen(path) > MAX_PATH - 1) { | |
3905 errno = ENAMETOOLONG; | |
3906 return -1; | |
3907 } | |
3908 int fd; | |
3909 int o_delete = (oflag & O_DELETE); | |
3910 oflag = oflag & ~O_DELETE; | |
3911 | |
3912 fd = ::open(path, oflag, mode); | |
3913 if (fd == -1) return -1; | |
3914 | |
3915 //If the open succeeded, the file might still be a directory | |
3916 { | |
3917 struct stat buf; | |
3918 int ret = ::fstat(fd, &buf); | |
3919 int st_mode = buf.st_mode; | |
3920 | |
3921 if (ret != -1) { | |
3922 if ((st_mode & S_IFMT) == S_IFDIR) { | |
3923 errno = EISDIR; | |
3924 ::close(fd); | |
3925 return -1; | |
3926 } | |
3927 } else { | |
3928 ::close(fd); | |
3929 return -1; | |
3930 } | |
3931 } | |
3932 | |
3933 /* | |
3934 * All file descriptors that are opened in the JVM and not | |
3935 * specifically destined for a subprocess should have the | |
3936 * close-on-exec flag set. If we don't set it, then careless 3rd | |
3937 * party native code might fork and exec without closing all | |
3938 * appropriate file descriptors (e.g. as we do in closeDescriptors in | |
3939 * UNIXProcess.c), and this in turn might: | |
3940 * | |
3941 * - cause end-of-file to fail to be detected on some file | |
3942 * descriptors, resulting in mysterious hangs, or | |
3943 * | |
3944 * - might cause an fopen in the subprocess to fail on a system | |
3945 * suffering from bug 1085341. | |
3946 * | |
3947 * (Yes, the default setting of the close-on-exec flag is a Unix | |
3948 * design flaw) | |
3949 * | |
3950 * See: | |
3951 * 1085341: 32-bit stdio routines should support file descriptors >255 | |
3952 * 4843136: (process) pipe file descriptor from Runtime.exec not being closed | |
3953 * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 | |
3954 */ | |
3955 #ifdef FD_CLOEXEC | |
3956 { | |
3957 int flags = ::fcntl(fd, F_GETFD); | |
3958 if (flags != -1) | |
3959 ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); | |
3960 } | |
3961 #endif | |
3962 | |
3963 if (o_delete != 0) { | |
3964 ::unlink(path); | |
3965 } | |
3966 return fd; | |
3967 } | |
3968 | |
3969 | |
3970 // create binary file, rewriting existing file if required | |
3971 int os::create_binary_file(const char* path, bool rewrite_existing) { | |
3972 int oflags = O_WRONLY | O_CREAT; | |
3973 if (!rewrite_existing) { | |
3974 oflags |= O_EXCL; | |
3975 } | |
3976 return ::open(path, oflags, S_IREAD | S_IWRITE); | |
3977 } | |
3978 | |
3979 // return current position of file pointer | |
3980 jlong os::current_file_offset(int fd) { | |
3981 return (jlong)::lseek(fd, (off_t)0, SEEK_CUR); | |
3982 } | |
3983 | |
3984 // move file pointer to the specified offset | |
3985 jlong os::seek_to_file_offset(int fd, jlong offset) { | |
3986 return (jlong)::lseek(fd, (off_t)offset, SEEK_SET); | |
3987 } | |
3988 | |
3989 // This code originates from JDK's sysAvailable | |
3990 // from src/solaris/hpi/src/native_threads/src/sys_api_td.c | |
3991 | |
3992 int os::available(int fd, jlong *bytes) { | |
3993 jlong cur, end; | |
3994 int mode; | |
3995 struct stat buf; | |
3996 | |
3997 if (::fstat(fd, &buf) >= 0) { | |
3998 mode = buf.st_mode; | |
3999 if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { | |
4000 /* | |
4001 * XXX: is the following call interruptible? If so, this might | |
4002 * need to go through the INTERRUPT_IO() wrapper as for other | |
4003 * blocking, interruptible calls in this file. | |
4004 */ | |
4005 int n; | |
4006 if (::ioctl(fd, FIONREAD, &n) >= 0) { | |
4007 *bytes = n; | |
4008 return 1; | |
4009 } | |
4010 } | |
4011 } | |
4012 if ((cur = ::lseek(fd, 0L, SEEK_CUR)) == -1) { | |
4013 return 0; | |
4014 } else if ((end = ::lseek(fd, 0L, SEEK_END)) == -1) { | |
4015 return 0; | |
4016 } else if (::lseek(fd, cur, SEEK_SET) == -1) { | |
4017 return 0; | |
4018 } | |
4019 *bytes = end - cur; | |
4020 return 1; | |
4021 } | |
4022 | |
4023 int os::socket_available(int fd, jint *pbytes) { | |
4024 if (fd < 0) | |
4025 return OS_OK; | |
4026 | |
4027 int ret; | |
4028 | |
4029 RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret); | |
4030 | |
4031 //%% note ioctl can return 0 when successful, JVM_SocketAvailable | |
4032 // is expected to return 0 on failure and 1 on success to the jdk. | |
4033 | |
4034 return (ret == OS_ERR) ? 0 : 1; | |
4035 } | |
4036 | |
4037 // Map a block of memory. | |
6197 | 4038 char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, |
3960 | 4039 char *addr, size_t bytes, bool read_only, |
4040 bool allow_exec) { | |
4041 int prot; | |
4042 int flags; | |
4043 | |
4044 if (read_only) { | |
4045 prot = PROT_READ; | |
4046 flags = MAP_SHARED; | |
4047 } else { | |
4048 prot = PROT_READ | PROT_WRITE; | |
4049 flags = MAP_PRIVATE; | |
4050 } | |
4051 | |
4052 if (allow_exec) { | |
4053 prot |= PROT_EXEC; | |
4054 } | |
4055 | |
4056 if (addr != NULL) { | |
4057 flags |= MAP_FIXED; | |
4058 } | |
4059 | |
4060 char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags, | |
4061 fd, file_offset); | |
4062 if (mapped_address == MAP_FAILED) { | |
4063 return NULL; | |
4064 } | |
4065 return mapped_address; | |
4066 } | |
4067 | |
4068 | |
4069 // Remap a block of memory. | |
6197 | 4070 char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset, |
3960 | 4071 char *addr, size_t bytes, bool read_only, |
4072 bool allow_exec) { | |
4073 // same as map_memory() on this OS | |
4074 return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only, | |
4075 allow_exec); | |
4076 } | |
4077 | |
4078 | |
4079 // Unmap a block of memory. | |
6197 | 4080 bool os::pd_unmap_memory(char* addr, size_t bytes) { |
3960 | 4081 return munmap(addr, bytes) == 0; |
4082 } | |
4083 | |
4084 // current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool) | |
4085 // are used by JVM M&M and JVMTI to get user+sys or user CPU time | |
4086 // of a thread. | |
4087 // | |
4088 // current_thread_cpu_time() and thread_cpu_time(Thread*) returns | |
4089 // the fast estimate available on the platform. | |
4090 | |
4091 jlong os::current_thread_cpu_time() { | |
4092 #ifdef __APPLE__ | |
4093 return os::thread_cpu_time(Thread::current(), true /* user + sys */); | |
8689
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4094 #else |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4095 Unimplemented(); |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4096 return 0; |
3960 | 4097 #endif |
4098 } | |
4099 | |
4100 jlong os::thread_cpu_time(Thread* thread) { | |
8689
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4101 #ifdef __APPLE__ |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4102 return os::thread_cpu_time(thread, true /* user + sys */); |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4103 #else |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4104 Unimplemented(); |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4105 return 0; |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4106 #endif |
3960 | 4107 } |
4108 | |
4109 jlong os::current_thread_cpu_time(bool user_sys_cpu_time) { | |
4110 #ifdef __APPLE__ | |
4111 return os::thread_cpu_time(Thread::current(), user_sys_cpu_time); | |
8689
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4112 #else |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4113 Unimplemented(); |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4114 return 0; |
3960 | 4115 #endif |
4116 } | |
4117 | |
4118 jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { | |
4119 #ifdef __APPLE__ | |
4120 struct thread_basic_info tinfo; | |
4121 mach_msg_type_number_t tcount = THREAD_INFO_MAX; | |
4122 kern_return_t kr; | |
4961
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
4123 thread_t mach_thread; |
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
4124 |
0368109684cb
7132070: Use a mach_port_t as the OSThread thread_id rather than pthread_t on BSD/OSX
sla
parents:
4960
diff
changeset
|
4125 mach_thread = thread->osthread()->thread_id(); |
3960 | 4126 kr = thread_info(mach_thread, THREAD_BASIC_INFO, (thread_info_t)&tinfo, &tcount); |
4127 if (kr != KERN_SUCCESS) | |
4128 return -1; | |
4129 | |
4130 if (user_sys_cpu_time) { | |
4131 jlong nanos; | |
4132 nanos = ((jlong) tinfo.system_time.seconds + tinfo.user_time.seconds) * (jlong)1000000000; | |
4133 nanos += ((jlong) tinfo.system_time.microseconds + (jlong) tinfo.user_time.microseconds) * (jlong)1000; | |
4134 return nanos; | |
4135 } else { | |
4136 return ((jlong)tinfo.user_time.seconds * 1000000000) + ((jlong)tinfo.user_time.microseconds * (jlong)1000); | |
4137 } | |
8689
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4138 #else |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4139 Unimplemented(); |
bf06968a8a00
8008559: [parfait] Path through non-void function '_ZN2os15thread_cpu_timeEP6Thread' returns an undefined value
morris
parents:
8067
diff
changeset
|
4140 return 0; |
3960 | 4141 #endif |
4142 } | |
4143 | |
4144 | |
4145 void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { | |
4146 info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits | |
4147 info_ptr->may_skip_backward = false; // elapsed time not wall time | |
4148 info_ptr->may_skip_forward = false; // elapsed time not wall time | |
4149 info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned | |
4150 } | |
4151 | |
4152 void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { | |
4153 info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits | |
4154 info_ptr->may_skip_backward = false; // elapsed time not wall time | |
4155 info_ptr->may_skip_forward = false; // elapsed time not wall time | |
4156 info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned | |
4157 } | |
4158 | |
4159 bool os::is_thread_cpu_time_supported() { | |
4160 #ifdef __APPLE__ | |
4161 return true; | |
6918 | 4162 #else |
3960 | 4163 return false; |
4164 #endif | |
4165 } | |
4166 | |
4167 // System loadavg support. Returns -1 if load average cannot be obtained. | |
4168 // Bsd doesn't yet have a (official) notion of processor sets, | |
4169 // so just return the system wide load average. | |
4170 int os::loadavg(double loadavg[], int nelem) { | |
4171 return ::getloadavg(loadavg, nelem); | |
4172 } | |
4173 | |
4174 void os::pause() { | |
4175 char filename[MAX_PATH]; | |
4176 if (PauseAtStartupFile && PauseAtStartupFile[0]) { | |
4177 jio_snprintf(filename, MAX_PATH, PauseAtStartupFile); | |
4178 } else { | |
4179 jio_snprintf(filename, MAX_PATH, "./vm.paused.%d", current_process_id()); | |
4180 } | |
4181 | |
4182 int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); | |
4183 if (fd != -1) { | |
4184 struct stat buf; | |
4185 ::close(fd); | |
4186 while (::stat(filename, &buf) == 0) { | |
4187 (void)::poll(NULL, 0, 100); | |
4188 } | |
4189 } else { | |
4190 jio_fprintf(stderr, | |
4191 "Could not open pause file '%s', continuing immediately.\n", filename); | |
4192 } | |
4193 } | |
4194 | |
4195 | |
4196 // Refer to the comments in os_solaris.cpp park-unpark. | |
4197 // | |
4198 // Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can | |
4199 // hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable. | |
4200 // For specifics regarding the bug see GLIBC BUGID 261237 : | |
4201 // http://www.mail-archive.com/debian-glibc@lists.debian.org/msg10837.html. | |
4202 // Briefly, pthread_cond_timedwait() calls with an expiry time that's not in the future | |
4203 // will either hang or corrupt the condvar, resulting in subsequent hangs if the condvar | |
4204 // is used. (The simple C test-case provided in the GLIBC bug report manifests the | |
4205 // hang). The JVM is vulernable via sleep(), Object.wait(timo), LockSupport.parkNanos() | |
4206 // and monitorenter when we're using 1-0 locking. All those operations may result in | |
4207 // calls to pthread_cond_timedwait(). Using LD_ASSUME_KERNEL to use an older version | |
4208 // of libpthread avoids the problem, but isn't practical. | |
4209 // | |
4210 // Possible remedies: | |
4211 // | |
4212 // 1. Establish a minimum relative wait time. 50 to 100 msecs seems to work. | |
4213 // This is palliative and probabilistic, however. If the thread is preempted | |
4214 // between the call to compute_abstime() and pthread_cond_timedwait(), more | |
4215 // than the minimum period may have passed, and the abstime may be stale (in the | |
4216 // past) resultin in a hang. Using this technique reduces the odds of a hang | |
4217 // but the JVM is still vulnerable, particularly on heavily loaded systems. | |
4218 // | |
4219 // 2. Modify park-unpark to use per-thread (per ParkEvent) pipe-pairs instead | |
4220 // of the usual flag-condvar-mutex idiom. The write side of the pipe is set | |
4221 // NDELAY. unpark() reduces to write(), park() reduces to read() and park(timo) | |
4222 // reduces to poll()+read(). This works well, but consumes 2 FDs per extant | |
4223 // thread. | |
4224 // | |
4225 // 3. Embargo pthread_cond_timedwait() and implement a native "chron" thread | |
4226 // that manages timeouts. We'd emulate pthread_cond_timedwait() by enqueuing | |
4227 // a timeout request to the chron thread and then blocking via pthread_cond_wait(). | |
4228 // This also works well. In fact it avoids kernel-level scalability impediments | |
4229 // on certain platforms that don't handle lots of active pthread_cond_timedwait() | |
4230 // timers in a graceful fashion. | |
4231 // | |
4232 // 4. When the abstime value is in the past it appears that control returns | |
4233 // correctly from pthread_cond_timedwait(), but the condvar is left corrupt. | |
4234 // Subsequent timedwait/wait calls may hang indefinitely. Given that, we | |
4235 // can avoid the problem by reinitializing the condvar -- by cond_destroy() | |
4236 // followed by cond_init() -- after all calls to pthread_cond_timedwait(). | |
4237 // It may be possible to avoid reinitialization by checking the return | |
4238 // value from pthread_cond_timedwait(). In addition to reinitializing the | |
4239 // condvar we must establish the invariant that cond_signal() is only called | |
4240 // within critical sections protected by the adjunct mutex. This prevents | |
4241 // cond_signal() from "seeing" a condvar that's in the midst of being | |
4242 // reinitialized or that is corrupt. Sadly, this invariant obviates the | |
4243 // desirable signal-after-unlock optimization that avoids futile context switching. | |
4244 // | |
4245 // I'm also concerned that some versions of NTPL might allocate an auxilliary | |
4246 // structure when a condvar is used or initialized. cond_destroy() would | |
4247 // release the helper structure. Our reinitialize-after-timedwait fix | |
4248 // put excessive stress on malloc/free and locks protecting the c-heap. | |
4249 // | |
4250 // We currently use (4). See the WorkAroundNTPLTimedWaitHang flag. | |
4251 // It may be possible to refine (4) by checking the kernel and NTPL verisons | |
4252 // and only enabling the work-around for vulnerable environments. | |
4253 | |
4254 // utility to compute the abstime argument to timedwait: | |
4255 // millis is the relative timeout time | |
4256 // abstime will be the absolute timeout time | |
4257 // TODO: replace compute_abstime() with unpackTime() | |
4258 | |
4259 static struct timespec* compute_abstime(struct timespec* abstime, jlong millis) { | |
4260 if (millis < 0) millis = 0; | |
4261 struct timeval now; | |
4262 int status = gettimeofday(&now, NULL); | |
4263 assert(status == 0, "gettimeofday"); | |
4264 jlong seconds = millis / 1000; | |
4265 millis %= 1000; | |
4266 if (seconds > 50000000) { // see man cond_timedwait(3T) | |
4267 seconds = 50000000; | |
4268 } | |
4269 abstime->tv_sec = now.tv_sec + seconds; | |
4270 long usec = now.tv_usec + millis * 1000; | |
4271 if (usec >= 1000000) { | |
4272 abstime->tv_sec += 1; | |
4273 usec -= 1000000; | |
4274 } | |
4275 abstime->tv_nsec = usec * 1000; | |
4276 return abstime; | |
4277 } | |
4278 | |
4279 | |
4280 // Test-and-clear _Event, always leaves _Event set to 0, returns immediately. | |
4281 // Conceptually TryPark() should be equivalent to park(0). | |
4282 | |
4283 int os::PlatformEvent::TryPark() { | |
4284 for (;;) { | |
4285 const int v = _Event ; | |
4286 guarantee ((v == 0) || (v == 1), "invariant") ; | |
4287 if (Atomic::cmpxchg (0, &_Event, v) == v) return v ; | |
4288 } | |
4289 } | |
4290 | |
4291 void os::PlatformEvent::park() { // AKA "down()" | |
4292 // Invariant: Only the thread associated with the Event/PlatformEvent | |
4293 // may call park(). | |
4294 // TODO: assert that _Assoc != NULL or _Assoc == Self | |
4295 int v ; | |
4296 for (;;) { | |
4297 v = _Event ; | |
4298 if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; | |
4299 } | |
4300 guarantee (v >= 0, "invariant") ; | |
4301 if (v == 0) { | |
4302 // Do this the hard way by blocking ... | |
4303 int status = pthread_mutex_lock(_mutex); | |
4304 assert_status(status == 0, status, "mutex_lock"); | |
4305 guarantee (_nParked == 0, "invariant") ; | |
4306 ++ _nParked ; | |
4307 while (_Event < 0) { | |
4308 status = pthread_cond_wait(_cond, _mutex); | |
4309 // for some reason, under 2.7 lwp_cond_wait() may return ETIME ... | |
4310 // Treat this the same as if the wait was interrupted | |
4311 if (status == ETIMEDOUT) { status = EINTR; } | |
4312 assert_status(status == 0 || status == EINTR, status, "cond_wait"); | |
4313 } | |
4314 -- _nParked ; | |
4315 | |
4316 _Event = 0 ; | |
4317 status = pthread_mutex_unlock(_mutex); | |
4318 assert_status(status == 0, status, "mutex_unlock"); | |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4319 // Paranoia to ensure our locked and lock-free paths interact |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4320 // correctly with each other. |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4321 OrderAccess::fence(); |
3960 | 4322 } |
4323 guarantee (_Event >= 0, "invariant") ; | |
4324 } | |
4325 | |
4326 int os::PlatformEvent::park(jlong millis) { | |
4327 guarantee (_nParked == 0, "invariant") ; | |
4328 | |
4329 int v ; | |
4330 for (;;) { | |
4331 v = _Event ; | |
4332 if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; | |
4333 } | |
4334 guarantee (v >= 0, "invariant") ; | |
4335 if (v != 0) return OS_OK ; | |
4336 | |
4337 // We do this the hard way, by blocking the thread. | |
4338 // Consider enforcing a minimum timeout value. | |
4339 struct timespec abst; | |
4340 compute_abstime(&abst, millis); | |
4341 | |
4342 int ret = OS_TIMEOUT; | |
4343 int status = pthread_mutex_lock(_mutex); | |
4344 assert_status(status == 0, status, "mutex_lock"); | |
4345 guarantee (_nParked == 0, "invariant") ; | |
4346 ++_nParked ; | |
4347 | |
4348 // Object.wait(timo) will return because of | |
4349 // (a) notification | |
4350 // (b) timeout | |
4351 // (c) thread.interrupt | |
4352 // | |
4353 // Thread.interrupt and object.notify{All} both call Event::set. | |
4354 // That is, we treat thread.interrupt as a special case of notification. | |
4355 // The underlying Solaris implementation, cond_timedwait, admits | |
4356 // spurious/premature wakeups, but the JLS/JVM spec prevents the | |
4357 // JVM from making those visible to Java code. As such, we must | |
4358 // filter out spurious wakeups. We assume all ETIME returns are valid. | |
4359 // | |
4360 // TODO: properly differentiate simultaneous notify+interrupt. | |
4361 // In that case, we should propagate the notify to another waiter. | |
4362 | |
4363 while (_Event < 0) { | |
4364 status = os::Bsd::safe_cond_timedwait(_cond, _mutex, &abst); | |
4365 if (status != 0 && WorkAroundNPTLTimedWaitHang) { | |
4366 pthread_cond_destroy (_cond); | |
4367 pthread_cond_init (_cond, NULL) ; | |
4368 } | |
4369 assert_status(status == 0 || status == EINTR || | |
4370 status == ETIMEDOUT, | |
4371 status, "cond_timedwait"); | |
4372 if (!FilterSpuriousWakeups) break ; // previous semantics | |
4373 if (status == ETIMEDOUT) break ; | |
4374 // We consume and ignore EINTR and spurious wakeups. | |
4375 } | |
4376 --_nParked ; | |
4377 if (_Event >= 0) { | |
4378 ret = OS_OK; | |
4379 } | |
4380 _Event = 0 ; | |
4381 status = pthread_mutex_unlock(_mutex); | |
4382 assert_status(status == 0, status, "mutex_unlock"); | |
4383 assert (_nParked == 0, "invariant") ; | |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4384 // Paranoia to ensure our locked and lock-free paths interact |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4385 // correctly with each other. |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4386 OrderAccess::fence(); |
3960 | 4387 return ret; |
4388 } | |
4389 | |
4390 void os::PlatformEvent::unpark() { | |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4391 // Transitions for _Event: |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4392 // 0 :=> 1 |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4393 // 1 :=> 1 |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4394 // -1 :=> either 0 or 1; must signal target thread |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4395 // That is, we can safely transition _Event from -1 to either |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4396 // 0 or 1. Forcing 1 is slightly more efficient for back-to-back |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4397 // unpark() calls. |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4398 // See also: "Semaphores in Plan 9" by Mullender & Cox |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4399 // |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4400 // Note: Forcing a transition from "-1" to "1" on an unpark() means |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4401 // that it will take two back-to-back park() calls for the owning |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4402 // thread to block. This has the benefit of forcing a spurious return |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4403 // from the first park() call after an unpark() call which will help |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4404 // shake out uses of park() and unpark() without condition variables. |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4405 |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4406 if (Atomic::xchg(1, &_Event) >= 0) return; |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4407 |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4408 // Wait for the thread associated with the event to vacate |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4409 int status = pthread_mutex_lock(_mutex); |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4410 assert_status(status == 0, status, "mutex_lock"); |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4411 int AnyWaiters = _nParked; |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4412 assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4413 if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4414 AnyWaiters = 0; |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4415 pthread_cond_signal(_cond); |
3960 | 4416 } |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4417 status = pthread_mutex_unlock(_mutex); |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4418 assert_status(status == 0, status, "mutex_unlock"); |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4419 if (AnyWaiters != 0) { |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4420 status = pthread_cond_signal(_cond); |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4421 assert_status(status == 0, status, "cond_signal"); |
3960 | 4422 } |
4423 | |
4424 // Note that we signal() _after dropping the lock for "immortal" Events. | |
4425 // This is safe and avoids a common class of futile wakeups. In rare | |
4426 // circumstances this can cause a thread to return prematurely from | |
4427 // cond_{timed}wait() but the spurious wakeup is benign and the victim will | |
4428 // simply re-test the condition and re-park itself. | |
4429 } | |
4430 | |
4431 | |
4432 // JSR166 | |
4433 // ------------------------------------------------------- | |
4434 | |
4435 /* | |
4436 * The solaris and bsd implementations of park/unpark are fairly | |
4437 * conservative for now, but can be improved. They currently use a | |
4438 * mutex/condvar pair, plus a a count. | |
4439 * Park decrements count if > 0, else does a condvar wait. Unpark | |
4440 * sets count to 1 and signals condvar. Only one thread ever waits | |
4441 * on the condvar. Contention seen when trying to park implies that someone | |
4442 * is unparking you, so don't wait. And spurious returns are fine, so there | |
4443 * is no need to track notifications. | |
4444 */ | |
4445 | |
4446 #define MAX_SECS 100000000 | |
4447 /* | |
4448 * This code is common to bsd and solaris and will be moved to a | |
4449 * common place in dolphin. | |
4450 * | |
4451 * The passed in time value is either a relative time in nanoseconds | |
4452 * or an absolute time in milliseconds. Either way it has to be unpacked | |
4453 * into suitable seconds and nanoseconds components and stored in the | |
4454 * given timespec structure. | |
4455 * Given time is a 64-bit value and the time_t used in the timespec is only | |
4456 * a signed-32-bit value (except on 64-bit Bsd) we have to watch for | |
4457 * overflow if times way in the future are given. Further on Solaris versions | |
4458 * prior to 10 there is a restriction (see cond_timedwait) that the specified | |
4459 * number of seconds, in abstime, is less than current_time + 100,000,000. | |
4460 * As it will be 28 years before "now + 100000000" will overflow we can | |
4461 * ignore overflow and just impose a hard-limit on seconds using the value | |
4462 * of "now + 100,000,000". This places a limit on the timeout of about 3.17 | |
4463 * years from "now". | |
4464 */ | |
4465 | |
4466 static void unpackTime(struct timespec* absTime, bool isAbsolute, jlong time) { | |
4467 assert (time > 0, "convertTime"); | |
4468 | |
4469 struct timeval now; | |
4470 int status = gettimeofday(&now, NULL); | |
4471 assert(status == 0, "gettimeofday"); | |
4472 | |
4473 time_t max_secs = now.tv_sec + MAX_SECS; | |
4474 | |
4475 if (isAbsolute) { | |
4476 jlong secs = time / 1000; | |
4477 if (secs > max_secs) { | |
4478 absTime->tv_sec = max_secs; | |
4479 } | |
4480 else { | |
4481 absTime->tv_sec = secs; | |
4482 } | |
4483 absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; | |
4484 } | |
4485 else { | |
4486 jlong secs = time / NANOSECS_PER_SEC; | |
4487 if (secs >= MAX_SECS) { | |
4488 absTime->tv_sec = max_secs; | |
4489 absTime->tv_nsec = 0; | |
4490 } | |
4491 else { | |
4492 absTime->tv_sec = now.tv_sec + secs; | |
4493 absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000; | |
4494 if (absTime->tv_nsec >= NANOSECS_PER_SEC) { | |
4495 absTime->tv_nsec -= NANOSECS_PER_SEC; | |
4496 ++absTime->tv_sec; // note: this must be <= max_secs | |
4497 } | |
4498 } | |
4499 } | |
4500 assert(absTime->tv_sec >= 0, "tv_sec < 0"); | |
4501 assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs"); | |
4502 assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); | |
4503 assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); | |
4504 } | |
4505 | |
4506 void Parker::park(bool isAbsolute, jlong time) { | |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4507 // Ideally we'd do something useful while spinning, such |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4508 // as calling unpackTime(). |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4509 |
3960 | 4510 // Optional fast-path check: |
4511 // Return immediately if a permit is available. | |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4512 // We depend on Atomic::xchg() having full barrier semantics |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4513 // since we are doing a lock-free update to _counter. |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4514 if (Atomic::xchg(0, &_counter) > 0) return; |
3960 | 4515 |
4516 Thread* thread = Thread::current(); | |
4517 assert(thread->is_Java_thread(), "Must be JavaThread"); | |
4518 JavaThread *jt = (JavaThread *)thread; | |
4519 | |
4520 // Optional optimization -- avoid state transitions if there's an interrupt pending. | |
4521 // Check interrupt before trying to wait | |
4522 if (Thread::is_interrupted(thread, false)) { | |
4523 return; | |
4524 } | |
4525 | |
4526 // Next, demultiplex/decode time arguments | |
4527 struct timespec absTime; | |
4528 if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all | |
4529 return; | |
4530 } | |
4531 if (time > 0) { | |
4532 unpackTime(&absTime, isAbsolute, time); | |
4533 } | |
4534 | |
4535 | |
4536 // Enter safepoint region | |
4537 // Beware of deadlocks such as 6317397. | |
4538 // The per-thread Parker:: mutex is a classic leaf-lock. | |
4539 // In particular a thread must never block on the Threads_lock while | |
4540 // holding the Parker:: mutex. If safepoints are pending both the | |
4541 // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock. | |
4542 ThreadBlockInVM tbivm(jt); | |
4543 | |
4544 // Don't wait if cannot get lock since interference arises from | |
4545 // unblocking. Also. check interrupt before trying wait | |
4546 if (Thread::is_interrupted(thread, false) || pthread_mutex_trylock(_mutex) != 0) { | |
4547 return; | |
4548 } | |
4549 | |
4550 int status ; | |
4551 if (_counter > 0) { // no wait needed | |
4552 _counter = 0; | |
4553 status = pthread_mutex_unlock(_mutex); | |
4554 assert (status == 0, "invariant") ; | |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4555 // Paranoia to ensure our locked and lock-free paths interact |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4556 // correctly with each other and Java-level accesses. |
3960 | 4557 OrderAccess::fence(); |
4558 return; | |
4559 } | |
4560 | |
4561 #ifdef ASSERT | |
4562 // Don't catch signals while blocked; let the running threads have the signals. | |
4563 // (This allows a debugger to break into the running thread.) | |
4564 sigset_t oldsigs; | |
4565 sigset_t* allowdebug_blocked = os::Bsd::allowdebug_blocked_signals(); | |
4566 pthread_sigmask(SIG_BLOCK, allowdebug_blocked, &oldsigs); | |
4567 #endif | |
4568 | |
4569 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); | |
4570 jt->set_suspend_equivalent(); | |
4571 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() | |
4572 | |
4573 if (time == 0) { | |
4574 status = pthread_cond_wait (_cond, _mutex) ; | |
4575 } else { | |
4576 status = os::Bsd::safe_cond_timedwait (_cond, _mutex, &absTime) ; | |
4577 if (status != 0 && WorkAroundNPTLTimedWaitHang) { | |
4578 pthread_cond_destroy (_cond) ; | |
4579 pthread_cond_init (_cond, NULL); | |
4580 } | |
4581 } | |
4582 assert_status(status == 0 || status == EINTR || | |
4583 status == ETIMEDOUT, | |
4584 status, "cond_timedwait"); | |
4585 | |
4586 #ifdef ASSERT | |
4587 pthread_sigmask(SIG_SETMASK, &oldsigs, NULL); | |
4588 #endif | |
4589 | |
4590 _counter = 0 ; | |
4591 status = pthread_mutex_unlock(_mutex) ; | |
4592 assert_status(status == 0, status, "invariant") ; | |
7629
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4593 // Paranoia to ensure our locked and lock-free paths interact |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4594 // correctly with each other and Java-level accesses. |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4595 OrderAccess::fence(); |
22ba8c8ce6a6
8004902: correctness fixes motivated by contended locking work (6607129)
dcubed
parents:
7626
diff
changeset
|
4596 |
3960 | 4597 // If externally suspended while waiting, re-suspend |
4598 if (jt->handle_special_suspend_equivalent_condition()) { | |
4599 jt->java_suspend_self(); | |
4600 } | |
4601 } | |
4602 | |
4603 void Parker::unpark() { | |
4604 int s, status ; | |
4605 status = pthread_mutex_lock(_mutex); | |
4606 assert (status == 0, "invariant") ; | |
4607 s = _counter; | |
4608 _counter = 1; | |
4609 if (s < 1) { | |
4610 if (WorkAroundNPTLTimedWaitHang) { | |
4611 status = pthread_cond_signal (_cond) ; | |
4612 assert (status == 0, "invariant") ; | |
4613 status = pthread_mutex_unlock(_mutex); | |
4614 assert (status == 0, "invariant") ; | |
4615 } else { | |
4616 status = pthread_mutex_unlock(_mutex); | |
4617 assert (status == 0, "invariant") ; | |
4618 status = pthread_cond_signal (_cond) ; | |
4619 assert (status == 0, "invariant") ; | |
4620 } | |
4621 } else { | |
4622 pthread_mutex_unlock(_mutex); | |
4623 assert (status == 0, "invariant") ; | |
4624 } | |
4625 } | |
4626 | |
4627 | |
4628 /* Darwin has no "environ" in a dynamic library. */ | |
4629 #ifdef __APPLE__ | |
4630 #include <crt_externs.h> | |
4631 #define environ (*_NSGetEnviron()) | |
4632 #else | |
4633 extern char** environ; | |
4634 #endif | |
4635 | |
4636 // Run the specified command in a separate process. Return its exit value, | |
4637 // or -1 on failure (e.g. can't fork a new process). | |
4638 // Unlike system(), this function can be called from signal handler. It | |
4639 // doesn't block SIGINT et al. | |
4640 int os::fork_and_exec(char* cmd) { | |
4641 const char * argv[4] = {"sh", "-c", cmd, NULL}; | |
4642 | |
4643 // fork() in BsdThreads/NPTL is not async-safe. It needs to run | |
4644 // pthread_atfork handlers and reset pthread library. All we need is a | |
4645 // separate process to execve. Make a direct syscall to fork process. | |
4646 // On IA64 there's no fork syscall, we have to use fork() and hope for | |
4647 // the best... | |
4648 pid_t pid = fork(); | |
4649 | |
4650 if (pid < 0) { | |
4651 // fork failed | |
4652 return -1; | |
4653 | |
4654 } else if (pid == 0) { | |
4655 // child process | |
4656 | |
4657 // execve() in BsdThreads will call pthread_kill_other_threads_np() | |
4658 // first to kill every thread on the thread list. Because this list is | |
4659 // not reset by fork() (see notes above), execve() will instead kill | |
4660 // every thread in the parent process. We know this is the only thread | |
4661 // in the new process, so make a system call directly. | |
4662 // IA64 should use normal execve() from glibc to match the glibc fork() | |
4663 // above. | |
4664 execve("/bin/sh", (char* const*)argv, environ); | |
4665 | |
4666 // execve failed | |
4667 _exit(-1); | |
4668 | |
4669 } else { | |
4670 // copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't | |
4671 // care about the actual exit code, for now. | |
4672 | |
4673 int status; | |
4674 | |
4675 // Wait for the child process to exit. This returns immediately if | |
4676 // the child has already exited. */ | |
4677 while (waitpid(pid, &status, 0) < 0) { | |
4678 switch (errno) { | |
4679 case ECHILD: return 0; | |
4680 case EINTR: break; | |
4681 default: return -1; | |
4682 } | |
4683 } | |
4684 | |
4685 if (WIFEXITED(status)) { | |
4686 // The child exited normally; get its exit code. | |
4687 return WEXITSTATUS(status); | |
4688 } else if (WIFSIGNALED(status)) { | |
4689 // The child exited because of a signal | |
4690 // The best value to return is 0x80 + signal number, | |
4691 // because that is what all Unix shells do, and because | |
4692 // it allows callers to distinguish between process exit and | |
4693 // process death by signal. | |
4694 return 0x80 + WTERMSIG(status); | |
4695 } else { | |
4696 // Unknown exit code; pass it through | |
4697 return status; | |
4698 } | |
4699 } | |
4700 } | |
4701 | |
4702 // is_headless_jre() | |
4703 // | |
4082
36b057451829
7110017: is_headless_jre should be updated to reflect the new location of awt toolkit libraries
dholmes
parents:
4006
diff
changeset
|
4704 // Test for the existence of xawt/libmawt.so or libawt_xawt.so |
3960 | 4705 // in order to report if we are running in a headless jre |
4706 // | |
4082
36b057451829
7110017: is_headless_jre should be updated to reflect the new location of awt toolkit libraries
dholmes
parents:
4006
diff
changeset
|
4707 // Since JDK8 xawt/libmawt.so was moved into the same directory |
36b057451829
7110017: is_headless_jre should be updated to reflect the new location of awt toolkit libraries
dholmes
parents:
4006
diff
changeset
|
4708 // as libawt.so, and renamed libawt_xawt.so |
36b057451829
7110017: is_headless_jre should be updated to reflect the new location of awt toolkit libraries
dholmes
parents:
4006
diff
changeset
|
4709 // |
3960 | 4710 bool os::is_headless_jre() { |
4711 struct stat statbuf; | |
4712 char buf[MAXPATHLEN]; | |
4713 char libmawtpath[MAXPATHLEN]; | |
4006 | 4714 const char *xawtstr = "/xawt/libmawt" JNI_LIB_SUFFIX; |
5921 | 4715 const char *new_xawtstr = "/libawt_xawt" JNI_LIB_SUFFIX; |
3960 | 4716 char *p; |
4717 | |
4718 // Get path to libjvm.so | |
4719 os::jvm_path(buf, sizeof(buf)); | |
4720 | |
4721 // Get rid of libjvm.so | |
4722 p = strrchr(buf, '/'); | |
4723 if (p == NULL) return false; | |
4724 else *p = '\0'; | |
4725 | |
4726 // Get rid of client or server | |
4727 p = strrchr(buf, '/'); | |
4728 if (p == NULL) return false; | |
4729 else *p = '\0'; | |
4730 | |
4731 // check xawt/libmawt.so | |
4732 strcpy(libmawtpath, buf); | |
4733 strcat(libmawtpath, xawtstr); | |
4734 if (::stat(libmawtpath, &statbuf) == 0) return false; | |
4735 | |
4082
36b057451829
7110017: is_headless_jre should be updated to reflect the new location of awt toolkit libraries
dholmes
parents:
4006
diff
changeset
|
4736 // check libawt_xawt.so |
3960 | 4737 strcpy(libmawtpath, buf); |
4082
36b057451829
7110017: is_headless_jre should be updated to reflect the new location of awt toolkit libraries
dholmes
parents:
4006
diff
changeset
|
4738 strcat(libmawtpath, new_xawtstr); |
3960 | 4739 if (::stat(libmawtpath, &statbuf) == 0) return false; |
4740 | |
4741 return true; | |
4742 } | |
6200
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4743 |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4744 // Get the default path to the core file |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4745 // Returns the length of the string |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4746 int os::get_core_path(char* buffer, size_t bufferSize) { |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4747 int n = jio_snprintf(buffer, bufferSize, "/cores"); |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4748 |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4749 // Truncate if theoretical string was longer than bufferSize |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4750 n = MIN2(n, (int)bufferSize); |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4751 |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4752 return n; |
65906dc96aa1
7129724: MAC: Core file location is wrong in crash report
mikael
parents:
6197
diff
changeset
|
4753 } |
10405 | 4754 |
12110
4c84d351cca9
8007074: SIGSEGV at ParMarkBitMap::verify_clear()
stefank
parents:
12096
diff
changeset
|
4755 #ifndef PRODUCT |
4c84d351cca9
8007074: SIGSEGV at ParMarkBitMap::verify_clear()
stefank
parents:
12096
diff
changeset
|
4756 void TestReserveMemorySpecial_test() { |
4c84d351cca9
8007074: SIGSEGV at ParMarkBitMap::verify_clear()
stefank
parents:
12096
diff
changeset
|
4757 // No tests available for this platform |
4c84d351cca9
8007074: SIGSEGV at ParMarkBitMap::verify_clear()
stefank
parents:
12096
diff
changeset
|
4758 } |
4c84d351cca9
8007074: SIGSEGV at ParMarkBitMap::verify_clear()
stefank
parents:
12096
diff
changeset
|
4759 #endif |