never@3156: /* dcubed@4471: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. never@3156: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. never@3156: * never@3156: * This code is free software; you can redistribute it and/or modify it never@3156: * under the terms of the GNU General Public License version 2 only, as never@3156: * published by the Free Software Foundation. never@3156: * never@3156: * This code is distributed in the hope that it will be useful, but WITHOUT never@3156: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or never@3156: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License never@3156: * version 2 for more details (a copy is included in the LICENSE file that never@3156: * accompanied this code). never@3156: * never@3156: * You should have received a copy of the GNU General Public License version never@3156: * 2 along with this work; if not, write to the Free Software Foundation, never@3156: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. never@3156: * never@3156: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA never@3156: * or visit www.oracle.com if you need additional information or have any never@3156: * questions. never@3156: * never@3156: */ never@3156: never@3156: // no precompiled headers never@3156: #include "classfile/classLoader.hpp" never@3156: #include "classfile/systemDictionary.hpp" never@3156: #include "classfile/vmSymbols.hpp" never@3156: #include "code/icBuffer.hpp" never@3156: #include "code/vtableStubs.hpp" never@3156: #include "compiler/compileBroker.hpp" twisti@4318: #include "compiler/disassembler.hpp" never@3156: #include "interpreter/interpreter.hpp" never@3156: #include "jvm_bsd.h" never@3156: #include "memory/allocation.inline.hpp" never@3156: #include "memory/filemap.hpp" never@3156: #include "mutex_bsd.inline.hpp" never@3156: #include "oops/oop.inline.hpp" never@3156: #include "os_share_bsd.hpp" never@3156: #include "prims/jniFastGetField.hpp" never@3156: #include "prims/jvm.h" never@3156: #include "prims/jvm_misc.hpp" never@3156: #include "runtime/arguments.hpp" never@3156: #include "runtime/extendedPC.hpp" never@3156: #include "runtime/globals.hpp" never@3156: #include "runtime/interfaceSupport.hpp" never@3156: #include "runtime/java.hpp" never@3156: #include "runtime/javaCalls.hpp" never@3156: #include "runtime/mutexLocker.hpp" never@3156: #include "runtime/objectMonitor.hpp" never@3156: #include "runtime/osThread.hpp" never@3156: #include "runtime/perfMemory.hpp" never@3156: #include "runtime/sharedRuntime.hpp" never@3156: #include "runtime/statSampler.hpp" never@3156: #include "runtime/stubRoutines.hpp" stefank@4299: #include "runtime/thread.inline.hpp" never@3156: #include "runtime/threadCritical.hpp" never@3156: #include "runtime/timer.hpp" never@3156: #include "services/attachListener.hpp" zgu@4711: #include "services/memTracker.hpp" never@3156: #include "services/runtimeService.hpp" never@3156: #include "utilities/decoder.hpp" never@3156: #include "utilities/defaultStream.hpp" never@3156: #include "utilities/events.hpp" never@3156: #include "utilities/growableArray.hpp" never@3156: #include "utilities/vmError.hpp" never@3156: never@3156: // put OS-includes here never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: # include never@3156: #ifndef __APPLE__ never@3156: # include never@3156: #endif never@3156: # include never@3156: # include never@3156: # include never@3156: never@3156: #if defined(__FreeBSD__) || defined(__NetBSD__) never@3156: # include never@3156: #endif never@3156: never@3156: #ifdef __APPLE__ dcubed@3202: # include // semaphore_* API dcubed@3202: # include dcubed@3202: # include dcubed@3202: # include never@3156: #endif never@3156: never@3156: #ifndef MAP_ANONYMOUS never@3156: #define MAP_ANONYMOUS MAP_ANON never@3156: #endif never@3156: never@3156: #define MAX_PATH (2 * K) never@3156: never@3156: // for timer info max values which include all bits never@3156: #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) never@3156: never@3156: #define LARGEPAGES_BIT (1 << 6) never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // global variables never@3156: julong os::Bsd::_physical_memory = 0; never@3156: never@3156: never@3156: int (*os::Bsd::_clock_gettime)(clockid_t, struct timespec *) = NULL; never@3156: pthread_t os::Bsd::_main_thread; never@3156: int os::Bsd::_page_size = -1; never@3156: never@3156: static jlong initial_time_count=0; never@3156: never@3156: static int clock_tics_per_sec = 100; never@3156: never@3156: // For diagnostics to print a message once. see run_periodic_checks never@3156: static sigset_t check_signal_done; sla@4229: static bool check_signals = true; never@3156: never@3156: static pid_t _initial_pid = 0; never@3156: never@3156: /* Signal number used to suspend/resume a thread */ never@3156: never@3156: /* do not use any signal number less than SIGSEGV, see 4355769 */ never@3156: static int SR_signum = SIGUSR2; never@3156: sigset_t SR_sigset; never@3156: never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // utility functions never@3156: never@3156: static int SR_initialize(); never@3156: static int SR_finalize(); never@3156: never@3156: julong os::available_memory() { never@3156: return Bsd::available_memory(); never@3156: } never@3156: never@3156: julong os::Bsd::available_memory() { never@3156: // XXXBSD: this is just a stopgap implementation never@3156: return physical_memory() >> 2; never@3156: } never@3156: never@3156: julong os::physical_memory() { never@3156: return Bsd::physical_memory(); never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // environment support never@3156: never@3156: bool os::getenv(const char* name, char* buf, int len) { never@3156: const char* val = ::getenv(name); never@3156: if (val != NULL && strlen(val) < (size_t)len) { never@3156: strcpy(buf, val); never@3156: return true; never@3156: } never@3156: if (len > 0) buf[0] = 0; // return a null string never@3156: return false; never@3156: } never@3156: never@3156: never@3156: // Return true if user is running as root. never@3156: never@3156: bool os::have_special_privileges() { never@3156: static bool init = false; never@3156: static bool privileges = false; never@3156: if (!init) { never@3156: privileges = (getuid() != geteuid()) || (getgid() != getegid()); never@3156: init = true; never@3156: } never@3156: return privileges; never@3156: } never@3156: never@3156: never@3156: never@3156: // Cpu architecture string never@3156: #if defined(ZERO) never@3156: static char cpu_arch[] = ZERO_LIBARCH; never@3156: #elif defined(IA64) never@3156: static char cpu_arch[] = "ia64"; never@3156: #elif defined(IA32) never@3156: static char cpu_arch[] = "i386"; never@3156: #elif defined(AMD64) never@3156: static char cpu_arch[] = "amd64"; never@3156: #elif defined(ARM) never@3156: static char cpu_arch[] = "arm"; never@3156: #elif defined(PPC) never@3156: static char cpu_arch[] = "ppc"; never@3156: #elif defined(SPARC) never@3156: # ifdef _LP64 never@3156: static char cpu_arch[] = "sparcv9"; never@3156: # else never@3156: static char cpu_arch[] = "sparc"; never@3156: # endif never@3156: #else never@3156: #error Add appropriate cpu_arch setting never@3156: #endif never@3156: phh@3473: // Compiler variant phh@3473: #ifdef COMPILER2 phh@3473: #define COMPILER_VARIANT "server" phh@3473: #else phh@3473: #define COMPILER_VARIANT "client" phh@3473: #endif never@3156: sla@4229: never@3156: void os::Bsd::initialize_system_info() { never@3156: int mib[2]; never@3156: size_t len; never@3156: int cpu_val; brutisso@4468: julong mem_val; never@3156: never@3156: /* get processors count via hw.ncpus sysctl */ never@3156: mib[0] = CTL_HW; never@3156: mib[1] = HW_NCPU; never@3156: len = sizeof(cpu_val); never@3156: if (sysctl(mib, 2, &cpu_val, &len, NULL, 0) != -1 && cpu_val >= 1) { brutisso@4468: assert(len == sizeof(cpu_val), "unexpected data size"); never@3156: set_processor_count(cpu_val); never@3156: } never@3156: else { never@3156: set_processor_count(1); // fallback never@3156: } never@3156: brutisso@4468: /* get physical memory via hw.memsize sysctl (hw.memsize is used brutisso@4468: * since it returns a 64 bit value) never@3156: */ never@3156: mib[0] = CTL_HW; brutisso@4468: mib[1] = HW_MEMSIZE; never@3156: len = sizeof(mem_val); brutisso@4468: if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) { brutisso@4468: assert(len == sizeof(mem_val), "unexpected data size"); never@3156: _physical_memory = mem_val; brutisso@4468: } else { never@3156: _physical_memory = 256*1024*1024; // fallback (XXXBSD?) brutisso@4468: } never@3156: never@3156: #ifdef __OpenBSD__ never@3156: { never@3156: // limit _physical_memory memory view on OpenBSD since never@3156: // datasize rlimit restricts us anyway. never@3156: struct rlimit limits; never@3156: getrlimit(RLIMIT_DATA, &limits); never@3156: _physical_memory = MIN2(_physical_memory, (julong)limits.rlim_cur); never@3156: } never@3156: #endif never@3156: } never@3156: dcubed@3202: #ifdef __APPLE__ dcubed@3202: static const char *get_home() { dcubed@3202: const char *home_dir = ::getenv("HOME"); dcubed@3202: if ((home_dir == NULL) || (*home_dir == '\0')) { dcubed@3202: struct passwd *passwd_info = getpwuid(geteuid()); dcubed@3202: if (passwd_info != NULL) { dcubed@3202: home_dir = passwd_info->pw_dir; dcubed@3202: } dcubed@3202: } dcubed@3202: dcubed@3202: return home_dir; dcubed@3202: } dcubed@3202: #endif dcubed@3202: never@3156: void os::init_system_properties_values() { never@3156: // char arch[12]; never@3156: // sysinfo(SI_ARCHITECTURE, arch, sizeof(arch)); never@3156: never@3156: // The next steps are taken in the product version: never@3156: // dcubed@4392: // Obtain the JAVA_HOME value from the location of libjvm.so. never@3156: // This library should be located at: dcubed@4392: // /jre/lib//{client|server}/libjvm.so. never@3156: // never@3156: // If "/jre/lib/" appears at the right place in the path, then we dcubed@4392: // assume libjvm.so is installed in a JDK and we use this path. never@3156: // never@3156: // Otherwise exit with message: "Could not create the Java virtual machine." never@3156: // never@3156: // The following extra steps are taken in the debugging version: never@3156: // never@3156: // If "/jre/lib/" does NOT appear at the right place in the path never@3156: // instead of exit check for $JAVA_HOME environment variable. never@3156: // never@3156: // If it is defined and we are able to locate $JAVA_HOME/jre/lib/, dcubed@4392: // then we append a fake suffix "hotspot/libjvm.so" to this path so dcubed@4392: // it looks like libjvm.so is installed there dcubed@4392: // /jre/lib//hotspot/libjvm.so. never@3156: // never@3156: // Otherwise exit. never@3156: // never@3156: // Important note: if the location of libjvm.so changes this never@3156: // code needs to be changed accordingly. never@3156: never@3156: // The next few definitions allow the code to be verbatim: zgu@3900: #define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal) never@3156: #define getenv(n) ::getenv(n) never@3156: never@3156: /* never@3156: * See ld(1): never@3156: * The linker uses the following search paths to locate required never@3156: * shared libraries: never@3156: * 1: ... never@3156: * ... never@3156: * 7: The default directories, normally /lib and /usr/lib. never@3156: */ never@3156: #ifndef DEFAULT_LIBPATH never@3156: #define DEFAULT_LIBPATH "/lib:/usr/lib" never@3156: #endif never@3156: never@3156: #define EXTENSIONS_DIR "/lib/ext" never@3156: #define ENDORSED_DIR "/lib/endorsed" never@3156: #define REG_DIR "/usr/java/packages" never@3156: dcubed@3202: #ifdef __APPLE__ dcubed@3202: #define SYS_EXTENSIONS_DIR "/Library/Java/Extensions" dcubed@3202: #define SYS_EXTENSIONS_DIRS SYS_EXTENSIONS_DIR ":/Network" SYS_EXTENSIONS_DIR ":/System" SYS_EXTENSIONS_DIR ":/usr/lib/java" dcubed@3202: const char *user_home_dir = get_home(); dcubed@3202: // the null in SYS_EXTENSIONS_DIRS counts for the size of the colon after user_home_dir dcubed@3202: int system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) + dcubed@3202: sizeof(SYS_EXTENSIONS_DIRS); dcubed@3202: #endif dcubed@3202: never@3156: { never@3156: /* sysclasspath, java_home, dll_dir */ never@3156: { never@3156: char *home_path; never@3156: char *dll_path; never@3156: char *pslash; never@3156: char buf[MAXPATHLEN]; never@3156: os::jvm_path(buf, sizeof(buf)); never@3156: never@3156: // Found the full path to libjvm.so. never@3156: // Now cut the path to /jre if we can. never@3156: *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */ never@3156: pslash = strrchr(buf, '/'); never@3156: if (pslash != NULL) never@3156: *pslash = '\0'; /* get rid of /{client|server|hotspot} */ never@3156: dll_path = malloc(strlen(buf) + 1); never@3156: if (dll_path == NULL) never@3156: return; never@3156: strcpy(dll_path, buf); never@3156: Arguments::set_dll_dir(dll_path); never@3156: never@3156: if (pslash != NULL) { never@3156: pslash = strrchr(buf, '/'); never@3156: if (pslash != NULL) { dcubed@3202: *pslash = '\0'; /* get rid of / (/lib on macosx) */ dcubed@3202: #ifndef __APPLE__ never@3156: pslash = strrchr(buf, '/'); never@3156: if (pslash != NULL) never@3156: *pslash = '\0'; /* get rid of /lib */ dcubed@3202: #endif never@3156: } never@3156: } never@3156: never@3156: home_path = malloc(strlen(buf) + 1); never@3156: if (home_path == NULL) never@3156: return; never@3156: strcpy(home_path, buf); never@3156: Arguments::set_java_home(home_path); never@3156: never@3156: if (!set_boot_path('/', ':')) never@3156: return; never@3156: } never@3156: never@3156: /* never@3156: * Where to look for native libraries never@3156: * never@3156: * Note: Due to a legacy implementation, most of the library path never@3156: * is set in the launcher. This was to accomodate linking restrictions never@3156: * on legacy Bsd implementations (which are no longer supported). never@3156: * Eventually, all the library path setting will be done here. never@3156: * never@3156: * However, to prevent the proliferation of improperly built native never@3156: * libraries, the new path component /usr/java/packages is added here. never@3156: * Eventually, all the library path setting will be done here. never@3156: */ never@3156: { never@3156: char *ld_library_path; never@3156: never@3156: /* never@3156: * Construct the invariant part of ld_library_path. Note that the never@3156: * space for the colon and the trailing null are provided by the never@3156: * nulls included by the sizeof operator (so actually we allocate never@3156: * a byte more than necessary). never@3156: */ dcubed@3202: #ifdef __APPLE__ dcubed@3202: ld_library_path = (char *) malloc(system_ext_size); dcubed@3202: sprintf(ld_library_path, "%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS, user_home_dir); dcubed@3202: #else never@3156: ld_library_path = (char *) malloc(sizeof(REG_DIR) + sizeof("/lib/") + never@3156: strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH)); never@3156: sprintf(ld_library_path, REG_DIR "/lib/%s:" DEFAULT_LIBPATH, cpu_arch); dcubed@3202: #endif never@3156: never@3156: /* never@3156: * Get the user setting of LD_LIBRARY_PATH, and prepended it. It never@3156: * should always exist (until the legacy problem cited above is never@3156: * addressed). never@3156: */ never@3156: #ifdef __APPLE__ dcubed@3202: // Prepend the default path with the JAVA_LIBRARY_PATH so that the app launcher code can specify a directory inside an app wrapper dcubed@3202: char *l = getenv("JAVA_LIBRARY_PATH"); dcubed@3202: if (l != NULL) { dcubed@3202: char *t = ld_library_path; dcubed@3202: /* That's +1 for the colon and +1 for the trailing '\0' */ dcubed@3202: ld_library_path = (char *) malloc(strlen(l) + 1 + strlen(t) + 1); dcubed@3202: sprintf(ld_library_path, "%s:%s", l, t); dcubed@3202: free(t); dcubed@3202: } dcubed@3202: never@3156: char *v = getenv("DYLD_LIBRARY_PATH"); never@3156: #else never@3156: char *v = getenv("LD_LIBRARY_PATH"); never@3156: #endif never@3156: if (v != NULL) { never@3156: char *t = ld_library_path; never@3156: /* That's +1 for the colon and +1 for the trailing '\0' */ never@3156: ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1); never@3156: sprintf(ld_library_path, "%s:%s", v, t); dcubed@3202: free(t); never@3156: } dcubed@3586: dcubed@3586: #ifdef __APPLE__ dcubed@3586: // Apple's Java6 has "." at the beginning of java.library.path. dcubed@3586: // OpenJDK on Windows has "." at the end of java.library.path. dcubed@3586: // OpenJDK on Linux and Solaris don't have "." in java.library.path dcubed@3586: // at all. To ease the transition from Apple's Java6 to OpenJDK7, dcubed@3586: // "." is appended to the end of java.library.path. Yes, this dcubed@3586: // could cause a change in behavior, but Apple's Java6 behavior dcubed@3586: // can be achieved by putting "." at the beginning of the dcubed@3586: // JAVA_LIBRARY_PATH environment variable. dcubed@3586: { dcubed@3586: char *t = ld_library_path; dcubed@3586: // that's +3 for appending ":." and the trailing '\0' dcubed@3586: ld_library_path = (char *) malloc(strlen(t) + 3); dcubed@3586: sprintf(ld_library_path, "%s:%s", t, "."); dcubed@3586: free(t); dcubed@3586: } dcubed@3586: #endif dcubed@3586: never@3156: Arguments::set_library_path(ld_library_path); never@3156: } never@3156: never@3156: /* never@3156: * Extensions directories. never@3156: * never@3156: * Note that the space for the colon and the trailing null are provided never@3156: * by the nulls included by the sizeof operator (so actually one byte more never@3156: * than necessary is allocated). never@3156: */ never@3156: { dcubed@3202: #ifdef __APPLE__ dcubed@3202: char *buf = malloc(strlen(Arguments::get_java_home()) + dcubed@3202: sizeof(EXTENSIONS_DIR) + system_ext_size); dcubed@3202: sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" dcubed@3202: SYS_EXTENSIONS_DIRS, user_home_dir, Arguments::get_java_home()); dcubed@3202: #else never@3156: char *buf = malloc(strlen(Arguments::get_java_home()) + never@3156: sizeof(EXTENSIONS_DIR) + sizeof(REG_DIR) + sizeof(EXTENSIONS_DIR)); never@3156: sprintf(buf, "%s" EXTENSIONS_DIR ":" REG_DIR EXTENSIONS_DIR, never@3156: Arguments::get_java_home()); dcubed@3202: #endif dcubed@3202: never@3156: Arguments::set_ext_dirs(buf); never@3156: } never@3156: never@3156: /* Endorsed standards default directory. */ never@3156: { never@3156: char * buf; never@3156: buf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR)); never@3156: sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home()); never@3156: Arguments::set_endorsed_dirs(buf); never@3156: } never@3156: } never@3156: dcubed@3202: #ifdef __APPLE__ dcubed@3202: #undef SYS_EXTENSIONS_DIR dcubed@3202: #endif never@3156: #undef malloc never@3156: #undef getenv never@3156: #undef EXTENSIONS_DIR never@3156: #undef ENDORSED_DIR never@3156: never@3156: // Done never@3156: return; never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // breakpoint support never@3156: never@3156: void os::breakpoint() { never@3156: BREAKPOINT; never@3156: } never@3156: never@3156: extern "C" void breakpoint() { never@3156: // use debugger to set breakpoint here never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // signal support never@3156: never@3156: debug_only(static bool signal_sets_initialized = false); never@3156: static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs; never@3156: never@3156: bool os::Bsd::is_sig_ignored(int sig) { never@3156: struct sigaction oact; never@3156: sigaction(sig, (struct sigaction*)NULL, &oact); never@3156: void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction) never@3156: : CAST_FROM_FN_PTR(void*, oact.sa_handler); never@3156: if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN)) never@3156: return true; never@3156: else never@3156: return false; never@3156: } never@3156: never@3156: void os::Bsd::signal_sets_init() { never@3156: // Should also have an assertion stating we are still single-threaded. never@3156: assert(!signal_sets_initialized, "Already initialized"); never@3156: // Fill in signals that are necessarily unblocked for all threads in never@3156: // the VM. Currently, we unblock the following signals: never@3156: // SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden never@3156: // by -Xrs (=ReduceSignalUsage)); never@3156: // BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all never@3156: // other threads. The "ReduceSignalUsage" boolean tells us not to alter never@3156: // the dispositions or masks wrt these signals. never@3156: // Programs embedding the VM that want to use the above signals for their never@3156: // own purposes must, at this time, use the "-Xrs" option to prevent never@3156: // interference with shutdown hooks and BREAK_SIGNAL thread dumping. never@3156: // (See bug 4345157, and other related bugs). never@3156: // In reality, though, unblocking these signals is really a nop, since never@3156: // these signals are not blocked by default. never@3156: sigemptyset(&unblocked_sigs); never@3156: sigemptyset(&allowdebug_blocked_sigs); never@3156: sigaddset(&unblocked_sigs, SIGILL); never@3156: sigaddset(&unblocked_sigs, SIGSEGV); never@3156: sigaddset(&unblocked_sigs, SIGBUS); never@3156: sigaddset(&unblocked_sigs, SIGFPE); never@3156: sigaddset(&unblocked_sigs, SR_signum); never@3156: never@3156: if (!ReduceSignalUsage) { never@3156: if (!os::Bsd::is_sig_ignored(SHUTDOWN1_SIGNAL)) { never@3156: sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL); never@3156: sigaddset(&allowdebug_blocked_sigs, SHUTDOWN1_SIGNAL); never@3156: } never@3156: if (!os::Bsd::is_sig_ignored(SHUTDOWN2_SIGNAL)) { never@3156: sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL); never@3156: sigaddset(&allowdebug_blocked_sigs, SHUTDOWN2_SIGNAL); never@3156: } never@3156: if (!os::Bsd::is_sig_ignored(SHUTDOWN3_SIGNAL)) { never@3156: sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL); never@3156: sigaddset(&allowdebug_blocked_sigs, SHUTDOWN3_SIGNAL); never@3156: } never@3156: } never@3156: // Fill in signals that are blocked by all but the VM thread. never@3156: sigemptyset(&vm_sigs); never@3156: if (!ReduceSignalUsage) never@3156: sigaddset(&vm_sigs, BREAK_SIGNAL); never@3156: debug_only(signal_sets_initialized = true); never@3156: never@3156: } never@3156: never@3156: // These are signals that are unblocked while a thread is running Java. never@3156: // (For some reason, they get blocked by default.) never@3156: sigset_t* os::Bsd::unblocked_signals() { never@3156: assert(signal_sets_initialized, "Not initialized"); never@3156: return &unblocked_sigs; never@3156: } never@3156: never@3156: // These are the signals that are blocked while a (non-VM) thread is never@3156: // running Java. Only the VM thread handles these signals. never@3156: sigset_t* os::Bsd::vm_signals() { never@3156: assert(signal_sets_initialized, "Not initialized"); never@3156: return &vm_sigs; never@3156: } never@3156: never@3156: // These are signals that are blocked during cond_wait to allow debugger in never@3156: sigset_t* os::Bsd::allowdebug_blocked_signals() { never@3156: assert(signal_sets_initialized, "Not initialized"); never@3156: return &allowdebug_blocked_sigs; never@3156: } never@3156: never@3156: void os::Bsd::hotspot_sigmask(Thread* thread) { never@3156: never@3156: //Save caller's signal mask before setting VM signal mask never@3156: sigset_t caller_sigmask; never@3156: pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask); never@3156: never@3156: OSThread* osthread = thread->osthread(); never@3156: osthread->set_caller_sigmask(caller_sigmask); never@3156: never@3156: pthread_sigmask(SIG_UNBLOCK, os::Bsd::unblocked_signals(), NULL); never@3156: never@3156: if (!ReduceSignalUsage) { never@3156: if (thread->is_VM_thread()) { never@3156: // Only the VM thread handles BREAK_SIGNAL ... never@3156: pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL); never@3156: } else { never@3156: // ... all other threads block BREAK_SIGNAL never@3156: pthread_sigmask(SIG_BLOCK, vm_signals(), NULL); never@3156: } never@3156: } never@3156: } never@3156: never@3156: never@3156: ////////////////////////////////////////////////////////////////////////////// never@3156: // create new thread never@3156: never@3156: static address highest_vm_reserved_address(); never@3156: never@3156: // check if it's safe to start a new thread never@3156: static bool _thread_safety_check(Thread* thread) { sla@4229: return true; never@3156: } never@3156: dcubed@3202: #ifdef __APPLE__ dcubed@3202: // library handle for calling objc_registerThreadWithCollector() dcubed@3202: // without static linking to the libobjc library dcubed@3202: #define OBJC_LIB "/usr/lib/libobjc.dylib" dcubed@3202: #define OBJC_GCREGISTER "objc_registerThreadWithCollector" dcubed@3202: typedef void (*objc_registerThreadWithCollector_t)(); dcubed@3202: extern "C" objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction; dcubed@3202: objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL; dcubed@3202: #endif dcubed@3202: sla@4564: #ifdef __APPLE__ sla@4564: static uint64_t locate_unique_thread_id() { sla@4564: // Additional thread_id used to correlate threads in SA sla@4564: thread_identifier_info_data_t m_ident_info; sla@4564: mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; sla@4564: sla@4564: thread_info(::mach_thread_self(), THREAD_IDENTIFIER_INFO, sla@4564: (thread_info_t) &m_ident_info, &count); sla@4564: return m_ident_info.thread_id; sla@4564: } sla@4564: #endif sla@4564: never@3156: // Thread start routine for all newly created threads never@3156: static void *java_start(Thread *thread) { never@3156: // Try to randomize the cache line index of hot stack frames. never@3156: // This helps when threads of the same stack traces evict each other's never@3156: // cache lines. The threads can be either from the same JVM instance, or never@3156: // from different JVM instances. The benefit is especially true for never@3156: // processors with hyperthreading technology. never@3156: static int counter = 0; never@3156: int pid = os::current_process_id(); never@3156: alloca(((pid ^ counter++) & 7) * 128); never@3156: never@3156: ThreadLocalStorage::set_thread(thread); never@3156: never@3156: OSThread* osthread = thread->osthread(); never@3156: Monitor* sync = osthread->startThread_lock(); never@3156: never@3156: // non floating stack BsdThreads needs extra check, see above never@3156: if (!_thread_safety_check(thread)) { never@3156: // notify parent thread never@3156: MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); never@3156: osthread->set_state(ZOMBIE); never@3156: sync->notify_all(); never@3156: return NULL; never@3156: } never@3156: sla@3587: #ifdef __APPLE__ sla@3587: // thread_id is mach thread on macos sla@3587: osthread->set_thread_id(::mach_thread_self()); sla@4564: osthread->set_unique_thread_id(locate_unique_thread_id()); sla@3587: #else never@3156: // thread_id is pthread_id on BSD never@3156: osthread->set_thread_id(::pthread_self()); sla@3587: #endif never@3156: // initialize signal mask for this thread never@3156: os::Bsd::hotspot_sigmask(thread); never@3156: never@3156: // initialize floating point control register never@3156: os::Bsd::init_thread_fpu_state(); never@3156: dcubed@3202: #ifdef __APPLE__ dcubed@3202: // register thread with objc gc dcubed@3202: if (objc_registerThreadWithCollectorFunction != NULL) { dcubed@3202: objc_registerThreadWithCollectorFunction(); dcubed@3202: } dcubed@3202: #endif dcubed@3202: never@3156: // handshaking with parent thread never@3156: { never@3156: MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); never@3156: never@3156: // notify parent thread never@3156: osthread->set_state(INITIALIZED); never@3156: sync->notify_all(); never@3156: never@3156: // wait until os::start_thread() never@3156: while (osthread->get_state() == INITIALIZED) { never@3156: sync->wait(Mutex::_no_safepoint_check_flag); never@3156: } never@3156: } never@3156: never@3156: // call one more level start routine never@3156: thread->run(); never@3156: never@3156: return 0; never@3156: } never@3156: never@3156: bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { never@3156: assert(thread->osthread() == NULL, "caller responsible"); never@3156: never@3156: // Allocate the OSThread object never@3156: OSThread* osthread = new OSThread(NULL, NULL); never@3156: if (osthread == NULL) { never@3156: return false; never@3156: } never@3156: never@3156: // set the correct thread state never@3156: osthread->set_thread_type(thr_type); never@3156: never@3156: // Initial state is ALLOCATED but not INITIALIZED never@3156: osthread->set_state(ALLOCATED); never@3156: never@3156: thread->set_osthread(osthread); never@3156: never@3156: // init thread attributes never@3156: pthread_attr_t attr; never@3156: pthread_attr_init(&attr); never@3156: pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); never@3156: never@3156: // stack size never@3156: if (os::Bsd::supports_variable_stack_size()) { never@3156: // calculate stack size if it's not specified by caller never@3156: if (stack_size == 0) { never@3156: stack_size = os::Bsd::default_stack_size(thr_type); never@3156: never@3156: switch (thr_type) { never@3156: case os::java_thread: never@3156: // Java threads use ThreadStackSize which default value can be never@3156: // changed with the flag -Xss never@3156: assert (JavaThread::stack_size_at_create() > 0, "this should be set"); never@3156: stack_size = JavaThread::stack_size_at_create(); never@3156: break; never@3156: case os::compiler_thread: never@3156: if (CompilerThreadStackSize > 0) { never@3156: stack_size = (size_t)(CompilerThreadStackSize * K); never@3156: break; never@3156: } // else fall through: never@3156: // use VMThreadStackSize if CompilerThreadStackSize is not defined never@3156: case os::vm_thread: never@3156: case os::pgc_thread: never@3156: case os::cgc_thread: never@3156: case os::watcher_thread: never@3156: if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); never@3156: break; never@3156: } never@3156: } never@3156: never@3156: stack_size = MAX2(stack_size, os::Bsd::min_stack_allowed); never@3156: pthread_attr_setstacksize(&attr, stack_size); never@3156: } else { never@3156: // let pthread_create() pick the default value. never@3156: } never@3156: never@3156: ThreadState state; never@3156: never@3156: { never@3156: pthread_t tid; never@3156: int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); never@3156: never@3156: pthread_attr_destroy(&attr); never@3156: never@3156: if (ret != 0) { never@3156: if (PrintMiscellaneous && (Verbose || WizardMode)) { never@3156: perror("pthread_create()"); never@3156: } never@3156: // Need to clean up stuff we've allocated so far never@3156: thread->set_osthread(NULL); never@3156: delete osthread; never@3156: return false; never@3156: } never@3156: never@3156: // Store pthread info into the OSThread never@3156: osthread->set_pthread_id(tid); never@3156: never@3156: // Wait until child thread is either initialized or aborted never@3156: { never@3156: Monitor* sync_with_child = osthread->startThread_lock(); never@3156: MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); never@3156: while ((state = osthread->get_state()) == ALLOCATED) { never@3156: sync_with_child->wait(Mutex::_no_safepoint_check_flag); never@3156: } never@3156: } never@3156: never@3156: } never@3156: never@3156: // Aborted due to thread limit being reached never@3156: if (state == ZOMBIE) { never@3156: thread->set_osthread(NULL); never@3156: delete osthread; never@3156: return false; never@3156: } never@3156: never@3156: // The thread is returned suspended (in state INITIALIZED), never@3156: // and is started higher up in the call chain never@3156: assert(state == INITIALIZED, "race condition"); never@3156: return true; never@3156: } never@3156: never@3156: ///////////////////////////////////////////////////////////////////////////// never@3156: // attach existing thread never@3156: never@3156: // bootstrap the main thread never@3156: bool os::create_main_thread(JavaThread* thread) { never@3156: assert(os::Bsd::_main_thread == pthread_self(), "should be called inside main thread"); never@3156: return create_attached_thread(thread); never@3156: } never@3156: never@3156: bool os::create_attached_thread(JavaThread* thread) { never@3156: #ifdef ASSERT never@3156: thread->verify_not_published(); never@3156: #endif never@3156: never@3156: // Allocate the OSThread object never@3156: OSThread* osthread = new OSThread(NULL, NULL); never@3156: never@3156: if (osthread == NULL) { never@3156: return false; never@3156: } never@3156: never@3156: // Store pthread info into the OSThread sla@3587: #ifdef __APPLE__ sla@3587: osthread->set_thread_id(::mach_thread_self()); sla@4564: osthread->set_unique_thread_id(locate_unique_thread_id()); sla@3587: #else never@3156: osthread->set_thread_id(::pthread_self()); sla@3587: #endif never@3156: osthread->set_pthread_id(::pthread_self()); never@3156: never@3156: // initialize floating point control register never@3156: os::Bsd::init_thread_fpu_state(); never@3156: never@3156: // Initial thread state is RUNNABLE never@3156: osthread->set_state(RUNNABLE); never@3156: never@3156: thread->set_osthread(osthread); never@3156: never@3156: // initialize signal mask for this thread never@3156: // and save the caller's signal mask never@3156: os::Bsd::hotspot_sigmask(thread); never@3156: never@3156: return true; never@3156: } never@3156: never@3156: void os::pd_start_thread(Thread* thread) { never@3156: OSThread * osthread = thread->osthread(); never@3156: assert(osthread->get_state() != INITIALIZED, "just checking"); never@3156: Monitor* sync_with_child = osthread->startThread_lock(); never@3156: MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); never@3156: sync_with_child->notify(); never@3156: } never@3156: never@3156: // Free Bsd resources related to the OSThread never@3156: void os::free_thread(OSThread* osthread) { never@3156: assert(osthread != NULL, "osthread not set"); never@3156: never@3156: if (Thread::current()->osthread() == osthread) { never@3156: // Restore caller's signal mask never@3156: sigset_t sigmask = osthread->caller_sigmask(); never@3156: pthread_sigmask(SIG_SETMASK, &sigmask, NULL); never@3156: } never@3156: never@3156: delete osthread; never@3156: } never@3156: never@3156: ////////////////////////////////////////////////////////////////////////////// never@3156: // thread local storage never@3156: never@3156: int os::allocate_thread_local_storage() { never@3156: pthread_key_t key; never@3156: int rslt = pthread_key_create(&key, NULL); never@3156: assert(rslt == 0, "cannot allocate thread local storage"); never@3156: return (int)key; never@3156: } never@3156: never@3156: // Note: This is currently not used by VM, as we don't destroy TLS key never@3156: // on VM exit. never@3156: void os::free_thread_local_storage(int index) { never@3156: int rslt = pthread_key_delete((pthread_key_t)index); never@3156: assert(rslt == 0, "invalid index"); never@3156: } never@3156: never@3156: void os::thread_local_storage_at_put(int index, void* value) { never@3156: int rslt = pthread_setspecific((pthread_key_t)index, value); never@3156: assert(rslt == 0, "pthread_setspecific failed"); never@3156: } never@3156: never@3156: extern "C" Thread* get_thread() { never@3156: return ThreadLocalStorage::thread(); never@3156: } never@3156: never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // time support never@3156: never@3156: // Time since start-up in seconds to a fine granularity. never@3156: // Used by VMSelfDestructTimer and the MemProfiler. never@3156: double os::elapsedTime() { never@3156: never@3156: return (double)(os::elapsed_counter()) * 0.000001; never@3156: } never@3156: never@3156: jlong os::elapsed_counter() { never@3156: timeval time; never@3156: int status = gettimeofday(&time, NULL); never@3156: return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count; never@3156: } never@3156: never@3156: jlong os::elapsed_frequency() { never@3156: return (1000 * 1000); never@3156: } never@3156: never@3156: // XXX: For now, code this as if BSD does not support vtime. never@3156: bool os::supports_vtime() { return false; } never@3156: bool os::enable_vtime() { return false; } never@3156: bool os::vtime_enabled() { return false; } never@3156: double os::elapsedVTime() { never@3156: // better than nothing, but not much never@3156: return elapsedTime(); never@3156: } never@3156: never@3156: jlong os::javaTimeMillis() { never@3156: timeval time; never@3156: int status = gettimeofday(&time, NULL); never@3156: assert(status != -1, "bsd error"); never@3156: return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000); never@3156: } never@3156: never@3156: #ifndef CLOCK_MONOTONIC never@3156: #define CLOCK_MONOTONIC (1) never@3156: #endif never@3156: never@3156: #ifdef __APPLE__ never@3156: void os::Bsd::clock_init() { never@3156: // XXXDARWIN: Investigate replacement monotonic clock never@3156: } sla@4229: #else never@3156: void os::Bsd::clock_init() { never@3156: struct timespec res; never@3156: struct timespec tp; never@3156: if (::clock_getres(CLOCK_MONOTONIC, &res) == 0 && never@3156: ::clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { never@3156: // yes, monotonic clock is supported never@3156: _clock_gettime = ::clock_gettime; never@3156: } never@3156: } never@3156: #endif never@3156: never@3156: never@3156: jlong os::javaTimeNanos() { never@3156: if (Bsd::supports_monotonic_clock()) { never@3156: struct timespec tp; never@3156: int status = Bsd::clock_gettime(CLOCK_MONOTONIC, &tp); never@3156: assert(status == 0, "gettime error"); never@3156: jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec); never@3156: return result; never@3156: } else { never@3156: timeval time; never@3156: int status = gettimeofday(&time, NULL); never@3156: assert(status != -1, "bsd error"); never@3156: jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec); never@3156: return 1000 * usecs; never@3156: } never@3156: } never@3156: never@3156: void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { never@3156: if (Bsd::supports_monotonic_clock()) { never@3156: info_ptr->max_value = ALL_64_BITS; never@3156: never@3156: // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past never@3156: info_ptr->may_skip_backward = false; // not subject to resetting or drifting never@3156: info_ptr->may_skip_forward = false; // not subject to resetting or drifting never@3156: } else { never@3156: // gettimeofday - based on time in seconds since the Epoch thus does not wrap never@3156: info_ptr->max_value = ALL_64_BITS; never@3156: never@3156: // gettimeofday is a real time clock so it skips never@3156: info_ptr->may_skip_backward = true; never@3156: info_ptr->may_skip_forward = true; never@3156: } never@3156: never@3156: info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time never@3156: } never@3156: never@3156: // Return the real, user, and system times in seconds from an never@3156: // arbitrary fixed point in the past. never@3156: bool os::getTimesSecs(double* process_real_time, never@3156: double* process_user_time, never@3156: double* process_system_time) { never@3156: struct tms ticks; never@3156: clock_t real_ticks = times(&ticks); never@3156: never@3156: if (real_ticks == (clock_t) (-1)) { never@3156: return false; never@3156: } else { never@3156: double ticks_per_second = (double) clock_tics_per_sec; never@3156: *process_user_time = ((double) ticks.tms_utime) / ticks_per_second; never@3156: *process_system_time = ((double) ticks.tms_stime) / ticks_per_second; never@3156: *process_real_time = ((double) real_ticks) / ticks_per_second; never@3156: never@3156: return true; never@3156: } never@3156: } never@3156: never@3156: never@3156: char * os::local_time_string(char *buf, size_t buflen) { never@3156: struct tm t; never@3156: time_t long_time; never@3156: time(&long_time); never@3156: localtime_r(&long_time, &t); never@3156: jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d", never@3156: t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, never@3156: t.tm_hour, t.tm_min, t.tm_sec); never@3156: return buf; never@3156: } never@3156: never@3156: struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { never@3156: return localtime_r(clock, res); never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // runtime exit support never@3156: never@3156: // Note: os::shutdown() might be called very early during initialization, or never@3156: // called from signal handler. Before adding something to os::shutdown(), make never@3156: // sure it is async-safe and can handle partially initialized VM. never@3156: void os::shutdown() { never@3156: never@3156: // allow PerfMemory to attempt cleanup of any persistent resources never@3156: perfMemory_exit(); never@3156: never@3156: // needs to remove object in file system never@3156: AttachListener::abort(); never@3156: never@3156: // flush buffered output, finish log files never@3156: ostream_abort(); never@3156: never@3156: // Check for abort hook never@3156: abort_hook_t abort_hook = Arguments::abort_hook(); never@3156: if (abort_hook != NULL) { never@3156: abort_hook(); never@3156: } never@3156: never@3156: } never@3156: never@3156: // Note: os::abort() might be called very early during initialization, or never@3156: // called from signal handler. Before adding something to os::abort(), make never@3156: // sure it is async-safe and can handle partially initialized VM. never@3156: void os::abort(bool dump_core) { never@3156: os::shutdown(); never@3156: if (dump_core) { never@3156: #ifndef PRODUCT never@3156: fdStream out(defaultStream::output_fd()); never@3156: out.print_raw("Current thread is "); never@3156: char buf[16]; never@3156: jio_snprintf(buf, sizeof(buf), UINTX_FORMAT, os::current_thread_id()); never@3156: out.print_raw_cr(buf); never@3156: out.print_raw_cr("Dumping core ..."); never@3156: #endif never@3156: ::abort(); // dump core never@3156: } never@3156: never@3156: ::exit(1); never@3156: } never@3156: never@3156: // Die immediately, no exit hook, no abort hook, no cleanup. never@3156: void os::die() { never@3156: // _exit() on BsdThreads only kills current thread never@3156: ::abort(); never@3156: } never@3156: never@3156: // unused on bsd for now. never@3156: void os::set_error_file(const char *logfile) {} never@3156: never@3156: never@3156: // This method is a copy of JDK's sysGetLastErrorString never@3156: // from src/solaris/hpi/src/system_md.c never@3156: never@3156: size_t os::lasterror(char *buf, size_t len) { never@3156: never@3156: if (errno == 0) return 0; never@3156: never@3156: const char *s = ::strerror(errno); never@3156: size_t n = ::strlen(s); never@3156: if (n >= len) { never@3156: n = len - 1; never@3156: } never@3156: ::strncpy(buf, s, n); never@3156: buf[n] = '\0'; never@3156: return n; never@3156: } never@3156: sla@3587: intx os::current_thread_id() { sla@3587: #ifdef __APPLE__ sla@3587: return (intx)::mach_thread_self(); sla@3587: #else sla@3587: return (intx)::pthread_self(); sla@3587: #endif sla@3587: } never@3156: int os::current_process_id() { never@3156: never@3156: // Under the old bsd thread library, bsd gives each thread never@3156: // its own process id. Because of this each thread will return never@3156: // a different pid if this method were to return the result never@3156: // of getpid(2). Bsd provides no api that returns the pid never@3156: // of the launcher thread for the vm. This implementation never@3156: // returns a unique pid, the pid of the launcher thread never@3156: // that starts the vm 'process'. never@3156: never@3156: // Under the NPTL, getpid() returns the same pid as the never@3156: // launcher thread rather than a unique pid per thread. never@3156: // Use gettid() if you want the old pre NPTL behaviour. never@3156: never@3156: // if you are looking for the result of a call to getpid() that never@3156: // returns a unique pid for the calling thread, then look at the never@3156: // OSThread::thread_id() method in osThread_bsd.hpp file never@3156: never@3156: return (int)(_initial_pid ? _initial_pid : getpid()); never@3156: } never@3156: never@3156: // DLL functions never@3156: never@3156: #define JNI_LIB_PREFIX "lib" never@3156: #ifdef __APPLE__ never@3156: #define JNI_LIB_SUFFIX ".dylib" never@3156: #else never@3156: #define JNI_LIB_SUFFIX ".so" never@3156: #endif never@3156: never@3156: const char* os::dll_file_extension() { return JNI_LIB_SUFFIX; } never@3156: never@3156: // This must be hard coded because it's the system's temporary never@3156: // directory not the java application's temp directory, ala java.io.tmpdir. dcubed@3202: #ifdef __APPLE__ dcubed@3202: // macosx has a secure per-user temporary directory dcubed@3202: char temp_path_storage[PATH_MAX]; dcubed@3202: const char* os::get_temp_directory() { dcubed@3202: static char *temp_path = NULL; dcubed@3202: if (temp_path == NULL) { dcubed@3202: int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, temp_path_storage, PATH_MAX); dcubed@3202: if (pathSize == 0 || pathSize > PATH_MAX) { dcubed@3202: strlcpy(temp_path_storage, "/tmp/", sizeof(temp_path_storage)); dcubed@3202: } dcubed@3202: temp_path = temp_path_storage; dcubed@3202: } dcubed@3202: return temp_path; dcubed@3202: } dcubed@3202: #else /* __APPLE__ */ never@3156: const char* os::get_temp_directory() { return "/tmp"; } dcubed@3202: #endif /* __APPLE__ */ never@3156: never@3156: static bool file_exists(const char* filename) { never@3156: struct stat statbuf; never@3156: if (filename == NULL || strlen(filename) == 0) { never@3156: return false; never@3156: } never@3156: return os::stat(filename, &statbuf) == 0; never@3156: } never@3156: bpittore@4261: bool os::dll_build_name(char* buffer, size_t buflen, never@3156: const char* pname, const char* fname) { bpittore@4261: bool retval = false; never@3156: // Copied from libhpi never@3156: const size_t pnamelen = pname ? strlen(pname) : 0; never@3156: bpittore@4261: // Return error on buffer overflow. never@3156: if (pnamelen + strlen(fname) + strlen(JNI_LIB_PREFIX) + strlen(JNI_LIB_SUFFIX) + 2 > buflen) { bpittore@4261: return retval; never@3156: } never@3156: never@3156: if (pnamelen == 0) { never@3156: snprintf(buffer, buflen, JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, fname); bpittore@4261: retval = true; never@3156: } else if (strchr(pname, *os::path_separator()) != NULL) { never@3156: int n; never@3156: char** pelements = split_path(pname, &n); never@3156: for (int i = 0 ; i < n ; i++) { never@3156: // Really shouldn't be NULL, but check can't hurt never@3156: if (pelements[i] == NULL || strlen(pelements[i]) == 0) { never@3156: continue; // skip the empty path values never@3156: } never@3156: snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, never@3156: pelements[i], fname); never@3156: if (file_exists(buffer)) { bpittore@4261: retval = true; never@3156: break; never@3156: } never@3156: } never@3156: // release the storage never@3156: for (int i = 0 ; i < n ; i++) { never@3156: if (pelements[i] != NULL) { zgu@3900: FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal); never@3156: } never@3156: } never@3156: if (pelements != NULL) { zgu@3900: FREE_C_HEAP_ARRAY(char*, pelements, mtInternal); never@3156: } never@3156: } else { never@3156: snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pname, fname); bpittore@4261: retval = true; never@3156: } bpittore@4261: return retval; never@3156: } never@3156: never@3156: const char* os::get_current_directory(char *buf, int buflen) { never@3156: return getcwd(buf, buflen); never@3156: } never@3156: dcubed@4392: // check if addr is inside libjvm.so never@3156: bool os::address_is_in_vm(address addr) { never@3156: static address libjvm_base_addr; never@3156: Dl_info dlinfo; never@3156: never@3156: if (libjvm_base_addr == NULL) { never@3156: dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo); never@3156: libjvm_base_addr = (address)dlinfo.dli_fbase; never@3156: assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm"); never@3156: } never@3156: never@3156: if (dladdr((void *)addr, &dlinfo)) { never@3156: if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true; never@3156: } never@3156: never@3156: return false; never@3156: } never@3156: zgu@3961: zgu@3961: #define MACH_MAXSYMLEN 256 zgu@3961: never@3156: bool os::dll_address_to_function_name(address addr, char *buf, never@3156: int buflen, int *offset) { never@3156: Dl_info dlinfo; zgu@3961: char localbuf[MACH_MAXSYMLEN]; zgu@3961: zgu@3961: // dladdr will find names of dynamic functions only, but does zgu@3961: // it set dli_fbase with mach_header address when it "fails" ? never@3156: if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) { never@3156: if (buf != NULL) { never@3156: if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { never@3156: jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); never@3156: } never@3156: } never@3156: if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; never@3156: return true; never@3156: } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { never@3156: if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), zgu@3432: buf, buflen, offset, dlinfo.dli_fname)) { never@3156: return true; never@3156: } never@3156: } never@3156: zgu@3961: // Handle non-dymanic manually: zgu@3961: if (dlinfo.dli_fbase != NULL && zgu@3961: Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, dlinfo.dli_fbase)) { zgu@3961: if(!Decoder::demangle(localbuf, buf, buflen)) { zgu@3961: jio_snprintf(buf, buflen, "%s", localbuf); zgu@3961: } zgu@3961: return true; zgu@3961: } never@3156: if (buf != NULL) buf[0] = '\0'; never@3156: if (offset != NULL) *offset = -1; never@3156: return false; never@3156: } never@3156: never@3156: // ported from solaris version never@3156: bool os::dll_address_to_library_name(address addr, char* buf, never@3156: int buflen, int* offset) { never@3156: Dl_info dlinfo; never@3156: never@3156: if (dladdr((void*)addr, &dlinfo)){ never@3156: if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); never@3156: if (offset) *offset = addr - (address)dlinfo.dli_fbase; never@3156: return true; never@3156: } else { never@3156: if (buf) buf[0] = '\0'; never@3156: if (offset) *offset = -1; never@3156: return false; never@3156: } never@3156: } sla@4229: sla@4229: // Loads .dll/.so and sla@4229: // in case of error it checks if .dll/.so was built for the sla@4229: // same architecture as Hotspot is running on never@3156: never@3156: #ifdef __APPLE__ never@3156: void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { never@3156: void * result= ::dlopen(filename, RTLD_LAZY); never@3156: if (result != NULL) { never@3156: // Successful loading never@3156: return result; never@3156: } never@3156: never@3156: // Read system error message into ebuf never@3156: ::strncpy(ebuf, ::dlerror(), ebuflen-1); never@3156: ebuf[ebuflen-1]='\0'; never@3156: never@3156: return NULL; never@3156: } never@3156: #else never@3156: void * os::dll_load(const char *filename, char *ebuf, int ebuflen) never@3156: { never@3156: void * result= ::dlopen(filename, RTLD_LAZY); never@3156: if (result != NULL) { never@3156: // Successful loading never@3156: return result; never@3156: } never@3156: never@3156: Elf32_Ehdr elf_head; never@3156: never@3156: // Read system error message into ebuf never@3156: // It may or may not be overwritten below never@3156: ::strncpy(ebuf, ::dlerror(), ebuflen-1); never@3156: ebuf[ebuflen-1]='\0'; never@3156: int diag_msg_max_length=ebuflen-strlen(ebuf); never@3156: char* diag_msg_buf=ebuf+strlen(ebuf); never@3156: never@3156: if (diag_msg_max_length==0) { never@3156: // No more space in ebuf for additional diagnostics message never@3156: return NULL; never@3156: } never@3156: never@3156: never@3156: int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK); never@3156: never@3156: if (file_descriptor < 0) { never@3156: // Can't open library, report dlerror() message never@3156: return NULL; never@3156: } never@3156: never@3156: bool failed_to_read_elf_head= never@3156: (sizeof(elf_head)!= never@3156: (::read(file_descriptor, &elf_head,sizeof(elf_head)))) ; never@3156: never@3156: ::close(file_descriptor); never@3156: if (failed_to_read_elf_head) { never@3156: // file i/o error - report dlerror() msg never@3156: return NULL; never@3156: } never@3156: never@3156: typedef struct { never@3156: Elf32_Half code; // Actual value as defined in elf.h never@3156: Elf32_Half compat_class; // Compatibility of archs at VM's sense never@3156: char elf_class; // 32 or 64 bit never@3156: char endianess; // MSB or LSB never@3156: char* name; // String representation never@3156: } arch_t; never@3156: never@3156: #ifndef EM_486 never@3156: #define EM_486 6 /* Intel 80486 */ never@3156: #endif never@3156: never@3156: #ifndef EM_MIPS_RS3_LE never@3156: #define EM_MIPS_RS3_LE 10 /* MIPS */ never@3156: #endif never@3156: never@3156: #ifndef EM_PPC64 never@3156: #define EM_PPC64 21 /* PowerPC64 */ never@3156: #endif never@3156: never@3156: #ifndef EM_S390 never@3156: #define EM_S390 22 /* IBM System/390 */ never@3156: #endif never@3156: never@3156: #ifndef EM_IA_64 never@3156: #define EM_IA_64 50 /* HP/Intel IA-64 */ never@3156: #endif never@3156: never@3156: #ifndef EM_X86_64 never@3156: #define EM_X86_64 62 /* AMD x86-64 */ never@3156: #endif never@3156: never@3156: static const arch_t arch_array[]={ never@3156: {EM_386, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"}, never@3156: {EM_486, EM_386, ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"}, never@3156: {EM_IA_64, EM_IA_64, ELFCLASS64, ELFDATA2LSB, (char*)"IA 64"}, never@3156: {EM_X86_64, EM_X86_64, ELFCLASS64, ELFDATA2LSB, (char*)"AMD 64"}, never@3156: {EM_SPARC, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"}, never@3156: {EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"}, never@3156: {EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"}, never@3156: {EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"}, never@3156: {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"}, never@3156: {EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"}, never@3156: {EM_S390, EM_S390, ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"}, never@3156: {EM_ALPHA, EM_ALPHA, ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"}, never@3156: {EM_MIPS_RS3_LE, EM_MIPS_RS3_LE, ELFCLASS32, ELFDATA2LSB, (char*)"MIPSel"}, never@3156: {EM_MIPS, EM_MIPS, ELFCLASS32, ELFDATA2MSB, (char*)"MIPS"}, never@3156: {EM_PARISC, EM_PARISC, ELFCLASS32, ELFDATA2MSB, (char*)"PARISC"}, never@3156: {EM_68K, EM_68K, ELFCLASS32, ELFDATA2MSB, (char*)"M68k"} never@3156: }; never@3156: never@3156: #if (defined IA32) never@3156: static Elf32_Half running_arch_code=EM_386; never@3156: #elif (defined AMD64) never@3156: static Elf32_Half running_arch_code=EM_X86_64; never@3156: #elif (defined IA64) never@3156: static Elf32_Half running_arch_code=EM_IA_64; never@3156: #elif (defined __sparc) && (defined _LP64) never@3156: static Elf32_Half running_arch_code=EM_SPARCV9; never@3156: #elif (defined __sparc) && (!defined _LP64) never@3156: static Elf32_Half running_arch_code=EM_SPARC; never@3156: #elif (defined __powerpc64__) never@3156: static Elf32_Half running_arch_code=EM_PPC64; never@3156: #elif (defined __powerpc__) never@3156: static Elf32_Half running_arch_code=EM_PPC; never@3156: #elif (defined ARM) never@3156: static Elf32_Half running_arch_code=EM_ARM; never@3156: #elif (defined S390) never@3156: static Elf32_Half running_arch_code=EM_S390; never@3156: #elif (defined ALPHA) never@3156: static Elf32_Half running_arch_code=EM_ALPHA; never@3156: #elif (defined MIPSEL) never@3156: static Elf32_Half running_arch_code=EM_MIPS_RS3_LE; never@3156: #elif (defined PARISC) never@3156: static Elf32_Half running_arch_code=EM_PARISC; never@3156: #elif (defined MIPS) never@3156: static Elf32_Half running_arch_code=EM_MIPS; never@3156: #elif (defined M68K) never@3156: static Elf32_Half running_arch_code=EM_68K; never@3156: #else never@3156: #error Method os::dll_load requires that one of following is defined:\ never@3156: IA32, AMD64, IA64, __sparc, __powerpc__, ARM, S390, ALPHA, MIPS, MIPSEL, PARISC, M68K never@3156: #endif never@3156: never@3156: // Identify compatability class for VM's architecture and library's architecture never@3156: // Obtain string descriptions for architectures never@3156: never@3156: arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL}; never@3156: int running_arch_index=-1; never@3156: never@3156: for (unsigned int i=0 ; i < ARRAY_SIZE(arch_array) ; i++ ) { never@3156: if (running_arch_code == arch_array[i].code) { never@3156: running_arch_index = i; never@3156: } never@3156: if (lib_arch.code == arch_array[i].code) { never@3156: lib_arch.compat_class = arch_array[i].compat_class; never@3156: lib_arch.name = arch_array[i].name; never@3156: } never@3156: } never@3156: never@3156: assert(running_arch_index != -1, never@3156: "Didn't find running architecture code (running_arch_code) in arch_array"); never@3156: if (running_arch_index == -1) { never@3156: // Even though running architecture detection failed never@3156: // we may still continue with reporting dlerror() message never@3156: return NULL; never@3156: } never@3156: never@3156: if (lib_arch.endianess != arch_array[running_arch_index].endianess) { never@3156: ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)"); never@3156: return NULL; never@3156: } never@3156: never@3156: #ifndef S390 never@3156: if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) { never@3156: ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: architecture word width mismatch)"); never@3156: return NULL; never@3156: } never@3156: #endif // !S390 never@3156: never@3156: if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) { never@3156: if ( lib_arch.name!=NULL ) { never@3156: ::snprintf(diag_msg_buf, diag_msg_max_length-1, never@3156: " (Possible cause: can't load %s-bit .so on a %s-bit platform)", never@3156: lib_arch.name, arch_array[running_arch_index].name); never@3156: } else { never@3156: ::snprintf(diag_msg_buf, diag_msg_max_length-1, never@3156: " (Possible cause: can't load this .so (machine code=0x%x) on a %s-bit platform)", never@3156: lib_arch.code, never@3156: arch_array[running_arch_index].name); never@3156: } never@3156: } never@3156: never@3156: return NULL; never@3156: } never@3156: #endif /* !__APPLE__ */ never@3156: never@3156: // XXX: Do we need a lock around this as per Linux? never@3156: void* os::dll_lookup(void* handle, const char* name) { never@3156: return dlsym(handle, name); never@3156: } never@3156: never@3156: never@3156: static bool _print_ascii_file(const char* filename, outputStream* st) { never@3156: int fd = ::open(filename, O_RDONLY); never@3156: if (fd == -1) { never@3156: return false; never@3156: } never@3156: never@3156: char buf[32]; never@3156: int bytes; never@3156: while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) { never@3156: st->print_raw(buf, bytes); never@3156: } never@3156: never@3156: ::close(fd); never@3156: never@3156: return true; never@3156: } never@3156: never@3156: void os::print_dll_info(outputStream *st) { never@3156: st->print_cr("Dynamic libraries:"); never@3156: #ifdef RTLD_DI_LINKMAP never@3156: Dl_info dli; never@3156: void *handle; never@3156: Link_map *map; never@3156: Link_map *p; never@3156: never@3156: if (!dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli)) { never@3156: st->print_cr("Error: Cannot print dynamic libraries."); never@3156: return; never@3156: } never@3156: handle = dlopen(dli.dli_fname, RTLD_LAZY); never@3156: if (handle == NULL) { never@3156: st->print_cr("Error: Cannot print dynamic libraries."); never@3156: return; never@3156: } never@3156: dlinfo(handle, RTLD_DI_LINKMAP, &map); never@3156: if (map == NULL) { never@3156: st->print_cr("Error: Cannot print dynamic libraries."); never@3156: return; never@3156: } never@3156: never@3156: while (map->l_prev != NULL) never@3156: map = map->l_prev; never@3156: never@3156: while (map != NULL) { never@3156: st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name); never@3156: map = map->l_next; never@3156: } never@3156: never@3156: dlclose(handle); never@3156: #elif defined(__APPLE__) never@3156: uint32_t count; never@3156: uint32_t i; never@3156: never@3156: count = _dyld_image_count(); never@3156: for (i = 1; i < count; i++) { never@3156: const char *name = _dyld_get_image_name(i); never@3156: intptr_t slide = _dyld_get_image_vmaddr_slide(i); never@3156: st->print_cr(PTR_FORMAT " \t%s", slide, name); never@3156: } never@3156: #else never@3156: st->print_cr("Error: Cannot print dynamic libraries."); never@3156: #endif never@3156: } never@3156: nloodin@3783: void os::print_os_info_brief(outputStream* st) { nloodin@3783: st->print("Bsd"); nloodin@3783: nloodin@3783: os::Posix::print_uname_info(st); nloodin@3783: } never@3156: never@3156: void os::print_os_info(outputStream* st) { never@3156: st->print("OS:"); nloodin@3783: st->print("Bsd"); nloodin@3783: nloodin@3783: os::Posix::print_uname_info(st); nloodin@3783: nloodin@3783: os::Posix::print_rlimit_info(st); nloodin@3783: nloodin@3783: os::Posix::print_load_average(st); never@3156: } never@3156: never@3156: void os::pd_print_cpu_info(outputStream* st) { never@3156: // Nothing to do for now. never@3156: } never@3156: never@3156: void os::print_memory_info(outputStream* st) { never@3156: never@3156: st->print("Memory:"); never@3156: st->print(" %dk page", os::vm_page_size()>>10); never@3156: never@3156: st->print(", physical " UINT64_FORMAT "k", never@3156: os::physical_memory() >> 10); never@3156: st->print("(" UINT64_FORMAT "k free)", never@3156: os::available_memory() >> 10); never@3156: st->cr(); never@3156: never@3156: // meminfo never@3156: st->print("\n/proc/meminfo:\n"); never@3156: _print_ascii_file("/proc/meminfo", st); never@3156: st->cr(); never@3156: } never@3156: never@3156: // Taken from /usr/include/bits/siginfo.h Supposed to be architecture specific never@3156: // but they're the same for all the bsd arch that we support never@3156: // and they're the same for solaris but there's no common place to put this. never@3156: const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR", never@3156: "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG", never@3156: "ILL_COPROC", "ILL_BADSTK" }; never@3156: never@3156: const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV", never@3156: "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES", never@3156: "FPE_FLTINV", "FPE_FLTSUB", "FPE_FLTDEN" }; never@3156: never@3156: const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" }; never@3156: never@3156: const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" }; never@3156: never@3156: void os::print_siginfo(outputStream* st, void* siginfo) { never@3156: st->print("siginfo:"); never@3156: never@3156: const int buflen = 100; never@3156: char buf[buflen]; never@3156: siginfo_t *si = (siginfo_t*)siginfo; never@3156: st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen)); never@3156: if (si->si_errno != 0 && strerror_r(si->si_errno, buf, buflen) == 0) { never@3156: st->print("si_errno=%s", buf); never@3156: } else { never@3156: st->print("si_errno=%d", si->si_errno); never@3156: } never@3156: const int c = si->si_code; never@3156: assert(c > 0, "unexpected si_code"); never@3156: switch (si->si_signo) { never@3156: case SIGILL: never@3156: st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]); never@3156: st->print(", si_addr=" PTR_FORMAT, si->si_addr); never@3156: break; never@3156: case SIGFPE: never@3156: st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]); never@3156: st->print(", si_addr=" PTR_FORMAT, si->si_addr); never@3156: break; never@3156: case SIGSEGV: never@3156: st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]); never@3156: st->print(", si_addr=" PTR_FORMAT, si->si_addr); never@3156: break; never@3156: case SIGBUS: never@3156: st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]); never@3156: st->print(", si_addr=" PTR_FORMAT, si->si_addr); never@3156: break; never@3156: default: never@3156: st->print(", si_code=%d", si->si_code); never@3156: // no si_addr never@3156: } never@3156: never@3156: if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && never@3156: UseSharedSpaces) { never@3156: FileMapInfo* mapinfo = FileMapInfo::current_info(); never@3156: if (mapinfo->is_in_shared_space(si->si_addr)) { never@3156: st->print("\n\nError accessing class data sharing archive." \ never@3156: " Mapped file inaccessible during execution, " \ never@3156: " possible disk/network problem."); never@3156: } never@3156: } never@3156: st->cr(); never@3156: } never@3156: never@3156: never@3156: static void print_signal_handler(outputStream* st, int sig, never@3156: char* buf, size_t buflen); never@3156: never@3156: void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { never@3156: st->print_cr("Signal Handlers:"); never@3156: print_signal_handler(st, SIGSEGV, buf, buflen); never@3156: print_signal_handler(st, SIGBUS , buf, buflen); never@3156: print_signal_handler(st, SIGFPE , buf, buflen); never@3156: print_signal_handler(st, SIGPIPE, buf, buflen); never@3156: print_signal_handler(st, SIGXFSZ, buf, buflen); never@3156: print_signal_handler(st, SIGILL , buf, buflen); never@3156: print_signal_handler(st, INTERRUPT_SIGNAL, buf, buflen); never@3156: print_signal_handler(st, SR_signum, buf, buflen); never@3156: print_signal_handler(st, SHUTDOWN1_SIGNAL, buf, buflen); never@3156: print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); never@3156: print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen); never@3156: print_signal_handler(st, BREAK_SIGNAL, buf, buflen); never@3156: } never@3156: never@3156: static char saved_jvm_path[MAXPATHLEN] = {0}; never@3156: dcubed@4392: // Find the full path to the current module, libjvm never@3156: void os::jvm_path(char *buf, jint buflen) { never@3156: // Error checking. never@3156: if (buflen < MAXPATHLEN) { never@3156: assert(false, "must use a large-enough buffer"); never@3156: buf[0] = '\0'; never@3156: return; never@3156: } never@3156: // Lazy resolve the path to current module. never@3156: if (saved_jvm_path[0] != 0) { never@3156: strcpy(buf, saved_jvm_path); never@3156: return; never@3156: } never@3156: never@3156: char dli_fname[MAXPATHLEN]; never@3156: bool ret = dll_address_to_library_name( never@3156: CAST_FROM_FN_PTR(address, os::jvm_path), never@3156: dli_fname, sizeof(dli_fname), NULL); never@3156: assert(ret != 0, "cannot locate libjvm"); never@3156: char *rp = realpath(dli_fname, buf); never@3156: if (rp == NULL) never@3156: return; never@3156: never@3156: if (Arguments::created_by_gamma_launcher()) { never@3156: // Support for the gamma launcher. Typical value for buf is phh@3473: // "/jre/lib///libjvm". If "/jre/lib/" appears at never@3156: // the right place in the string, then assume we are installed in a JDK and phh@3473: // we're done. Otherwise, check for a JAVA_HOME environment variable and phh@3473: // construct a path to the JVM being overridden. phh@3473: never@3156: const char *p = buf + strlen(buf) - 1; never@3156: for (int count = 0; p > buf && count < 5; ++count) { never@3156: for (--p; p > buf && *p != '/'; --p) never@3156: /* empty */ ; never@3156: } never@3156: never@3156: if (strncmp(p, "/jre/lib/", 9) != 0) { never@3156: // Look for JAVA_HOME in the environment. never@3156: char* java_home_var = ::getenv("JAVA_HOME"); never@3156: if (java_home_var != NULL && java_home_var[0] != 0) { never@3156: char* jrelib_p; never@3156: int len; never@3156: dcubed@4392: // Check the current module name "libjvm" never@3156: p = strrchr(buf, '/'); never@3156: assert(strstr(p, "/libjvm") == p, "invalid library name"); never@3156: never@3156: rp = realpath(java_home_var, buf); never@3156: if (rp == NULL) never@3156: return; never@3156: never@3156: // determine if this is a legacy image or modules image never@3156: // modules image doesn't have "jre" subdirectory never@3156: len = strlen(buf); never@3156: jrelib_p = buf + len; phh@3473: phh@3473: // Add the appropriate library subdir phh@3473: snprintf(jrelib_p, buflen-len, "/jre/lib"); never@3156: if (0 != access(buf, F_OK)) { phh@3473: snprintf(jrelib_p, buflen-len, "/lib"); never@3156: } never@3156: phh@3473: // Add the appropriate client or server subdir phh@3473: len = strlen(buf); phh@3473: jrelib_p = buf + len; phh@3473: snprintf(jrelib_p, buflen-len, "/%s", COMPILER_VARIANT); phh@3473: if (0 != access(buf, F_OK)) { phh@3473: snprintf(jrelib_p, buflen-len, ""); phh@3473: } phh@3473: phh@3473: // If the path exists within JAVA_HOME, add the JVM library name phh@3473: // to complete the path to JVM being overridden. Otherwise fallback phh@3473: // to the path to the current library. never@3156: if (0 == access(buf, F_OK)) { dcubed@4392: // Use current module name "libjvm" never@3156: len = strlen(buf); dcubed@4392: snprintf(buf + len, buflen-len, "/libjvm%s", JNI_LIB_SUFFIX); never@3156: } else { phh@3473: // Fall back to path of current library never@3156: rp = realpath(dli_fname, buf); never@3156: if (rp == NULL) never@3156: return; never@3156: } never@3156: } never@3156: } never@3156: } never@3156: never@3156: strcpy(saved_jvm_path, buf); never@3156: } never@3156: never@3156: void os::print_jni_name_prefix_on(outputStream* st, int args_size) { never@3156: // no prefix required, not even "_" never@3156: } never@3156: never@3156: void os::print_jni_name_suffix_on(outputStream* st, int args_size) { never@3156: // no suffix required never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // sun.misc.Signal support never@3156: never@3156: static volatile jint sigint_count = 0; never@3156: never@3156: static void never@3156: UserHandler(int sig, void *siginfo, void *context) { never@3156: // 4511530 - sem_post is serialized and handled by the manager thread. When never@3156: // the program is interrupted by Ctrl-C, SIGINT is sent to every thread. We never@3156: // don't want to flood the manager thread with sem_post requests. never@3156: if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) never@3156: return; never@3156: never@3156: // Ctrl-C is pressed during error reporting, likely because the error never@3156: // handler fails to abort. Let VM die immediately. never@3156: if (sig == SIGINT && is_error_reported()) { never@3156: os::die(); never@3156: } never@3156: never@3156: os::signal_notify(sig); never@3156: } never@3156: never@3156: void* os::user_handler() { never@3156: return CAST_FROM_FN_PTR(void*, UserHandler); never@3156: } never@3156: never@3156: extern "C" { never@3156: typedef void (*sa_handler_t)(int); never@3156: typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); never@3156: } never@3156: never@3156: void* os::signal(int signal_number, void* handler) { never@3156: struct sigaction sigAct, oldSigAct; never@3156: never@3156: sigfillset(&(sigAct.sa_mask)); never@3156: sigAct.sa_flags = SA_RESTART|SA_SIGINFO; never@3156: sigAct.sa_handler = CAST_TO_FN_PTR(sa_handler_t, handler); never@3156: never@3156: if (sigaction(signal_number, &sigAct, &oldSigAct)) { never@3156: // -1 means registration failed never@3156: return (void *)-1; never@3156: } never@3156: never@3156: return CAST_FROM_FN_PTR(void*, oldSigAct.sa_handler); never@3156: } never@3156: never@3156: void os::signal_raise(int signal_number) { never@3156: ::raise(signal_number); never@3156: } never@3156: never@3156: /* never@3156: * The following code is moved from os.cpp for making this never@3156: * code platform specific, which it is by its very nature. never@3156: */ never@3156: never@3156: // Will be modified when max signal is changed to be dynamic never@3156: int os::sigexitnum_pd() { never@3156: return NSIG; never@3156: } never@3156: never@3156: // a counter for each possible signal value never@3156: static volatile jint pending_signals[NSIG+1] = { 0 }; never@3156: never@3156: // Bsd(POSIX) specific hand shaking semaphore. never@3156: #ifdef __APPLE__ never@3156: static semaphore_t sig_sem; never@3156: #define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value) never@3156: #define SEM_WAIT(sem) semaphore_wait(sem); never@3156: #define SEM_POST(sem) semaphore_signal(sem); never@3156: #else never@3156: static sem_t sig_sem; never@3156: #define SEM_INIT(sem, value) sem_init(&sem, 0, value) never@3156: #define SEM_WAIT(sem) sem_wait(&sem); never@3156: #define SEM_POST(sem) sem_post(&sem); never@3156: #endif never@3156: never@3156: void os::signal_init_pd() { never@3156: // Initialize signal structures never@3156: ::memset((void*)pending_signals, 0, sizeof(pending_signals)); never@3156: never@3156: // Initialize signal semaphore never@3156: ::SEM_INIT(sig_sem, 0); never@3156: } never@3156: never@3156: void os::signal_notify(int sig) { never@3156: Atomic::inc(&pending_signals[sig]); never@3156: ::SEM_POST(sig_sem); never@3156: } never@3156: never@3156: static int check_pending_signals(bool wait) { never@3156: Atomic::store(0, &sigint_count); never@3156: for (;;) { never@3156: for (int i = 0; i < NSIG + 1; i++) { never@3156: jint n = pending_signals[i]; never@3156: if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) { never@3156: return i; never@3156: } never@3156: } never@3156: if (!wait) { never@3156: return -1; never@3156: } never@3156: JavaThread *thread = JavaThread::current(); never@3156: ThreadBlockInVM tbivm(thread); never@3156: never@3156: bool threadIsSuspended; never@3156: do { never@3156: thread->set_suspend_equivalent(); never@3156: // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() never@3156: ::SEM_WAIT(sig_sem); never@3156: never@3156: // were we externally suspended while we were waiting? never@3156: threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); never@3156: if (threadIsSuspended) { never@3156: // never@3156: // The semaphore has been incremented, but while we were waiting never@3156: // another thread suspended us. We don't want to continue running never@3156: // while suspended because that would surprise the thread that never@3156: // suspended us. never@3156: // never@3156: ::SEM_POST(sig_sem); never@3156: never@3156: thread->java_suspend_self(); never@3156: } never@3156: } while (threadIsSuspended); never@3156: } never@3156: } never@3156: never@3156: int os::signal_lookup() { never@3156: return check_pending_signals(false); never@3156: } never@3156: never@3156: int os::signal_wait() { never@3156: return check_pending_signals(true); never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // Virtual Memory never@3156: never@3156: int os::vm_page_size() { never@3156: // Seems redundant as all get out never@3156: assert(os::Bsd::page_size() != -1, "must call os::init"); never@3156: return os::Bsd::page_size(); never@3156: } never@3156: never@3156: // Solaris allocates memory by pages. never@3156: int os::vm_allocation_granularity() { never@3156: assert(os::Bsd::page_size() != -1, "must call os::init"); never@3156: return os::Bsd::page_size(); never@3156: } never@3156: never@3156: // Rationale behind this function: never@3156: // current (Mon Apr 25 20:12:18 MSD 2005) oprofile drops samples without executable never@3156: // mapping for address (see lookup_dcookie() in the kernel module), thus we cannot get never@3156: // samples for JITted code. Here we create private executable mapping over the code cache never@3156: // and then we can use standard (well, almost, as mapping can change) way to provide never@3156: // info for the reporting script by storing timestamp and location of symbol never@3156: void bsd_wrap_code(char* base, size_t size) { never@3156: static volatile jint cnt = 0; never@3156: never@3156: if (!UseOprofile) { never@3156: return; never@3156: } never@3156: never@3156: char buf[PATH_MAX + 1]; never@3156: int num = Atomic::add(1, &cnt); never@3156: never@3156: snprintf(buf, PATH_MAX + 1, "%s/hs-vm-%d-%d", never@3156: os::get_temp_directory(), os::current_process_id(), num); never@3156: unlink(buf); never@3156: never@3156: int fd = ::open(buf, O_CREAT | O_RDWR, S_IRWXU); never@3156: never@3156: if (fd != -1) { never@3156: off_t rv = ::lseek(fd, size-2, SEEK_SET); never@3156: if (rv != (off_t)-1) { never@3156: if (::write(fd, "", 1) == 1) { never@3156: mmap(base, size, never@3156: PROT_READ|PROT_WRITE|PROT_EXEC, never@3156: MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0); never@3156: } never@3156: } never@3156: ::close(fd); never@3156: unlink(buf); never@3156: } never@3156: } never@3156: never@3156: // NOTE: Bsd kernel does not really reserve the pages for us. never@3156: // All it does is to check if there are enough free pages never@3156: // left at the time of mmap(). This could be a potential never@3156: // problem. zgu@3900: bool os::pd_commit_memory(char* addr, size_t size, bool exec) { never@3156: int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; never@3156: #ifdef __OpenBSD__ never@3156: // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD never@3156: return ::mprotect(addr, size, prot) == 0; never@3156: #else never@3156: uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, never@3156: MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); never@3156: return res != (uintptr_t) MAP_FAILED; never@3156: #endif never@3156: } never@3156: never@3156: zgu@3900: bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, never@3156: bool exec) { never@3156: return commit_memory(addr, size, exec); never@3156: } never@3156: zgu@3900: void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { never@3156: } never@3156: zgu@3900: void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { never@3156: ::madvise(addr, bytes, MADV_DONTNEED); never@3156: } never@3156: never@3156: void os::numa_make_global(char *addr, size_t bytes) { never@3156: } never@3156: never@3156: void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { never@3156: } never@3156: never@3156: bool os::numa_topology_changed() { return false; } never@3156: never@3156: size_t os::numa_get_groups_num() { never@3156: return 1; never@3156: } never@3156: never@3156: int os::numa_get_group_id() { never@3156: return 0; never@3156: } never@3156: never@3156: size_t os::numa_get_leaf_groups(int *ids, size_t size) { never@3156: if (size > 0) { never@3156: ids[0] = 0; never@3156: return 1; never@3156: } never@3156: return 0; never@3156: } never@3156: never@3156: bool os::get_page_info(char *start, page_info* info) { never@3156: return false; never@3156: } never@3156: never@3156: char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) { never@3156: return end; never@3156: } never@3156: never@3156: zgu@3900: bool os::pd_uncommit_memory(char* addr, size_t size) { never@3156: #ifdef __OpenBSD__ never@3156: // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD never@3156: return ::mprotect(addr, size, PROT_NONE) == 0; never@3156: #else never@3156: uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE, never@3156: MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0); never@3156: return res != (uintptr_t) MAP_FAILED; never@3156: #endif never@3156: } never@3156: zgu@3900: bool os::pd_create_stack_guard_pages(char* addr, size_t size) { never@3156: return os::commit_memory(addr, size); never@3156: } never@3156: never@3156: // If this is a growable mapping, remove the guard pages entirely by never@3156: // munmap()ping them. If not, just call uncommit_memory(). never@3156: bool os::remove_stack_guard_pages(char* addr, size_t size) { never@3156: return os::uncommit_memory(addr, size); never@3156: } never@3156: never@3156: static address _highest_vm_reserved_address = NULL; never@3156: never@3156: // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory never@3156: // at 'requested_addr'. If there are existing memory mappings at the same never@3156: // location, however, they will be overwritten. If 'fixed' is false, never@3156: // 'requested_addr' is only treated as a hint, the return value may or never@3156: // may not start from the requested address. Unlike Bsd mmap(), this never@3156: // function returns NULL to indicate failure. never@3156: static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) { never@3156: char * addr; never@3156: int flags; never@3156: never@3156: flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS; never@3156: if (fixed) { never@3156: assert((uintptr_t)requested_addr % os::Bsd::page_size() == 0, "unaligned address"); never@3156: flags |= MAP_FIXED; never@3156: } never@3156: never@3156: // Map uncommitted pages PROT_READ and PROT_WRITE, change access never@3156: // to PROT_EXEC if executable when we commit the page. never@3156: addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE, never@3156: flags, -1, 0); never@3156: never@3156: if (addr != MAP_FAILED) { never@3156: // anon_mmap() should only get called during VM initialization, never@3156: // don't need lock (actually we can skip locking even it can be called never@3156: // from multiple threads, because _highest_vm_reserved_address is just a never@3156: // hint about the upper limit of non-stack memory regions.) never@3156: if ((address)addr + bytes > _highest_vm_reserved_address) { never@3156: _highest_vm_reserved_address = (address)addr + bytes; never@3156: } never@3156: } never@3156: never@3156: return addr == MAP_FAILED ? NULL : addr; never@3156: } never@3156: never@3156: // Don't update _highest_vm_reserved_address, because there might be memory never@3156: // regions above addr + size. If so, releasing a memory region only creates never@3156: // a hole in the address space, it doesn't help prevent heap-stack collision. never@3156: // never@3156: static int anon_munmap(char * addr, size_t size) { never@3156: return ::munmap(addr, size) == 0; never@3156: } never@3156: zgu@3900: char* os::pd_reserve_memory(size_t bytes, char* requested_addr, never@3156: size_t alignment_hint) { never@3156: return anon_mmap(requested_addr, bytes, (requested_addr != NULL)); never@3156: } never@3156: zgu@3900: bool os::pd_release_memory(char* addr, size_t size) { never@3156: return anon_munmap(addr, size); never@3156: } never@3156: never@3156: static address highest_vm_reserved_address() { never@3156: return _highest_vm_reserved_address; never@3156: } never@3156: never@3156: static bool bsd_mprotect(char* addr, size_t size, int prot) { never@3156: // Bsd wants the mprotect address argument to be page aligned. never@3156: char* bottom = (char*)align_size_down((intptr_t)addr, os::Bsd::page_size()); never@3156: never@3156: // According to SUSv3, mprotect() should only be used with mappings never@3156: // established by mmap(), and mmap() always maps whole pages. Unaligned never@3156: // 'addr' likely indicates problem in the VM (e.g. trying to change never@3156: // protection of malloc'ed or statically allocated memory). Check the never@3156: // caller if you hit this assert. never@3156: assert(addr == bottom, "sanity check"); never@3156: never@3156: size = align_size_up(pointer_delta(addr, bottom, 1) + size, os::Bsd::page_size()); never@3156: return ::mprotect(bottom, size, prot) == 0; never@3156: } never@3156: never@3156: // Set protections specified never@3156: bool os::protect_memory(char* addr, size_t bytes, ProtType prot, never@3156: bool is_committed) { never@3156: unsigned int p = 0; never@3156: switch (prot) { never@3156: case MEM_PROT_NONE: p = PROT_NONE; break; never@3156: case MEM_PROT_READ: p = PROT_READ; break; never@3156: case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break; never@3156: case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break; never@3156: default: never@3156: ShouldNotReachHere(); never@3156: } never@3156: // is_committed is unused. never@3156: return bsd_mprotect(addr, bytes, p); never@3156: } never@3156: never@3156: bool os::guard_memory(char* addr, size_t size) { never@3156: return bsd_mprotect(addr, size, PROT_NONE); never@3156: } never@3156: never@3156: bool os::unguard_memory(char* addr, size_t size) { never@3156: return bsd_mprotect(addr, size, PROT_READ|PROT_WRITE); never@3156: } never@3156: never@3156: bool os::Bsd::hugetlbfs_sanity_check(bool warn, size_t page_size) { sla@4229: return false; never@3156: } never@3156: never@3156: /* never@3156: * Set the coredump_filter bits to include largepages in core dump (bit 6) never@3156: * never@3156: * From the coredump_filter documentation: never@3156: * never@3156: * - (bit 0) anonymous private memory never@3156: * - (bit 1) anonymous shared memory never@3156: * - (bit 2) file-backed private memory never@3156: * - (bit 3) file-backed shared memory never@3156: * - (bit 4) ELF header pages in file-backed private memory areas (it is never@3156: * effective only if the bit 2 is cleared) never@3156: * - (bit 5) hugetlb private memory never@3156: * - (bit 6) hugetlb shared memory never@3156: */ never@3156: static void set_coredump_filter(void) { never@3156: FILE *f; never@3156: long cdm; never@3156: never@3156: if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) { never@3156: return; never@3156: } never@3156: never@3156: if (fscanf(f, "%lx", &cdm) != 1) { never@3156: fclose(f); never@3156: return; never@3156: } never@3156: never@3156: rewind(f); never@3156: never@3156: if ((cdm & LARGEPAGES_BIT) == 0) { never@3156: cdm |= LARGEPAGES_BIT; never@3156: fprintf(f, "%#lx", cdm); never@3156: } never@3156: never@3156: fclose(f); never@3156: } never@3156: never@3156: // Large page support never@3156: never@3156: static size_t _large_page_size = 0; never@3156: never@3156: void os::large_page_init() { never@3156: } never@3156: never@3156: never@3156: char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) { never@3156: // "exec" is passed in but not used. Creating the shared image for never@3156: // the code cache doesn't have an SHM_X executable permission to check. never@3156: assert(UseLargePages && UseSHM, "only for SHM large pages"); never@3156: never@3156: key_t key = IPC_PRIVATE; never@3156: char *addr; never@3156: never@3156: bool warn_on_failure = UseLargePages && never@3156: (!FLAG_IS_DEFAULT(UseLargePages) || never@3156: !FLAG_IS_DEFAULT(LargePageSizeInBytes) never@3156: ); never@3156: char msg[128]; never@3156: never@3156: // Create a large shared memory region to attach to based on size. never@3156: // Currently, size is the total size of the heap never@3156: int shmid = shmget(key, bytes, IPC_CREAT|SHM_R|SHM_W); never@3156: if (shmid == -1) { never@3156: // Possible reasons for shmget failure: never@3156: // 1. shmmax is too small for Java heap. never@3156: // > check shmmax value: cat /proc/sys/kernel/shmmax never@3156: // > increase shmmax value: echo "0xffffffff" > /proc/sys/kernel/shmmax never@3156: // 2. not enough large page memory. never@3156: // > check available large pages: cat /proc/meminfo never@3156: // > increase amount of large pages: never@3156: // echo new_value > /proc/sys/vm/nr_hugepages never@3156: // Note 1: different Bsd may use different name for this property, never@3156: // e.g. on Redhat AS-3 it is "hugetlb_pool". never@3156: // Note 2: it's possible there's enough physical memory available but never@3156: // they are so fragmented after a long run that they can't never@3156: // coalesce into large pages. Try to reserve large pages when never@3156: // the system is still "fresh". never@3156: if (warn_on_failure) { never@3156: jio_snprintf(msg, sizeof(msg), "Failed to reserve shared memory (errno = %d).", errno); never@3156: warning(msg); never@3156: } never@3156: return NULL; never@3156: } never@3156: never@3156: // attach to the region never@3156: addr = (char*)shmat(shmid, req_addr, 0); never@3156: int err = errno; never@3156: never@3156: // Remove shmid. If shmat() is successful, the actual shared memory segment never@3156: // will be deleted when it's detached by shmdt() or when the process never@3156: // terminates. If shmat() is not successful this will remove the shared never@3156: // segment immediately. never@3156: shmctl(shmid, IPC_RMID, NULL); never@3156: never@3156: if ((intptr_t)addr == -1) { never@3156: if (warn_on_failure) { never@3156: jio_snprintf(msg, sizeof(msg), "Failed to attach shared memory (errno = %d).", err); never@3156: warning(msg); never@3156: } never@3156: return NULL; never@3156: } never@3156: zgu@4711: // The memory is committed zgu@4711: address pc = CALLER_PC; zgu@4711: MemTracker::record_virtual_memory_reserve((address)addr, bytes, pc); zgu@4711: MemTracker::record_virtual_memory_commit((address)addr, bytes, pc); zgu@4711: never@3156: return addr; never@3156: } never@3156: never@3156: bool os::release_memory_special(char* base, size_t bytes) { never@3156: // detaching the SHM segment will also delete it, see reserve_memory_special() never@3156: int rslt = shmdt(base); zgu@4711: if (rslt == 0) { zgu@4711: MemTracker::record_virtual_memory_uncommit((address)base, bytes); zgu@4711: MemTracker::record_virtual_memory_release((address)base, bytes); zgu@4711: return true; zgu@4711: } else { zgu@4711: return false; zgu@4711: } zgu@4711: never@3156: } never@3156: never@3156: size_t os::large_page_size() { never@3156: return _large_page_size; never@3156: } never@3156: never@3156: // HugeTLBFS allows application to commit large page memory on demand; never@3156: // with SysV SHM the entire memory region must be allocated as shared never@3156: // memory. never@3156: bool os::can_commit_large_page_memory() { never@3156: return UseHugeTLBFS; never@3156: } never@3156: never@3156: bool os::can_execute_large_page_memory() { never@3156: return UseHugeTLBFS; never@3156: } never@3156: never@3156: // Reserve memory at an arbitrary address, only if that area is never@3156: // available (and not reserved for something else). never@3156: zgu@3900: char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { never@3156: const int max_tries = 10; never@3156: char* base[max_tries]; never@3156: size_t size[max_tries]; never@3156: const size_t gap = 0x000000; never@3156: never@3156: // Assert only that the size is a multiple of the page size, since never@3156: // that's all that mmap requires, and since that's all we really know never@3156: // about at this low abstraction level. If we need higher alignment, never@3156: // we can either pass an alignment to this method or verify alignment never@3156: // in one of the methods further up the call chain. See bug 5044738. never@3156: assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block"); never@3156: never@3156: // Repeatedly allocate blocks until the block is allocated at the never@3156: // right spot. Give up after max_tries. Note that reserve_memory() will never@3156: // automatically update _highest_vm_reserved_address if the call is never@3156: // successful. The variable tracks the highest memory address every reserved never@3156: // by JVM. It is used to detect heap-stack collision if running with never@3156: // fixed-stack BsdThreads. Because here we may attempt to reserve more never@3156: // space than needed, it could confuse the collision detecting code. To never@3156: // solve the problem, save current _highest_vm_reserved_address and never@3156: // calculate the correct value before return. never@3156: address old_highest = _highest_vm_reserved_address; never@3156: never@3156: // Bsd mmap allows caller to pass an address as hint; give it a try first, never@3156: // if kernel honors the hint then we can return immediately. never@3156: char * addr = anon_mmap(requested_addr, bytes, false); never@3156: if (addr == requested_addr) { never@3156: return requested_addr; never@3156: } never@3156: never@3156: if (addr != NULL) { never@3156: // mmap() is successful but it fails to reserve at the requested address never@3156: anon_munmap(addr, bytes); never@3156: } never@3156: never@3156: int i; never@3156: for (i = 0; i < max_tries; ++i) { never@3156: base[i] = reserve_memory(bytes); never@3156: never@3156: if (base[i] != NULL) { never@3156: // Is this the block we wanted? never@3156: if (base[i] == requested_addr) { never@3156: size[i] = bytes; never@3156: break; never@3156: } never@3156: never@3156: // Does this overlap the block we wanted? Give back the overlapped never@3156: // parts and try again. never@3156: never@3156: size_t top_overlap = requested_addr + (bytes + gap) - base[i]; never@3156: if (top_overlap >= 0 && top_overlap < bytes) { never@3156: unmap_memory(base[i], top_overlap); never@3156: base[i] += top_overlap; never@3156: size[i] = bytes - top_overlap; never@3156: } else { never@3156: size_t bottom_overlap = base[i] + bytes - requested_addr; never@3156: if (bottom_overlap >= 0 && bottom_overlap < bytes) { never@3156: unmap_memory(requested_addr, bottom_overlap); never@3156: size[i] = bytes - bottom_overlap; never@3156: } else { never@3156: size[i] = bytes; never@3156: } never@3156: } never@3156: } never@3156: } never@3156: never@3156: // Give back the unused reserved pieces. never@3156: never@3156: for (int j = 0; j < i; ++j) { never@3156: if (base[j] != NULL) { never@3156: unmap_memory(base[j], size[j]); never@3156: } never@3156: } never@3156: never@3156: if (i < max_tries) { never@3156: _highest_vm_reserved_address = MAX2(old_highest, (address)requested_addr + bytes); never@3156: return requested_addr; never@3156: } else { never@3156: _highest_vm_reserved_address = old_highest; never@3156: return NULL; never@3156: } never@3156: } never@3156: never@3156: size_t os::read(int fd, void *buf, unsigned int nBytes) { never@3156: RESTARTABLE_RETURN_INT(::read(fd, buf, nBytes)); never@3156: } never@3156: never@3156: // TODO-FIXME: reconcile Solaris' os::sleep with the bsd variation. never@3156: // Solaris uses poll(), bsd uses park(). never@3156: // Poll() is likely a better choice, assuming that Thread.interrupt() never@3156: // generates a SIGUSRx signal. Note that SIGUSR1 can interfere with never@3156: // SIGSEGV, see 4355769. never@3156: never@3156: int os::sleep(Thread* thread, jlong millis, bool interruptible) { never@3156: assert(thread == Thread::current(), "thread consistency check"); never@3156: never@3156: ParkEvent * const slp = thread->_SleepEvent ; never@3156: slp->reset() ; never@3156: OrderAccess::fence() ; never@3156: never@3156: if (interruptible) { never@3156: jlong prevtime = javaTimeNanos(); never@3156: never@3156: for (;;) { never@3156: if (os::is_interrupted(thread, true)) { never@3156: return OS_INTRPT; never@3156: } never@3156: never@3156: jlong newtime = javaTimeNanos(); never@3156: never@3156: if (newtime - prevtime < 0) { never@3156: // time moving backwards, should only happen if no monotonic clock never@3156: // not a guarantee() because JVM should not abort on kernel/glibc bugs never@3156: assert(!Bsd::supports_monotonic_clock(), "time moving backwards"); never@3156: } else { johnc@3339: millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; never@3156: } never@3156: never@3156: if(millis <= 0) { never@3156: return OS_OK; never@3156: } never@3156: never@3156: prevtime = newtime; never@3156: never@3156: { never@3156: assert(thread->is_Java_thread(), "sanity check"); never@3156: JavaThread *jt = (JavaThread *) thread; never@3156: ThreadBlockInVM tbivm(jt); never@3156: OSThreadWaitState osts(jt->osthread(), false /* not Object.wait() */); never@3156: never@3156: jt->set_suspend_equivalent(); never@3156: // cleared by handle_special_suspend_equivalent_condition() or never@3156: // java_suspend_self() via check_and_wait_while_suspended() never@3156: never@3156: slp->park(millis); never@3156: never@3156: // were we externally suspended while we were waiting? never@3156: jt->check_and_wait_while_suspended(); never@3156: } never@3156: } never@3156: } else { never@3156: OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); never@3156: jlong prevtime = javaTimeNanos(); never@3156: never@3156: for (;;) { never@3156: // It'd be nice to avoid the back-to-back javaTimeNanos() calls on never@3156: // the 1st iteration ... never@3156: jlong newtime = javaTimeNanos(); never@3156: never@3156: if (newtime - prevtime < 0) { never@3156: // time moving backwards, should only happen if no monotonic clock never@3156: // not a guarantee() because JVM should not abort on kernel/glibc bugs never@3156: assert(!Bsd::supports_monotonic_clock(), "time moving backwards"); never@3156: } else { johnc@3339: millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC; never@3156: } never@3156: never@3156: if(millis <= 0) break ; never@3156: never@3156: prevtime = newtime; never@3156: slp->park(millis); never@3156: } never@3156: return OS_OK ; never@3156: } never@3156: } never@3156: never@3156: int os::naked_sleep() { never@3156: // %% make the sleep time an integer flag. for now use 1 millisec. never@3156: return os::sleep(Thread::current(), 1, false); never@3156: } never@3156: never@3156: // Sleep forever; naked call to OS-specific sleep; use with CAUTION never@3156: void os::infinite_sleep() { never@3156: while (true) { // sleep forever ... never@3156: ::sleep(100); // ... 100 seconds at a time never@3156: } never@3156: } never@3156: never@3156: // Used to convert frequent JVM_Yield() to nops never@3156: bool os::dont_yield() { never@3156: return DontYieldALot; never@3156: } never@3156: never@3156: void os::yield() { never@3156: sched_yield(); never@3156: } never@3156: never@3156: os::YieldResult os::NakedYield() { sched_yield(); return os::YIELD_UNKNOWN ;} never@3156: never@3156: void os::yield_all(int attempts) { never@3156: // Yields to all threads, including threads with lower priorities never@3156: // Threads on Bsd are all with same priority. The Solaris style never@3156: // os::yield_all() with nanosleep(1ms) is not necessary. never@3156: sched_yield(); never@3156: } never@3156: never@3156: // Called from the tight loops to possibly influence time-sharing heuristics never@3156: void os::loop_breaker(int attempts) { never@3156: os::yield_all(attempts); never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // thread priority support never@3156: never@3156: // Note: Normal Bsd applications are run with SCHED_OTHER policy. SCHED_OTHER never@3156: // only supports dynamic priority, static priority must be zero. For real-time never@3156: // applications, Bsd supports SCHED_RR which allows static priority (1-99). never@3156: // However, for large multi-threaded applications, SCHED_RR is not only slower never@3156: // than SCHED_OTHER, but also very unstable (my volano tests hang hard 4 out never@3156: // of 5 runs - Sep 2005). never@3156: // never@3156: // The following code actually changes the niceness of kernel-thread/LWP. It never@3156: // has an assumption that setpriority() only modifies one kernel-thread/LWP, never@3156: // not the entire user process, and user level threads are 1:1 mapped to kernel never@3156: // threads. It has always been the case, but could change in the future. For never@3156: // this reason, the code should not be used as default (ThreadPriorityPolicy=0). never@3156: // It is only used when ThreadPriorityPolicy=1 and requires root privilege. never@3156: sla@4229: #if !defined(__APPLE__) phh@3481: int os::java_to_os_priority[CriticalPriority + 1] = { never@3156: 19, // 0 Entry should never be used never@3156: never@3156: 0, // 1 MinPriority never@3156: 3, // 2 never@3156: 6, // 3 never@3156: phh@3481: 10, // 4 phh@3481: 15, // 5 NormPriority phh@3481: 18, // 6 phh@3481: phh@3481: 21, // 7 phh@3481: 25, // 8 phh@3481: 28, // 9 NearMaxPriority phh@3481: phh@3481: 31, // 10 MaxPriority phh@3481: phh@3481: 31 // 11 CriticalPriority never@3156: }; sla@4229: #else never@3156: /* Using Mach high-level priority assignments */ phh@3481: int os::java_to_os_priority[CriticalPriority + 1] = { never@3156: 0, // 0 Entry should never be used (MINPRI_USER) never@3156: never@3156: 27, // 1 MinPriority never@3156: 28, // 2 never@3156: 29, // 3 never@3156: never@3156: 30, // 4 never@3156: 31, // 5 NormPriority (BASEPRI_DEFAULT) never@3156: 32, // 6 never@3156: never@3156: 33, // 7 never@3156: 34, // 8 never@3156: 35, // 9 NearMaxPriority never@3156: phh@3481: 36, // 10 MaxPriority phh@3481: phh@3481: 36 // 11 CriticalPriority never@3156: }; never@3156: #endif never@3156: never@3156: static int prio_init() { never@3156: if (ThreadPriorityPolicy == 1) { never@3156: // Only root can raise thread priority. Don't allow ThreadPriorityPolicy=1 never@3156: // if effective uid is not root. Perhaps, a more elegant way of doing never@3156: // this is to test CAP_SYS_NICE capability, but that will require libcap.so never@3156: if (geteuid() != 0) { never@3156: if (!FLAG_IS_DEFAULT(ThreadPriorityPolicy)) { never@3156: warning("-XX:ThreadPriorityPolicy requires root privilege on Bsd"); never@3156: } never@3156: ThreadPriorityPolicy = 0; never@3156: } never@3156: } phh@3481: if (UseCriticalJavaThreadPriority) { phh@3481: os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority]; phh@3481: } never@3156: return 0; never@3156: } never@3156: never@3156: OSReturn os::set_native_priority(Thread* thread, int newpri) { never@3156: if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) return OS_OK; never@3156: never@3156: #ifdef __OpenBSD__ never@3156: // OpenBSD pthread_setprio starves low priority threads never@3156: return OS_OK; never@3156: #elif defined(__FreeBSD__) never@3156: int ret = pthread_setprio(thread->osthread()->pthread_id(), newpri); never@3156: #elif defined(__APPLE__) || defined(__NetBSD__) never@3156: struct sched_param sp; never@3156: int policy; never@3156: pthread_t self = pthread_self(); never@3156: never@3156: if (pthread_getschedparam(self, &policy, &sp) != 0) never@3156: return OS_ERR; never@3156: never@3156: sp.sched_priority = newpri; never@3156: if (pthread_setschedparam(self, policy, &sp) != 0) never@3156: return OS_ERR; never@3156: never@3156: return OS_OK; never@3156: #else never@3156: int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri); never@3156: return (ret == 0) ? OS_OK : OS_ERR; never@3156: #endif never@3156: } never@3156: never@3156: OSReturn os::get_native_priority(const Thread* const thread, int *priority_ptr) { never@3156: if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) { never@3156: *priority_ptr = java_to_os_priority[NormPriority]; never@3156: return OS_OK; never@3156: } never@3156: never@3156: errno = 0; never@3156: #if defined(__OpenBSD__) || defined(__FreeBSD__) never@3156: *priority_ptr = pthread_getprio(thread->osthread()->pthread_id()); never@3156: #elif defined(__APPLE__) || defined(__NetBSD__) never@3156: int policy; never@3156: struct sched_param sp; never@3156: never@3156: pthread_getschedparam(pthread_self(), &policy, &sp); never@3156: *priority_ptr = sp.sched_priority; never@3156: #else never@3156: *priority_ptr = getpriority(PRIO_PROCESS, thread->osthread()->thread_id()); never@3156: #endif never@3156: return (*priority_ptr != -1 || errno == 0 ? OS_OK : OS_ERR); never@3156: } never@3156: never@3156: // Hint to the underlying OS that a task switch would not be good. never@3156: // Void return because it's a hint and can fail. never@3156: void os::hint_no_preempt() {} never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // suspend/resume support never@3156: never@3156: // the low-level signal-based suspend/resume support is a remnant from the never@3156: // old VM-suspension that used to be for java-suspension, safepoints etc, never@3156: // within hotspot. Now there is a single use-case for this: never@3156: // - calling get_thread_pc() on the VMThread by the flat-profiler task never@3156: // that runs in the watcher thread. never@3156: // The remaining code is greatly simplified from the more general suspension never@3156: // code that used to be used. never@3156: // never@3156: // The protocol is quite simple: never@3156: // - suspend: never@3156: // - sends a signal to the target thread never@3156: // - polls the suspend state of the osthread using a yield loop never@3156: // - target thread signal handler (SR_handler) sets suspend state never@3156: // and blocks in sigsuspend until continued never@3156: // - resume: never@3156: // - sets target osthread state to continue never@3156: // - sends signal to end the sigsuspend loop in the SR_handler never@3156: // never@3156: // Note that the SR_lock plays no role in this suspend/resume protocol. never@3156: // never@3156: never@3156: static void resume_clear_context(OSThread *osthread) { never@3156: osthread->set_ucontext(NULL); never@3156: osthread->set_siginfo(NULL); never@3156: never@3156: // notify the suspend action is completed, we have now resumed never@3156: osthread->sr.clear_suspended(); never@3156: } never@3156: never@3156: static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontext_t* context) { never@3156: osthread->set_ucontext(context); never@3156: osthread->set_siginfo(siginfo); never@3156: } never@3156: never@3156: // never@3156: // Handler function invoked when a thread's execution is suspended or never@3156: // resumed. We have to be careful that only async-safe functions are never@3156: // called here (Note: most pthread functions are not async safe and never@3156: // should be avoided.) never@3156: // never@3156: // Note: sigwait() is a more natural fit than sigsuspend() from an never@3156: // interface point of view, but sigwait() prevents the signal hander never@3156: // from being run. libpthread would get very confused by not having never@3156: // its signal handlers run and prevents sigwait()'s use with the never@3156: // mutex granting granting signal. never@3156: // never@3156: // Currently only ever called on the VMThread never@3156: // never@3156: static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { never@3156: // Save and restore errno to avoid confusing native code with EINTR never@3156: // after sigsuspend. never@3156: int old_errno = errno; never@3156: never@3156: Thread* thread = Thread::current(); never@3156: OSThread* osthread = thread->osthread(); never@3156: assert(thread->is_VM_thread(), "Must be VMThread"); never@3156: // read current suspend action never@3156: int action = osthread->sr.suspend_action(); simonis@4675: if (action == os::Bsd::SuspendResume::SR_SUSPEND) { never@3156: suspend_save_context(osthread, siginfo, context); never@3156: never@3156: // Notify the suspend action is about to be completed. do_suspend() never@3156: // waits until SR_SUSPENDED is set and then returns. We will wait never@3156: // here for a resume signal and that completes the suspend-other never@3156: // action. do_suspend/do_resume is always called as a pair from never@3156: // the same thread - so there are no races never@3156: never@3156: // notify the caller never@3156: osthread->sr.set_suspended(); never@3156: never@3156: sigset_t suspend_set; // signals for sigsuspend() never@3156: never@3156: // get current set of blocked signals and unblock resume signal never@3156: pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); never@3156: sigdelset(&suspend_set, SR_signum); never@3156: never@3156: // wait here until we are resumed never@3156: do { never@3156: sigsuspend(&suspend_set); never@3156: // ignore all returns until we get a resume signal simonis@4675: } while (osthread->sr.suspend_action() != os::Bsd::SuspendResume::SR_CONTINUE); never@3156: never@3156: resume_clear_context(osthread); never@3156: never@3156: } else { simonis@4675: assert(action == os::Bsd::SuspendResume::SR_CONTINUE, "unexpected sr action"); never@3156: // nothing special to do - just leave the handler never@3156: } never@3156: never@3156: errno = old_errno; never@3156: } never@3156: never@3156: never@3156: static int SR_initialize() { never@3156: struct sigaction act; never@3156: char *s; never@3156: /* Get signal number to use for suspend/resume */ never@3156: if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) { never@3156: int sig = ::strtol(s, 0, 10); never@3156: if (sig > 0 || sig < NSIG) { never@3156: SR_signum = sig; never@3156: } never@3156: } never@3156: never@3156: assert(SR_signum > SIGSEGV && SR_signum > SIGBUS, never@3156: "SR_signum must be greater than max(SIGSEGV, SIGBUS), see 4355769"); never@3156: never@3156: sigemptyset(&SR_sigset); never@3156: sigaddset(&SR_sigset, SR_signum); never@3156: never@3156: /* Set up signal handler for suspend/resume */ never@3156: act.sa_flags = SA_RESTART|SA_SIGINFO; never@3156: act.sa_handler = (void (*)(int)) SR_handler; never@3156: never@3156: // SR_signum is blocked by default. never@3156: // 4528190 - We also need to block pthread restart signal (32 on all never@3156: // supported Bsd platforms). Note that BsdThreads need to block never@3156: // this signal for all threads to work properly. So we don't have never@3156: // to use hard-coded signal number when setting up the mask. never@3156: pthread_sigmask(SIG_BLOCK, NULL, &act.sa_mask); never@3156: never@3156: if (sigaction(SR_signum, &act, 0) == -1) { never@3156: return -1; never@3156: } never@3156: never@3156: // Save signal flag never@3156: os::Bsd::set_our_sigflags(SR_signum, act.sa_flags); never@3156: return 0; never@3156: } never@3156: never@3156: static int SR_finalize() { never@3156: return 0; never@3156: } never@3156: never@3156: never@3156: // returns true on success and false on error - really an error is fatal never@3156: // but this seems the normal response to library errors never@3156: static bool do_suspend(OSThread* osthread) { never@3156: // mark as suspended and send signal simonis@4675: osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_SUSPEND); never@3156: int status = pthread_kill(osthread->pthread_id(), SR_signum); never@3156: assert_status(status == 0, status, "pthread_kill"); never@3156: never@3156: // check status and wait until notified of suspension never@3156: if (status == 0) { never@3156: for (int i = 0; !osthread->sr.is_suspended(); i++) { never@3156: os::yield_all(i); never@3156: } simonis@4675: osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); never@3156: return true; never@3156: } never@3156: else { simonis@4675: osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); never@3156: return false; never@3156: } never@3156: } never@3156: never@3156: static void do_resume(OSThread* osthread) { never@3156: assert(osthread->sr.is_suspended(), "thread should be suspended"); simonis@4675: osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_CONTINUE); never@3156: never@3156: int status = pthread_kill(osthread->pthread_id(), SR_signum); never@3156: assert_status(status == 0, status, "pthread_kill"); never@3156: // check status and wait unit notified of resumption never@3156: if (status == 0) { never@3156: for (int i = 0; osthread->sr.is_suspended(); i++) { never@3156: os::yield_all(i); never@3156: } never@3156: } simonis@4675: osthread->sr.set_suspend_action(os::Bsd::SuspendResume::SR_NONE); never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // interrupt support never@3156: never@3156: void os::interrupt(Thread* thread) { never@3156: assert(Thread::current() == thread || Threads_lock->owned_by_self(), never@3156: "possibility of dangling Thread pointer"); never@3156: never@3156: OSThread* osthread = thread->osthread(); never@3156: never@3156: if (!osthread->interrupted()) { never@3156: osthread->set_interrupted(true); never@3156: // More than one thread can get here with the same value of osthread, never@3156: // resulting in multiple notifications. We do, however, want the store never@3156: // to interrupted() to be visible to other threads before we execute unpark(). never@3156: OrderAccess::fence(); never@3156: ParkEvent * const slp = thread->_SleepEvent ; never@3156: if (slp != NULL) slp->unpark() ; never@3156: } never@3156: never@3156: // For JSR166. Unpark even if interrupt status already was set never@3156: if (thread->is_Java_thread()) never@3156: ((JavaThread*)thread)->parker()->unpark(); never@3156: never@3156: ParkEvent * ev = thread->_ParkEvent ; never@3156: if (ev != NULL) ev->unpark() ; never@3156: never@3156: } never@3156: never@3156: bool os::is_interrupted(Thread* thread, bool clear_interrupted) { never@3156: assert(Thread::current() == thread || Threads_lock->owned_by_self(), never@3156: "possibility of dangling Thread pointer"); never@3156: never@3156: OSThread* osthread = thread->osthread(); never@3156: never@3156: bool interrupted = osthread->interrupted(); never@3156: never@3156: if (interrupted && clear_interrupted) { never@3156: osthread->set_interrupted(false); never@3156: // consider thread->_SleepEvent->reset() ... optional optimization never@3156: } never@3156: never@3156: return interrupted; never@3156: } never@3156: never@3156: /////////////////////////////////////////////////////////////////////////////////// never@3156: // signal handling (except suspend/resume) never@3156: never@3156: // This routine may be used by user applications as a "hook" to catch signals. never@3156: // The user-defined signal handler must pass unrecognized signals to this never@3156: // routine, and if it returns true (non-zero), then the signal handler must never@3156: // return immediately. If the flag "abort_if_unrecognized" is true, then this never@3156: // routine will never retun false (zero), but instead will execute a VM panic never@3156: // routine kill the process. never@3156: // never@3156: // If this routine returns false, it is OK to call it again. This allows never@3156: // the user-defined signal handler to perform checks either before or after never@3156: // the VM performs its own checks. Naturally, the user code would be making never@3156: // a serious error if it tried to handle an exception (such as a null check never@3156: // or breakpoint) that the VM was generating for its own correct operation. never@3156: // never@3156: // This routine may recognize any of the following kinds of signals: never@3156: // SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1. never@3156: // It should be consulted by handlers for any of those signals. never@3156: // never@3156: // The caller of this routine must pass in the three arguments supplied never@3156: // to the function referred to in the "sa_sigaction" (not the "sa_handler") never@3156: // field of the structure passed to sigaction(). This routine assumes that never@3156: // the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART. never@3156: // never@3156: // Note that the VM will print warnings if it detects conflicting signal never@3156: // handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers". never@3156: // never@3156: extern "C" JNIEXPORT int never@3156: JVM_handle_bsd_signal(int signo, siginfo_t* siginfo, never@3156: void* ucontext, int abort_if_unrecognized); never@3156: never@3156: void signalHandler(int sig, siginfo_t* info, void* uc) { never@3156: assert(info != NULL && uc != NULL, "it must be old kernel"); hseigel@4608: int orig_errno = errno; // Preserve errno value over signal handler. never@3156: JVM_handle_bsd_signal(sig, info, uc, true); hseigel@4608: errno = orig_errno; never@3156: } never@3156: never@3156: never@3156: // This boolean allows users to forward their own non-matching signals never@3156: // to JVM_handle_bsd_signal, harmlessly. never@3156: bool os::Bsd::signal_handlers_are_installed = false; never@3156: never@3156: // For signal-chaining never@3156: struct sigaction os::Bsd::sigact[MAXSIGNUM]; never@3156: unsigned int os::Bsd::sigs = 0; never@3156: bool os::Bsd::libjsig_is_loaded = false; never@3156: typedef struct sigaction *(*get_signal_t)(int); never@3156: get_signal_t os::Bsd::get_signal_action = NULL; never@3156: never@3156: struct sigaction* os::Bsd::get_chained_signal_action(int sig) { never@3156: struct sigaction *actp = NULL; never@3156: never@3156: if (libjsig_is_loaded) { never@3156: // Retrieve the old signal handler from libjsig never@3156: actp = (*get_signal_action)(sig); never@3156: } never@3156: if (actp == NULL) { never@3156: // Retrieve the preinstalled signal handler from jvm never@3156: actp = get_preinstalled_handler(sig); never@3156: } never@3156: never@3156: return actp; never@3156: } never@3156: never@3156: static bool call_chained_handler(struct sigaction *actp, int sig, never@3156: siginfo_t *siginfo, void *context) { never@3156: // Call the old signal handler never@3156: if (actp->sa_handler == SIG_DFL) { never@3156: // It's more reasonable to let jvm treat it as an unexpected exception never@3156: // instead of taking the default action. never@3156: return false; never@3156: } else if (actp->sa_handler != SIG_IGN) { never@3156: if ((actp->sa_flags & SA_NODEFER) == 0) { never@3156: // automaticlly block the signal never@3156: sigaddset(&(actp->sa_mask), sig); never@3156: } never@3156: never@3156: sa_handler_t hand; never@3156: sa_sigaction_t sa; never@3156: bool siginfo_flag_set = (actp->sa_flags & SA_SIGINFO) != 0; never@3156: // retrieve the chained handler never@3156: if (siginfo_flag_set) { never@3156: sa = actp->sa_sigaction; never@3156: } else { never@3156: hand = actp->sa_handler; never@3156: } never@3156: never@3156: if ((actp->sa_flags & SA_RESETHAND) != 0) { never@3156: actp->sa_handler = SIG_DFL; never@3156: } never@3156: never@3156: // try to honor the signal mask never@3156: sigset_t oset; never@3156: pthread_sigmask(SIG_SETMASK, &(actp->sa_mask), &oset); never@3156: never@3156: // call into the chained handler never@3156: if (siginfo_flag_set) { never@3156: (*sa)(sig, siginfo, context); never@3156: } else { never@3156: (*hand)(sig); never@3156: } never@3156: never@3156: // restore the signal mask never@3156: pthread_sigmask(SIG_SETMASK, &oset, 0); never@3156: } never@3156: // Tell jvm's signal handler the signal is taken care of. never@3156: return true; never@3156: } never@3156: never@3156: bool os::Bsd::chained_handler(int sig, siginfo_t* siginfo, void* context) { never@3156: bool chained = false; never@3156: // signal-chaining never@3156: if (UseSignalChaining) { never@3156: struct sigaction *actp = get_chained_signal_action(sig); never@3156: if (actp != NULL) { never@3156: chained = call_chained_handler(actp, sig, siginfo, context); never@3156: } never@3156: } never@3156: return chained; never@3156: } never@3156: never@3156: struct sigaction* os::Bsd::get_preinstalled_handler(int sig) { never@3156: if ((( (unsigned int)1 << sig ) & sigs) != 0) { never@3156: return &sigact[sig]; never@3156: } never@3156: return NULL; never@3156: } never@3156: never@3156: void os::Bsd::save_preinstalled_handler(int sig, struct sigaction& oldAct) { never@3156: assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); never@3156: sigact[sig] = oldAct; never@3156: sigs |= (unsigned int)1 << sig; never@3156: } never@3156: never@3156: // for diagnostic never@3156: int os::Bsd::sigflags[MAXSIGNUM]; never@3156: never@3156: int os::Bsd::get_our_sigflags(int sig) { never@3156: assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); never@3156: return sigflags[sig]; never@3156: } never@3156: never@3156: void os::Bsd::set_our_sigflags(int sig, int flags) { never@3156: assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); never@3156: sigflags[sig] = flags; never@3156: } never@3156: never@3156: void os::Bsd::set_signal_handler(int sig, bool set_installed) { never@3156: // Check for overwrite. never@3156: struct sigaction oldAct; never@3156: sigaction(sig, (struct sigaction*)NULL, &oldAct); never@3156: never@3156: void* oldhand = oldAct.sa_sigaction never@3156: ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) never@3156: : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); never@3156: if (oldhand != CAST_FROM_FN_PTR(void*, SIG_DFL) && never@3156: oldhand != CAST_FROM_FN_PTR(void*, SIG_IGN) && never@3156: oldhand != CAST_FROM_FN_PTR(void*, (sa_sigaction_t)signalHandler)) { never@3156: if (AllowUserSignalHandlers || !set_installed) { never@3156: // Do not overwrite; user takes responsibility to forward to us. never@3156: return; never@3156: } else if (UseSignalChaining) { never@3156: // save the old handler in jvm never@3156: save_preinstalled_handler(sig, oldAct); never@3156: // libjsig also interposes the sigaction() call below and saves the never@3156: // old sigaction on it own. never@3156: } else { never@3156: fatal(err_msg("Encountered unexpected pre-existing sigaction handler " never@3156: "%#lx for signal %d.", (long)oldhand, sig)); never@3156: } never@3156: } never@3156: never@3156: struct sigaction sigAct; never@3156: sigfillset(&(sigAct.sa_mask)); never@3156: sigAct.sa_handler = SIG_DFL; never@3156: if (!set_installed) { never@3156: sigAct.sa_flags = SA_SIGINFO|SA_RESTART; never@3156: } else { never@3156: sigAct.sa_sigaction = signalHandler; never@3156: sigAct.sa_flags = SA_SIGINFO|SA_RESTART; never@3156: } never@3156: // Save flags, which are set by ours never@3156: assert(sig > 0 && sig < MAXSIGNUM, "vm signal out of expected range"); never@3156: sigflags[sig] = sigAct.sa_flags; never@3156: never@3156: int ret = sigaction(sig, &sigAct, &oldAct); never@3156: assert(ret == 0, "check"); never@3156: never@3156: void* oldhand2 = oldAct.sa_sigaction never@3156: ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) never@3156: : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); never@3156: assert(oldhand2 == oldhand, "no concurrent signal handler installation"); never@3156: } never@3156: never@3156: // install signal handlers for signals that HotSpot needs to never@3156: // handle in order to support Java-level exception handling. never@3156: never@3156: void os::Bsd::install_signal_handlers() { never@3156: if (!signal_handlers_are_installed) { never@3156: signal_handlers_are_installed = true; never@3156: never@3156: // signal-chaining never@3156: typedef void (*signal_setting_t)(); never@3156: signal_setting_t begin_signal_setting = NULL; never@3156: signal_setting_t end_signal_setting = NULL; never@3156: begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t, never@3156: dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting")); never@3156: if (begin_signal_setting != NULL) { never@3156: end_signal_setting = CAST_TO_FN_PTR(signal_setting_t, never@3156: dlsym(RTLD_DEFAULT, "JVM_end_signal_setting")); never@3156: get_signal_action = CAST_TO_FN_PTR(get_signal_t, never@3156: dlsym(RTLD_DEFAULT, "JVM_get_signal_action")); never@3156: libjsig_is_loaded = true; never@3156: assert(UseSignalChaining, "should enable signal-chaining"); never@3156: } never@3156: if (libjsig_is_loaded) { never@3156: // Tell libjsig jvm is setting signal handlers never@3156: (*begin_signal_setting)(); never@3156: } never@3156: never@3156: set_signal_handler(SIGSEGV, true); never@3156: set_signal_handler(SIGPIPE, true); never@3156: set_signal_handler(SIGBUS, true); never@3156: set_signal_handler(SIGILL, true); never@3156: set_signal_handler(SIGFPE, true); never@3156: set_signal_handler(SIGXFSZ, true); never@3156: never@3156: #if defined(__APPLE__) never@3156: // In Mac OS X 10.4, CrashReporter will write a crash log for all 'fatal' signals, including never@3156: // signals caught and handled by the JVM. To work around this, we reset the mach task never@3156: // signal handler that's placed on our process by CrashReporter. This disables never@3156: // CrashReporter-based reporting. never@3156: // never@3156: // This work-around is not necessary for 10.5+, as CrashReporter no longer intercedes never@3156: // on caught fatal signals. never@3156: // never@3156: // Additionally, gdb installs both standard BSD signal handlers, and mach exception never@3156: // handlers. By replacing the existing task exception handler, we disable gdb's mach never@3156: // exception handling, while leaving the standard BSD signal handlers functional. never@3156: kern_return_t kr; never@3156: kr = task_set_exception_ports(mach_task_self(), never@3156: EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, never@3156: MACH_PORT_NULL, never@3156: EXCEPTION_STATE_IDENTITY, never@3156: MACHINE_THREAD_STATE); never@3156: never@3156: assert(kr == KERN_SUCCESS, "could not set mach task signal handler"); never@3156: #endif never@3156: never@3156: if (libjsig_is_loaded) { never@3156: // Tell libjsig jvm finishes setting signal handlers never@3156: (*end_signal_setting)(); never@3156: } never@3156: never@3156: // We don't activate signal checker if libjsig is in place, we trust ourselves never@3156: // and if UserSignalHandler is installed all bets are off never@3156: if (CheckJNICalls) { never@3156: if (libjsig_is_loaded) { never@3156: tty->print_cr("Info: libjsig is activated, all active signal checking is disabled"); never@3156: check_signals = false; never@3156: } never@3156: if (AllowUserSignalHandlers) { never@3156: tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); never@3156: check_signals = false; never@3156: } never@3156: } never@3156: } never@3156: } never@3156: never@3156: never@3156: ///// never@3156: // glibc on Bsd platform uses non-documented flag never@3156: // to indicate, that some special sort of signal never@3156: // trampoline is used. never@3156: // We will never set this flag, and we should never@3156: // ignore this flag in our diagnostic never@3156: #ifdef SIGNIFICANT_SIGNAL_MASK never@3156: #undef SIGNIFICANT_SIGNAL_MASK never@3156: #endif never@3156: #define SIGNIFICANT_SIGNAL_MASK (~0x04000000) never@3156: never@3156: static const char* get_signal_handler_name(address handler, never@3156: char* buf, int buflen) { never@3156: int offset; never@3156: bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset); never@3156: if (found) { never@3156: // skip directory names never@3156: const char *p1, *p2; never@3156: p1 = buf; never@3156: size_t len = strlen(os::file_separator()); never@3156: while ((p2 = strstr(p1, os::file_separator())) != NULL) p1 = p2 + len; never@3156: jio_snprintf(buf, buflen, "%s+0x%x", p1, offset); never@3156: } else { never@3156: jio_snprintf(buf, buflen, PTR_FORMAT, handler); never@3156: } never@3156: return buf; never@3156: } never@3156: never@3156: static void print_signal_handler(outputStream* st, int sig, never@3156: char* buf, size_t buflen) { never@3156: struct sigaction sa; never@3156: never@3156: sigaction(sig, NULL, &sa); never@3156: never@3156: // See comment for SIGNIFICANT_SIGNAL_MASK define never@3156: sa.sa_flags &= SIGNIFICANT_SIGNAL_MASK; never@3156: never@3156: st->print("%s: ", os::exception_name(sig, buf, buflen)); never@3156: never@3156: address handler = (sa.sa_flags & SA_SIGINFO) never@3156: ? CAST_FROM_FN_PTR(address, sa.sa_sigaction) never@3156: : CAST_FROM_FN_PTR(address, sa.sa_handler); never@3156: never@3156: if (handler == CAST_FROM_FN_PTR(address, SIG_DFL)) { never@3156: st->print("SIG_DFL"); never@3156: } else if (handler == CAST_FROM_FN_PTR(address, SIG_IGN)) { never@3156: st->print("SIG_IGN"); never@3156: } else { never@3156: st->print("[%s]", get_signal_handler_name(handler, buf, buflen)); never@3156: } never@3156: never@3156: st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask); never@3156: never@3156: address rh = VMError::get_resetted_sighandler(sig); never@3156: // May be, handler was resetted by VMError? never@3156: if(rh != NULL) { never@3156: handler = rh; never@3156: sa.sa_flags = VMError::get_resetted_sigflags(sig) & SIGNIFICANT_SIGNAL_MASK; never@3156: } never@3156: never@3156: st->print(", sa_flags=" PTR32_FORMAT, sa.sa_flags); never@3156: never@3156: // Check: is it our handler? never@3156: if(handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler) || never@3156: handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler)) { never@3156: // It is our signal handler never@3156: // check for flags, reset system-used one! never@3156: if((int)sa.sa_flags != os::Bsd::get_our_sigflags(sig)) { never@3156: st->print( never@3156: ", flags was changed from " PTR32_FORMAT ", consider using jsig library", never@3156: os::Bsd::get_our_sigflags(sig)); never@3156: } never@3156: } never@3156: st->cr(); never@3156: } never@3156: never@3156: never@3156: #define DO_SIGNAL_CHECK(sig) \ never@3156: if (!sigismember(&check_signal_done, sig)) \ never@3156: os::Bsd::check_signal_handler(sig) never@3156: never@3156: // This method is a periodic task to check for misbehaving JNI applications never@3156: // under CheckJNI, we can add any periodic checks here never@3156: never@3156: void os::run_periodic_checks() { never@3156: never@3156: if (check_signals == false) return; never@3156: never@3156: // SEGV and BUS if overridden could potentially prevent never@3156: // generation of hs*.log in the event of a crash, debugging never@3156: // such a case can be very challenging, so we absolutely never@3156: // check the following for a good measure: never@3156: DO_SIGNAL_CHECK(SIGSEGV); never@3156: DO_SIGNAL_CHECK(SIGILL); never@3156: DO_SIGNAL_CHECK(SIGFPE); never@3156: DO_SIGNAL_CHECK(SIGBUS); never@3156: DO_SIGNAL_CHECK(SIGPIPE); never@3156: DO_SIGNAL_CHECK(SIGXFSZ); never@3156: never@3156: never@3156: // ReduceSignalUsage allows the user to override these handlers never@3156: // see comments at the very top and jvm_solaris.h never@3156: if (!ReduceSignalUsage) { never@3156: DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL); never@3156: DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL); never@3156: DO_SIGNAL_CHECK(SHUTDOWN3_SIGNAL); never@3156: DO_SIGNAL_CHECK(BREAK_SIGNAL); never@3156: } never@3156: never@3156: DO_SIGNAL_CHECK(SR_signum); never@3156: DO_SIGNAL_CHECK(INTERRUPT_SIGNAL); never@3156: } never@3156: never@3156: typedef int (*os_sigaction_t)(int, const struct sigaction *, struct sigaction *); never@3156: never@3156: static os_sigaction_t os_sigaction = NULL; never@3156: never@3156: void os::Bsd::check_signal_handler(int sig) { never@3156: char buf[O_BUFLEN]; never@3156: address jvmHandler = NULL; never@3156: never@3156: never@3156: struct sigaction act; never@3156: if (os_sigaction == NULL) { never@3156: // only trust the default sigaction, in case it has been interposed never@3156: os_sigaction = (os_sigaction_t)dlsym(RTLD_DEFAULT, "sigaction"); never@3156: if (os_sigaction == NULL) return; never@3156: } never@3156: never@3156: os_sigaction(sig, (struct sigaction*)NULL, &act); never@3156: never@3156: never@3156: act.sa_flags &= SIGNIFICANT_SIGNAL_MASK; never@3156: never@3156: address thisHandler = (act.sa_flags & SA_SIGINFO) never@3156: ? CAST_FROM_FN_PTR(address, act.sa_sigaction) never@3156: : CAST_FROM_FN_PTR(address, act.sa_handler) ; never@3156: never@3156: never@3156: switch(sig) { never@3156: case SIGSEGV: never@3156: case SIGBUS: never@3156: case SIGFPE: never@3156: case SIGPIPE: never@3156: case SIGILL: never@3156: case SIGXFSZ: never@3156: jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler); never@3156: break; never@3156: never@3156: case SHUTDOWN1_SIGNAL: never@3156: case SHUTDOWN2_SIGNAL: never@3156: case SHUTDOWN3_SIGNAL: never@3156: case BREAK_SIGNAL: never@3156: jvmHandler = (address)user_handler(); never@3156: break; never@3156: never@3156: case INTERRUPT_SIGNAL: never@3156: jvmHandler = CAST_FROM_FN_PTR(address, SIG_DFL); never@3156: break; never@3156: never@3156: default: never@3156: if (sig == SR_signum) { never@3156: jvmHandler = CAST_FROM_FN_PTR(address, (sa_sigaction_t)SR_handler); never@3156: } else { never@3156: return; never@3156: } never@3156: break; never@3156: } never@3156: never@3156: if (thisHandler != jvmHandler) { never@3156: tty->print("Warning: %s handler ", exception_name(sig, buf, O_BUFLEN)); never@3156: tty->print("expected:%s", get_signal_handler_name(jvmHandler, buf, O_BUFLEN)); never@3156: tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN)); never@3156: // No need to check this sig any longer never@3156: sigaddset(&check_signal_done, sig); never@3156: } else if(os::Bsd::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Bsd::get_our_sigflags(sig)) { never@3156: tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN)); never@3156: tty->print("expected:" PTR32_FORMAT, os::Bsd::get_our_sigflags(sig)); never@3156: tty->print_cr(" found:" PTR32_FORMAT, act.sa_flags); never@3156: // No need to check this sig any longer never@3156: sigaddset(&check_signal_done, sig); never@3156: } never@3156: never@3156: // Dump all the signal never@3156: if (sigismember(&check_signal_done, sig)) { never@3156: print_signal_handlers(tty, buf, O_BUFLEN); never@3156: } never@3156: } never@3156: never@3156: extern void report_error(char* file_name, int line_no, char* title, char* format, ...); never@3156: never@3156: extern bool signal_name(int signo, char* buf, size_t len); never@3156: never@3156: const char* os::exception_name(int exception_code, char* buf, size_t size) { never@3156: if (0 < exception_code && exception_code <= SIGRTMAX) { never@3156: // signal never@3156: if (!signal_name(exception_code, buf, size)) { never@3156: jio_snprintf(buf, size, "SIG%d", exception_code); never@3156: } never@3156: return buf; never@3156: } else { never@3156: return NULL; never@3156: } never@3156: } never@3156: never@3156: // this is called _before_ the most of global arguments have been parsed never@3156: void os::init(void) { never@3156: char dummy; /* used to get a guess on initial stack address */ never@3156: // first_hrtime = gethrtime(); never@3156: never@3156: // With BsdThreads the JavaMain thread pid (primordial thread) never@3156: // is different than the pid of the java launcher thread. never@3156: // So, on Bsd, the launcher thread pid is passed to the VM never@3156: // via the sun.java.launcher.pid property. never@3156: // Use this property instead of getpid() if it was correctly passed. never@3156: // See bug 6351349. never@3156: pid_t java_launcher_pid = (pid_t) Arguments::sun_java_launcher_pid(); never@3156: never@3156: _initial_pid = (java_launcher_pid > 0) ? java_launcher_pid : getpid(); never@3156: never@3156: clock_tics_per_sec = CLK_TCK; never@3156: never@3156: init_random(1234567); never@3156: never@3156: ThreadCritical::initialize(); never@3156: never@3156: Bsd::set_page_size(getpagesize()); never@3156: if (Bsd::page_size() == -1) { never@3156: fatal(err_msg("os_bsd.cpp: os::init: sysconf failed (%s)", never@3156: strerror(errno))); never@3156: } never@3156: init_page_sizes((size_t) Bsd::page_size()); never@3156: never@3156: Bsd::initialize_system_info(); never@3156: never@3156: // main_thread points to the aboriginal thread never@3156: Bsd::_main_thread = pthread_self(); never@3156: never@3156: Bsd::clock_init(); never@3156: initial_time_count = os::elapsed_counter(); never@3156: never@3156: #ifdef __APPLE__ never@3156: // XXXDARWIN never@3156: // Work around the unaligned VM callbacks in hotspot's never@3156: // sharedRuntime. The callbacks don't use SSE2 instructions, and work on never@3156: // Linux, Solaris, and FreeBSD. On Mac OS X, dyld (rightly so) enforces never@3156: // alignment when doing symbol lookup. To work around this, we force early never@3156: // binding of all symbols now, thus binding when alignment is known-good. never@3156: _dyld_bind_fully_image_containing_address((const void *) &os::init); never@3156: #endif never@3156: } never@3156: never@3156: // To install functions for atexit system call never@3156: extern "C" { never@3156: static void perfMemory_exit_helper() { never@3156: perfMemory_exit(); never@3156: } never@3156: } never@3156: never@3156: // this is called _after_ the global arguments have been parsed never@3156: jint os::init_2(void) never@3156: { never@3156: // Allocate a single page and mark it as readable for safepoint polling never@3156: address polling_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); never@3156: guarantee( polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page" ); never@3156: never@3156: os::set_polling_page( polling_page ); never@3156: never@3156: #ifndef PRODUCT never@3156: if(Verbose && PrintMiscellaneous) never@3156: tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", (intptr_t)polling_page); never@3156: #endif never@3156: never@3156: if (!UseMembar) { never@3156: address mem_serialize_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); never@3156: guarantee( mem_serialize_page != NULL, "mmap Failed for memory serialize page"); never@3156: os::set_memory_serialize_page( mem_serialize_page ); never@3156: never@3156: #ifndef PRODUCT never@3156: if(Verbose && PrintMiscellaneous) never@3156: tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); never@3156: #endif never@3156: } never@3156: never@3156: os::large_page_init(); never@3156: never@3156: // initialize suspend/resume support - must do this before signal_sets_init() never@3156: if (SR_initialize() != 0) { never@3156: perror("SR_initialize failed"); never@3156: return JNI_ERR; never@3156: } never@3156: never@3156: Bsd::signal_sets_init(); never@3156: Bsd::install_signal_handlers(); never@3156: never@3156: // Check minimum allowable stack size for thread creation and to initialize never@3156: // the java system classes, including StackOverflowError - depends on page never@3156: // size. Add a page for compiler2 recursion in main thread. never@3156: // Add in 2*BytesPerWord times page size to account for VM stack during never@3156: // class initialization depending on 32 or 64 bit VM. never@3156: os::Bsd::min_stack_allowed = MAX2(os::Bsd::min_stack_allowed, never@3156: (size_t)(StackYellowPages+StackRedPages+StackShadowPages+ never@3156: 2*BytesPerWord COMPILER2_PRESENT(+1)) * Bsd::page_size()); never@3156: never@3156: size_t threadStackSizeInBytes = ThreadStackSize * K; never@3156: if (threadStackSizeInBytes != 0 && never@3156: threadStackSizeInBytes < os::Bsd::min_stack_allowed) { never@3156: tty->print_cr("\nThe stack size specified is too small, " never@3156: "Specify at least %dk", never@3156: os::Bsd::min_stack_allowed/ K); never@3156: return JNI_ERR; never@3156: } never@3156: never@3156: // Make the stack size a multiple of the page size so that never@3156: // the yellow/red zones can be guarded. never@3156: JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, never@3156: vm_page_size())); never@3156: never@3156: if (MaxFDLimit) { never@3156: // set the number of file descriptors to max. print out error never@3156: // if getrlimit/setrlimit fails but continue regardless. never@3156: struct rlimit nbr_files; never@3156: int status = getrlimit(RLIMIT_NOFILE, &nbr_files); never@3156: if (status != 0) { never@3156: if (PrintMiscellaneous && (Verbose || WizardMode)) never@3156: perror("os::init_2 getrlimit failed"); never@3156: } else { never@3156: nbr_files.rlim_cur = nbr_files.rlim_max; never@3156: never@3156: #ifdef __APPLE__ never@3156: // Darwin returns RLIM_INFINITY for rlim_max, but fails with EINVAL if never@3156: // you attempt to use RLIM_INFINITY. As per setrlimit(2), OPEN_MAX must never@3156: // be used instead never@3156: nbr_files.rlim_cur = MIN(OPEN_MAX, nbr_files.rlim_cur); never@3156: #endif never@3156: never@3156: status = setrlimit(RLIMIT_NOFILE, &nbr_files); never@3156: if (status != 0) { never@3156: if (PrintMiscellaneous && (Verbose || WizardMode)) never@3156: perror("os::init_2 setrlimit failed"); never@3156: } never@3156: } never@3156: } never@3156: never@3156: // at-exit methods are called in the reverse order of their registration. never@3156: // atexit functions are called on return from main or as a result of a never@3156: // call to exit(3C). There can be only 32 of these functions registered never@3156: // and atexit() does not set errno. never@3156: never@3156: if (PerfAllowAtExitRegistration) { never@3156: // only register atexit functions if PerfAllowAtExitRegistration is set. never@3156: // atexit functions can be delayed until process exit time, which never@3156: // can be problematic for embedded VM situations. Embedded VMs should never@3156: // call DestroyJavaVM() to assure that VM resources are released. never@3156: never@3156: // note: perfMemory_exit_helper atexit function may be removed in never@3156: // the future if the appropriate cleanup code can be added to the never@3156: // VM_Exit VMOperation's doit method. never@3156: if (atexit(perfMemory_exit_helper) != 0) { never@3156: warning("os::init2 atexit(perfMemory_exit_helper) failed"); never@3156: } never@3156: } never@3156: never@3156: // initialize thread priority policy never@3156: prio_init(); never@3156: dcubed@3202: #ifdef __APPLE__ dcubed@3202: // dynamically link to objective c gc registration dcubed@3202: void *handleLibObjc = dlopen(OBJC_LIB, RTLD_LAZY); dcubed@3202: if (handleLibObjc != NULL) { dcubed@3202: objc_registerThreadWithCollectorFunction = (objc_registerThreadWithCollector_t) dlsym(handleLibObjc, OBJC_GCREGISTER); dcubed@3202: } dcubed@3202: #endif dcubed@3202: never@3156: return JNI_OK; never@3156: } never@3156: never@3156: // this is called at the end of vm_initialization never@3156: void os::init_3(void) { } never@3156: never@3156: // Mark the polling page as unreadable never@3156: void os::make_polling_page_unreadable(void) { never@3156: if( !guard_memory((char*)_polling_page, Bsd::page_size()) ) never@3156: fatal("Could not disable polling page"); never@3156: }; never@3156: never@3156: // Mark the polling page as readable never@3156: void os::make_polling_page_readable(void) { never@3156: if( !bsd_mprotect((char *)_polling_page, Bsd::page_size(), PROT_READ)) { never@3156: fatal("Could not enable polling page"); never@3156: } never@3156: }; never@3156: never@3156: int os::active_processor_count() { never@3156: return _processor_count; never@3156: } never@3156: dcubed@3202: void os::set_native_thread_name(const char *name) { dcubed@3202: #if defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 dcubed@3202: // This is only supported in Snow Leopard and beyond dcubed@3202: if (name != NULL) { dcubed@3202: // Add a "Java: " prefix to the name dcubed@3202: char buf[MAXTHREADNAMESIZE]; dcubed@3202: snprintf(buf, sizeof(buf), "Java: %s", name); dcubed@3202: pthread_setname_np(buf); dcubed@3202: } dcubed@3202: #endif dcubed@3202: } dcubed@3202: never@3156: bool os::distribute_processes(uint length, uint* distribution) { never@3156: // Not yet implemented. never@3156: return false; never@3156: } never@3156: never@3156: bool os::bind_to_processor(uint processor_id) { never@3156: // Not yet implemented. never@3156: return false; never@3156: } never@3156: never@3156: /// never@3156: never@3156: // Suspends the target using the signal mechanism and then grabs the PC before never@3156: // resuming the target. Used by the flat-profiler only never@3156: ExtendedPC os::get_thread_pc(Thread* thread) { never@3156: // Make sure that it is called by the watcher for the VMThread never@3156: assert(Thread::current()->is_Watcher_thread(), "Must be watcher"); never@3156: assert(thread->is_VM_thread(), "Can only be called for VMThread"); never@3156: never@3156: ExtendedPC epc; never@3156: never@3156: OSThread* osthread = thread->osthread(); never@3156: if (do_suspend(osthread)) { never@3156: if (osthread->ucontext() != NULL) { never@3156: epc = os::Bsd::ucontext_get_pc(osthread->ucontext()); never@3156: } else { never@3156: // NULL context is unexpected, double-check this is the VMThread never@3156: guarantee(thread->is_VM_thread(), "can only be called for VMThread"); never@3156: } never@3156: do_resume(osthread); never@3156: } never@3156: // failure means pthread_kill failed for some reason - arguably this is never@3156: // a fatal problem, but such problems are ignored elsewhere never@3156: never@3156: return epc; never@3156: } never@3156: never@3156: int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) never@3156: { never@3156: return pthread_cond_timedwait(_cond, _mutex, _abstime); never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // debug support never@3156: never@3156: static address same_page(address x, address y) { never@3156: int page_bits = -os::vm_page_size(); never@3156: if ((intptr_t(x) & page_bits) == (intptr_t(y) & page_bits)) never@3156: return x; never@3156: else if (x > y) never@3156: return (address)(intptr_t(y) | ~page_bits) + 1; never@3156: else never@3156: return (address)(intptr_t(y) & page_bits); never@3156: } never@3156: never@3156: bool os::find(address addr, outputStream* st) { never@3156: Dl_info dlinfo; never@3156: memset(&dlinfo, 0, sizeof(dlinfo)); never@3156: if (dladdr(addr, &dlinfo)) { never@3156: st->print(PTR_FORMAT ": ", addr); never@3156: if (dlinfo.dli_sname != NULL) { never@3156: st->print("%s+%#x", dlinfo.dli_sname, never@3156: addr - (intptr_t)dlinfo.dli_saddr); never@3156: } else if (dlinfo.dli_fname) { never@3156: st->print("", addr - (intptr_t)dlinfo.dli_fbase); never@3156: } else { never@3156: st->print(""); never@3156: } never@3156: if (dlinfo.dli_fname) { never@3156: st->print(" in %s", dlinfo.dli_fname); never@3156: } never@3156: if (dlinfo.dli_fbase) { never@3156: st->print(" at " PTR_FORMAT, dlinfo.dli_fbase); never@3156: } never@3156: st->cr(); never@3156: never@3156: if (Verbose) { never@3156: // decode some bytes around the PC never@3156: address begin = same_page(addr-40, addr); never@3156: address end = same_page(addr+40, addr); never@3156: address lowest = (address) dlinfo.dli_sname; never@3156: if (!lowest) lowest = (address) dlinfo.dli_fbase; never@3156: if (begin < lowest) begin = lowest; never@3156: Dl_info dlinfo2; never@3156: if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr never@3156: && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) never@3156: end = (address) dlinfo2.dli_saddr; never@3156: Disassembler::decode(begin, end, st); never@3156: } never@3156: return true; never@3156: } never@3156: return false; never@3156: } never@3156: never@3156: //////////////////////////////////////////////////////////////////////////////// never@3156: // misc never@3156: never@3156: // This does not do anything on Bsd. This is basically a hook for being never@3156: // able to use structured exception handling (thread-local exception filters) never@3156: // on, e.g., Win32. never@3156: void never@3156: os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, never@3156: JavaCallArguments* args, Thread* thread) { never@3156: f(value, method, args, thread); never@3156: } never@3156: never@3156: void os::print_statistics() { never@3156: } never@3156: never@3156: int os::message_box(const char* title, const char* message) { never@3156: int i; never@3156: fdStream err(defaultStream::error_fd()); never@3156: for (i = 0; i < 78; i++) err.print_raw("="); never@3156: err.cr(); never@3156: err.print_raw_cr(title); never@3156: for (i = 0; i < 78; i++) err.print_raw("-"); never@3156: err.cr(); never@3156: err.print_raw_cr(message); never@3156: for (i = 0; i < 78; i++) err.print_raw("="); never@3156: err.cr(); never@3156: never@3156: char buf[16]; never@3156: // Prevent process from exiting upon "read error" without consuming all CPU never@3156: while (::read(0, buf, sizeof(buf)) <= 0) { ::sleep(100); } never@3156: never@3156: return buf[0] == 'y' || buf[0] == 'Y'; never@3156: } never@3156: never@3156: int os::stat(const char *path, struct stat *sbuf) { never@3156: char pathbuf[MAX_PATH]; never@3156: if (strlen(path) > MAX_PATH - 1) { never@3156: errno = ENAMETOOLONG; never@3156: return -1; never@3156: } never@3156: os::native_path(strcpy(pathbuf, path)); never@3156: return ::stat(pathbuf, sbuf); never@3156: } never@3156: never@3156: bool os::check_heap(bool force) { never@3156: return true; never@3156: } never@3156: never@3156: int local_vsnprintf(char* buf, size_t count, const char* format, va_list args) { never@3156: return ::vsnprintf(buf, count, format, args); never@3156: } never@3156: never@3156: // Is a (classpath) directory empty? never@3156: bool os::dir_is_empty(const char* path) { never@3156: DIR *dir = NULL; never@3156: struct dirent *ptr; never@3156: never@3156: dir = opendir(path); never@3156: if (dir == NULL) return true; never@3156: never@3156: /* Scan the directory */ never@3156: bool result = true; never@3156: char buf[sizeof(struct dirent) + MAX_PATH]; never@3156: while (result && (ptr = ::readdir(dir)) != NULL) { never@3156: if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) { never@3156: result = false; never@3156: } never@3156: } never@3156: closedir(dir); never@3156: return result; never@3156: } never@3156: never@3156: // This code originates from JDK's sysOpen and open64_w never@3156: // from src/solaris/hpi/src/system_md.c never@3156: never@3156: #ifndef O_DELETE never@3156: #define O_DELETE 0x10000 never@3156: #endif never@3156: never@3156: // Open a file. Unlink the file immediately after open returns never@3156: // if the specified oflag has the O_DELETE flag set. never@3156: // O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c never@3156: never@3156: int os::open(const char *path, int oflag, int mode) { never@3156: never@3156: if (strlen(path) > MAX_PATH - 1) { never@3156: errno = ENAMETOOLONG; never@3156: return -1; never@3156: } never@3156: int fd; never@3156: int o_delete = (oflag & O_DELETE); never@3156: oflag = oflag & ~O_DELETE; never@3156: never@3156: fd = ::open(path, oflag, mode); never@3156: if (fd == -1) return -1; never@3156: never@3156: //If the open succeeded, the file might still be a directory never@3156: { never@3156: struct stat buf; never@3156: int ret = ::fstat(fd, &buf); never@3156: int st_mode = buf.st_mode; never@3156: never@3156: if (ret != -1) { never@3156: if ((st_mode & S_IFMT) == S_IFDIR) { never@3156: errno = EISDIR; never@3156: ::close(fd); never@3156: return -1; never@3156: } never@3156: } else { never@3156: ::close(fd); never@3156: return -1; never@3156: } never@3156: } never@3156: never@3156: /* never@3156: * All file descriptors that are opened in the JVM and not never@3156: * specifically destined for a subprocess should have the never@3156: * close-on-exec flag set. If we don't set it, then careless 3rd never@3156: * party native code might fork and exec without closing all never@3156: * appropriate file descriptors (e.g. as we do in closeDescriptors in never@3156: * UNIXProcess.c), and this in turn might: never@3156: * never@3156: * - cause end-of-file to fail to be detected on some file never@3156: * descriptors, resulting in mysterious hangs, or never@3156: * never@3156: * - might cause an fopen in the subprocess to fail on a system never@3156: * suffering from bug 1085341. never@3156: * never@3156: * (Yes, the default setting of the close-on-exec flag is a Unix never@3156: * design flaw) never@3156: * never@3156: * See: never@3156: * 1085341: 32-bit stdio routines should support file descriptors >255 never@3156: * 4843136: (process) pipe file descriptor from Runtime.exec not being closed never@3156: * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 never@3156: */ never@3156: #ifdef FD_CLOEXEC never@3156: { never@3156: int flags = ::fcntl(fd, F_GETFD); never@3156: if (flags != -1) never@3156: ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); never@3156: } never@3156: #endif never@3156: never@3156: if (o_delete != 0) { never@3156: ::unlink(path); never@3156: } never@3156: return fd; never@3156: } never@3156: never@3156: never@3156: // create binary file, rewriting existing file if required never@3156: int os::create_binary_file(const char* path, bool rewrite_existing) { never@3156: int oflags = O_WRONLY | O_CREAT; never@3156: if (!rewrite_existing) { never@3156: oflags |= O_EXCL; never@3156: } never@3156: return ::open(path, oflags, S_IREAD | S_IWRITE); never@3156: } never@3156: never@3156: // return current position of file pointer never@3156: jlong os::current_file_offset(int fd) { never@3156: return (jlong)::lseek(fd, (off_t)0, SEEK_CUR); never@3156: } never@3156: never@3156: // move file pointer to the specified offset never@3156: jlong os::seek_to_file_offset(int fd, jlong offset) { never@3156: return (jlong)::lseek(fd, (off_t)offset, SEEK_SET); never@3156: } never@3156: never@3156: // This code originates from JDK's sysAvailable never@3156: // from src/solaris/hpi/src/native_threads/src/sys_api_td.c never@3156: never@3156: int os::available(int fd, jlong *bytes) { never@3156: jlong cur, end; never@3156: int mode; never@3156: struct stat buf; never@3156: never@3156: if (::fstat(fd, &buf) >= 0) { never@3156: mode = buf.st_mode; never@3156: if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { never@3156: /* never@3156: * XXX: is the following call interruptible? If so, this might never@3156: * need to go through the INTERRUPT_IO() wrapper as for other never@3156: * blocking, interruptible calls in this file. never@3156: */ never@3156: int n; never@3156: if (::ioctl(fd, FIONREAD, &n) >= 0) { never@3156: *bytes = n; never@3156: return 1; never@3156: } never@3156: } never@3156: } never@3156: if ((cur = ::lseek(fd, 0L, SEEK_CUR)) == -1) { never@3156: return 0; never@3156: } else if ((end = ::lseek(fd, 0L, SEEK_END)) == -1) { never@3156: return 0; never@3156: } else if (::lseek(fd, cur, SEEK_SET) == -1) { never@3156: return 0; never@3156: } never@3156: *bytes = end - cur; never@3156: return 1; never@3156: } never@3156: never@3156: int os::socket_available(int fd, jint *pbytes) { never@3156: if (fd < 0) never@3156: return OS_OK; never@3156: never@3156: int ret; never@3156: never@3156: RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret); never@3156: never@3156: //%% note ioctl can return 0 when successful, JVM_SocketAvailable never@3156: // is expected to return 0 on failure and 1 on success to the jdk. never@3156: never@3156: return (ret == OS_ERR) ? 0 : 1; never@3156: } never@3156: never@3156: // Map a block of memory. zgu@3900: char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, never@3156: char *addr, size_t bytes, bool read_only, never@3156: bool allow_exec) { never@3156: int prot; never@3156: int flags; never@3156: never@3156: if (read_only) { never@3156: prot = PROT_READ; never@3156: flags = MAP_SHARED; never@3156: } else { never@3156: prot = PROT_READ | PROT_WRITE; never@3156: flags = MAP_PRIVATE; never@3156: } never@3156: never@3156: if (allow_exec) { never@3156: prot |= PROT_EXEC; never@3156: } never@3156: never@3156: if (addr != NULL) { never@3156: flags |= MAP_FIXED; never@3156: } never@3156: never@3156: char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags, never@3156: fd, file_offset); never@3156: if (mapped_address == MAP_FAILED) { never@3156: return NULL; never@3156: } never@3156: return mapped_address; never@3156: } never@3156: never@3156: never@3156: // Remap a block of memory. zgu@3900: char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset, never@3156: char *addr, size_t bytes, bool read_only, never@3156: bool allow_exec) { never@3156: // same as map_memory() on this OS never@3156: return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only, never@3156: allow_exec); never@3156: } never@3156: never@3156: never@3156: // Unmap a block of memory. zgu@3900: bool os::pd_unmap_memory(char* addr, size_t bytes) { never@3156: return munmap(addr, bytes) == 0; never@3156: } never@3156: never@3156: // current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool) never@3156: // are used by JVM M&M and JVMTI to get user+sys or user CPU time never@3156: // of a thread. never@3156: // never@3156: // current_thread_cpu_time() and thread_cpu_time(Thread*) returns never@3156: // the fast estimate available on the platform. never@3156: never@3156: jlong os::current_thread_cpu_time() { never@3156: #ifdef __APPLE__ never@3156: return os::thread_cpu_time(Thread::current(), true /* user + sys */); morris@4689: #else morris@4689: Unimplemented(); morris@4689: return 0; never@3156: #endif never@3156: } never@3156: never@3156: jlong os::thread_cpu_time(Thread* thread) { morris@4689: #ifdef __APPLE__ morris@4689: return os::thread_cpu_time(thread, true /* user + sys */); morris@4689: #else morris@4689: Unimplemented(); morris@4689: return 0; morris@4689: #endif never@3156: } never@3156: never@3156: jlong os::current_thread_cpu_time(bool user_sys_cpu_time) { never@3156: #ifdef __APPLE__ never@3156: return os::thread_cpu_time(Thread::current(), user_sys_cpu_time); morris@4689: #else morris@4689: Unimplemented(); morris@4689: return 0; never@3156: #endif never@3156: } never@3156: never@3156: jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { never@3156: #ifdef __APPLE__ never@3156: struct thread_basic_info tinfo; never@3156: mach_msg_type_number_t tcount = THREAD_INFO_MAX; never@3156: kern_return_t kr; sla@3587: thread_t mach_thread; sla@3587: sla@3587: mach_thread = thread->osthread()->thread_id(); never@3156: kr = thread_info(mach_thread, THREAD_BASIC_INFO, (thread_info_t)&tinfo, &tcount); never@3156: if (kr != KERN_SUCCESS) never@3156: return -1; never@3156: never@3156: if (user_sys_cpu_time) { never@3156: jlong nanos; never@3156: nanos = ((jlong) tinfo.system_time.seconds + tinfo.user_time.seconds) * (jlong)1000000000; never@3156: nanos += ((jlong) tinfo.system_time.microseconds + (jlong) tinfo.user_time.microseconds) * (jlong)1000; never@3156: return nanos; never@3156: } else { never@3156: return ((jlong)tinfo.user_time.seconds * 1000000000) + ((jlong)tinfo.user_time.microseconds * (jlong)1000); never@3156: } morris@4689: #else morris@4689: Unimplemented(); morris@4689: return 0; never@3156: #endif never@3156: } never@3156: never@3156: never@3156: void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { never@3156: info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits never@3156: info_ptr->may_skip_backward = false; // elapsed time not wall time never@3156: info_ptr->may_skip_forward = false; // elapsed time not wall time never@3156: info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned never@3156: } never@3156: never@3156: void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { never@3156: info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits never@3156: info_ptr->may_skip_backward = false; // elapsed time not wall time never@3156: info_ptr->may_skip_forward = false; // elapsed time not wall time never@3156: info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned never@3156: } never@3156: never@3156: bool os::is_thread_cpu_time_supported() { never@3156: #ifdef __APPLE__ never@3156: return true; sla@4229: #else never@3156: return false; never@3156: #endif never@3156: } never@3156: never@3156: // System loadavg support. Returns -1 if load average cannot be obtained. never@3156: // Bsd doesn't yet have a (official) notion of processor sets, never@3156: // so just return the system wide load average. never@3156: int os::loadavg(double loadavg[], int nelem) { never@3156: return ::getloadavg(loadavg, nelem); never@3156: } never@3156: never@3156: void os::pause() { never@3156: char filename[MAX_PATH]; never@3156: if (PauseAtStartupFile && PauseAtStartupFile[0]) { never@3156: jio_snprintf(filename, MAX_PATH, PauseAtStartupFile); never@3156: } else { never@3156: jio_snprintf(filename, MAX_PATH, "./vm.paused.%d", current_process_id()); never@3156: } never@3156: never@3156: int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); never@3156: if (fd != -1) { never@3156: struct stat buf; never@3156: ::close(fd); never@3156: while (::stat(filename, &buf) == 0) { never@3156: (void)::poll(NULL, 0, 100); never@3156: } never@3156: } else { never@3156: jio_fprintf(stderr, never@3156: "Could not open pause file '%s', continuing immediately.\n", filename); never@3156: } never@3156: } never@3156: never@3156: never@3156: // Refer to the comments in os_solaris.cpp park-unpark. never@3156: // never@3156: // Beware -- Some versions of NPTL embody a flaw where pthread_cond_timedwait() can never@3156: // hang indefinitely. For instance NPTL 0.60 on 2.4.21-4ELsmp is vulnerable. never@3156: // For specifics regarding the bug see GLIBC BUGID 261237 : never@3156: // http://www.mail-archive.com/debian-glibc@lists.debian.org/msg10837.html. never@3156: // Briefly, pthread_cond_timedwait() calls with an expiry time that's not in the future never@3156: // will either hang or corrupt the condvar, resulting in subsequent hangs if the condvar never@3156: // is used. (The simple C test-case provided in the GLIBC bug report manifests the never@3156: // hang). The JVM is vulernable via sleep(), Object.wait(timo), LockSupport.parkNanos() never@3156: // and monitorenter when we're using 1-0 locking. All those operations may result in never@3156: // calls to pthread_cond_timedwait(). Using LD_ASSUME_KERNEL to use an older version never@3156: // of libpthread avoids the problem, but isn't practical. never@3156: // never@3156: // Possible remedies: never@3156: // never@3156: // 1. Establish a minimum relative wait time. 50 to 100 msecs seems to work. never@3156: // This is palliative and probabilistic, however. If the thread is preempted never@3156: // between the call to compute_abstime() and pthread_cond_timedwait(), more never@3156: // than the minimum period may have passed, and the abstime may be stale (in the never@3156: // past) resultin in a hang. Using this technique reduces the odds of a hang never@3156: // but the JVM is still vulnerable, particularly on heavily loaded systems. never@3156: // never@3156: // 2. Modify park-unpark to use per-thread (per ParkEvent) pipe-pairs instead never@3156: // of the usual flag-condvar-mutex idiom. The write side of the pipe is set never@3156: // NDELAY. unpark() reduces to write(), park() reduces to read() and park(timo) never@3156: // reduces to poll()+read(). This works well, but consumes 2 FDs per extant never@3156: // thread. never@3156: // never@3156: // 3. Embargo pthread_cond_timedwait() and implement a native "chron" thread never@3156: // that manages timeouts. We'd emulate pthread_cond_timedwait() by enqueuing never@3156: // a timeout request to the chron thread and then blocking via pthread_cond_wait(). never@3156: // This also works well. In fact it avoids kernel-level scalability impediments never@3156: // on certain platforms that don't handle lots of active pthread_cond_timedwait() never@3156: // timers in a graceful fashion. never@3156: // never@3156: // 4. When the abstime value is in the past it appears that control returns never@3156: // correctly from pthread_cond_timedwait(), but the condvar is left corrupt. never@3156: // Subsequent timedwait/wait calls may hang indefinitely. Given that, we never@3156: // can avoid the problem by reinitializing the condvar -- by cond_destroy() never@3156: // followed by cond_init() -- after all calls to pthread_cond_timedwait(). never@3156: // It may be possible to avoid reinitialization by checking the return never@3156: // value from pthread_cond_timedwait(). In addition to reinitializing the never@3156: // condvar we must establish the invariant that cond_signal() is only called never@3156: // within critical sections protected by the adjunct mutex. This prevents never@3156: // cond_signal() from "seeing" a condvar that's in the midst of being never@3156: // reinitialized or that is corrupt. Sadly, this invariant obviates the never@3156: // desirable signal-after-unlock optimization that avoids futile context switching. never@3156: // never@3156: // I'm also concerned that some versions of NTPL might allocate an auxilliary never@3156: // structure when a condvar is used or initialized. cond_destroy() would never@3156: // release the helper structure. Our reinitialize-after-timedwait fix never@3156: // put excessive stress on malloc/free and locks protecting the c-heap. never@3156: // never@3156: // We currently use (4). See the WorkAroundNTPLTimedWaitHang flag. never@3156: // It may be possible to refine (4) by checking the kernel and NTPL verisons never@3156: // and only enabling the work-around for vulnerable environments. never@3156: never@3156: // utility to compute the abstime argument to timedwait: never@3156: // millis is the relative timeout time never@3156: // abstime will be the absolute timeout time never@3156: // TODO: replace compute_abstime() with unpackTime() never@3156: never@3156: static struct timespec* compute_abstime(struct timespec* abstime, jlong millis) { never@3156: if (millis < 0) millis = 0; never@3156: struct timeval now; never@3156: int status = gettimeofday(&now, NULL); never@3156: assert(status == 0, "gettimeofday"); never@3156: jlong seconds = millis / 1000; never@3156: millis %= 1000; never@3156: if (seconds > 50000000) { // see man cond_timedwait(3T) never@3156: seconds = 50000000; never@3156: } never@3156: abstime->tv_sec = now.tv_sec + seconds; never@3156: long usec = now.tv_usec + millis * 1000; never@3156: if (usec >= 1000000) { never@3156: abstime->tv_sec += 1; never@3156: usec -= 1000000; never@3156: } never@3156: abstime->tv_nsec = usec * 1000; never@3156: return abstime; never@3156: } never@3156: never@3156: never@3156: // Test-and-clear _Event, always leaves _Event set to 0, returns immediately. never@3156: // Conceptually TryPark() should be equivalent to park(0). never@3156: never@3156: int os::PlatformEvent::TryPark() { never@3156: for (;;) { never@3156: const int v = _Event ; never@3156: guarantee ((v == 0) || (v == 1), "invariant") ; never@3156: if (Atomic::cmpxchg (0, &_Event, v) == v) return v ; never@3156: } never@3156: } never@3156: never@3156: void os::PlatformEvent::park() { // AKA "down()" never@3156: // Invariant: Only the thread associated with the Event/PlatformEvent never@3156: // may call park(). never@3156: // TODO: assert that _Assoc != NULL or _Assoc == Self never@3156: int v ; never@3156: for (;;) { never@3156: v = _Event ; never@3156: if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; never@3156: } never@3156: guarantee (v >= 0, "invariant") ; never@3156: if (v == 0) { never@3156: // Do this the hard way by blocking ... never@3156: int status = pthread_mutex_lock(_mutex); never@3156: assert_status(status == 0, status, "mutex_lock"); never@3156: guarantee (_nParked == 0, "invariant") ; never@3156: ++ _nParked ; never@3156: while (_Event < 0) { never@3156: status = pthread_cond_wait(_cond, _mutex); never@3156: // for some reason, under 2.7 lwp_cond_wait() may return ETIME ... never@3156: // Treat this the same as if the wait was interrupted never@3156: if (status == ETIMEDOUT) { status = EINTR; } never@3156: assert_status(status == 0 || status == EINTR, status, "cond_wait"); never@3156: } never@3156: -- _nParked ; never@3156: never@3156: _Event = 0 ; never@3156: status = pthread_mutex_unlock(_mutex); never@3156: assert_status(status == 0, status, "mutex_unlock"); dcubed@4471: // Paranoia to ensure our locked and lock-free paths interact dcubed@4471: // correctly with each other. dcubed@4471: OrderAccess::fence(); never@3156: } never@3156: guarantee (_Event >= 0, "invariant") ; never@3156: } never@3156: never@3156: int os::PlatformEvent::park(jlong millis) { never@3156: guarantee (_nParked == 0, "invariant") ; never@3156: never@3156: int v ; never@3156: for (;;) { never@3156: v = _Event ; never@3156: if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ; never@3156: } never@3156: guarantee (v >= 0, "invariant") ; never@3156: if (v != 0) return OS_OK ; never@3156: never@3156: // We do this the hard way, by blocking the thread. never@3156: // Consider enforcing a minimum timeout value. never@3156: struct timespec abst; never@3156: compute_abstime(&abst, millis); never@3156: never@3156: int ret = OS_TIMEOUT; never@3156: int status = pthread_mutex_lock(_mutex); never@3156: assert_status(status == 0, status, "mutex_lock"); never@3156: guarantee (_nParked == 0, "invariant") ; never@3156: ++_nParked ; never@3156: never@3156: // Object.wait(timo) will return because of never@3156: // (a) notification never@3156: // (b) timeout never@3156: // (c) thread.interrupt never@3156: // never@3156: // Thread.interrupt and object.notify{All} both call Event::set. never@3156: // That is, we treat thread.interrupt as a special case of notification. never@3156: // The underlying Solaris implementation, cond_timedwait, admits never@3156: // spurious/premature wakeups, but the JLS/JVM spec prevents the never@3156: // JVM from making those visible to Java code. As such, we must never@3156: // filter out spurious wakeups. We assume all ETIME returns are valid. never@3156: // never@3156: // TODO: properly differentiate simultaneous notify+interrupt. never@3156: // In that case, we should propagate the notify to another waiter. never@3156: never@3156: while (_Event < 0) { never@3156: status = os::Bsd::safe_cond_timedwait(_cond, _mutex, &abst); never@3156: if (status != 0 && WorkAroundNPTLTimedWaitHang) { never@3156: pthread_cond_destroy (_cond); never@3156: pthread_cond_init (_cond, NULL) ; never@3156: } never@3156: assert_status(status == 0 || status == EINTR || never@3156: status == ETIMEDOUT, never@3156: status, "cond_timedwait"); never@3156: if (!FilterSpuriousWakeups) break ; // previous semantics never@3156: if (status == ETIMEDOUT) break ; never@3156: // We consume and ignore EINTR and spurious wakeups. never@3156: } never@3156: --_nParked ; never@3156: if (_Event >= 0) { never@3156: ret = OS_OK; never@3156: } never@3156: _Event = 0 ; never@3156: status = pthread_mutex_unlock(_mutex); never@3156: assert_status(status == 0, status, "mutex_unlock"); never@3156: assert (_nParked == 0, "invariant") ; dcubed@4471: // Paranoia to ensure our locked and lock-free paths interact dcubed@4471: // correctly with each other. dcubed@4471: OrderAccess::fence(); never@3156: return ret; never@3156: } never@3156: never@3156: void os::PlatformEvent::unpark() { dcubed@4471: // Transitions for _Event: dcubed@4471: // 0 :=> 1 dcubed@4471: // 1 :=> 1 dcubed@4471: // -1 :=> either 0 or 1; must signal target thread dcubed@4471: // That is, we can safely transition _Event from -1 to either dcubed@4471: // 0 or 1. Forcing 1 is slightly more efficient for back-to-back dcubed@4471: // unpark() calls. dcubed@4471: // See also: "Semaphores in Plan 9" by Mullender & Cox dcubed@4471: // dcubed@4471: // Note: Forcing a transition from "-1" to "1" on an unpark() means dcubed@4471: // that it will take two back-to-back park() calls for the owning dcubed@4471: // thread to block. This has the benefit of forcing a spurious return dcubed@4471: // from the first park() call after an unpark() call which will help dcubed@4471: // shake out uses of park() and unpark() without condition variables. dcubed@4471: dcubed@4471: if (Atomic::xchg(1, &_Event) >= 0) return; dcubed@4471: dcubed@4471: // Wait for the thread associated with the event to vacate dcubed@4471: int status = pthread_mutex_lock(_mutex); dcubed@4471: assert_status(status == 0, status, "mutex_lock"); dcubed@4471: int AnyWaiters = _nParked; dcubed@4471: assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); dcubed@4471: if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { dcubed@4471: AnyWaiters = 0; dcubed@4471: pthread_cond_signal(_cond); never@3156: } dcubed@4471: status = pthread_mutex_unlock(_mutex); dcubed@4471: assert_status(status == 0, status, "mutex_unlock"); dcubed@4471: if (AnyWaiters != 0) { dcubed@4471: status = pthread_cond_signal(_cond); dcubed@4471: assert_status(status == 0, status, "cond_signal"); never@3156: } never@3156: never@3156: // Note that we signal() _after dropping the lock for "immortal" Events. never@3156: // This is safe and avoids a common class of futile wakeups. In rare never@3156: // circumstances this can cause a thread to return prematurely from never@3156: // cond_{timed}wait() but the spurious wakeup is benign and the victim will never@3156: // simply re-test the condition and re-park itself. never@3156: } never@3156: never@3156: never@3156: // JSR166 never@3156: // ------------------------------------------------------- never@3156: never@3156: /* never@3156: * The solaris and bsd implementations of park/unpark are fairly never@3156: * conservative for now, but can be improved. They currently use a never@3156: * mutex/condvar pair, plus a a count. never@3156: * Park decrements count if > 0, else does a condvar wait. Unpark never@3156: * sets count to 1 and signals condvar. Only one thread ever waits never@3156: * on the condvar. Contention seen when trying to park implies that someone never@3156: * is unparking you, so don't wait. And spurious returns are fine, so there never@3156: * is no need to track notifications. never@3156: */ never@3156: never@3156: #define MAX_SECS 100000000 never@3156: /* never@3156: * This code is common to bsd and solaris and will be moved to a never@3156: * common place in dolphin. never@3156: * never@3156: * The passed in time value is either a relative time in nanoseconds never@3156: * or an absolute time in milliseconds. Either way it has to be unpacked never@3156: * into suitable seconds and nanoseconds components and stored in the never@3156: * given timespec structure. never@3156: * Given time is a 64-bit value and the time_t used in the timespec is only never@3156: * a signed-32-bit value (except on 64-bit Bsd) we have to watch for never@3156: * overflow if times way in the future are given. Further on Solaris versions never@3156: * prior to 10 there is a restriction (see cond_timedwait) that the specified never@3156: * number of seconds, in abstime, is less than current_time + 100,000,000. never@3156: * As it will be 28 years before "now + 100000000" will overflow we can never@3156: * ignore overflow and just impose a hard-limit on seconds using the value never@3156: * of "now + 100,000,000". This places a limit on the timeout of about 3.17 never@3156: * years from "now". never@3156: */ never@3156: never@3156: static void unpackTime(struct timespec* absTime, bool isAbsolute, jlong time) { never@3156: assert (time > 0, "convertTime"); never@3156: never@3156: struct timeval now; never@3156: int status = gettimeofday(&now, NULL); never@3156: assert(status == 0, "gettimeofday"); never@3156: never@3156: time_t max_secs = now.tv_sec + MAX_SECS; never@3156: never@3156: if (isAbsolute) { never@3156: jlong secs = time / 1000; never@3156: if (secs > max_secs) { never@3156: absTime->tv_sec = max_secs; never@3156: } never@3156: else { never@3156: absTime->tv_sec = secs; never@3156: } never@3156: absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; never@3156: } never@3156: else { never@3156: jlong secs = time / NANOSECS_PER_SEC; never@3156: if (secs >= MAX_SECS) { never@3156: absTime->tv_sec = max_secs; never@3156: absTime->tv_nsec = 0; never@3156: } never@3156: else { never@3156: absTime->tv_sec = now.tv_sec + secs; never@3156: absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000; never@3156: if (absTime->tv_nsec >= NANOSECS_PER_SEC) { never@3156: absTime->tv_nsec -= NANOSECS_PER_SEC; never@3156: ++absTime->tv_sec; // note: this must be <= max_secs never@3156: } never@3156: } never@3156: } never@3156: assert(absTime->tv_sec >= 0, "tv_sec < 0"); never@3156: assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs"); never@3156: assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); never@3156: assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); never@3156: } never@3156: never@3156: void Parker::park(bool isAbsolute, jlong time) { dcubed@4471: // Ideally we'd do something useful while spinning, such dcubed@4471: // as calling unpackTime(). dcubed@4471: never@3156: // Optional fast-path check: never@3156: // Return immediately if a permit is available. dcubed@4471: // We depend on Atomic::xchg() having full barrier semantics dcubed@4471: // since we are doing a lock-free update to _counter. dcubed@4471: if (Atomic::xchg(0, &_counter) > 0) return; never@3156: never@3156: Thread* thread = Thread::current(); never@3156: assert(thread->is_Java_thread(), "Must be JavaThread"); never@3156: JavaThread *jt = (JavaThread *)thread; never@3156: never@3156: // Optional optimization -- avoid state transitions if there's an interrupt pending. never@3156: // Check interrupt before trying to wait never@3156: if (Thread::is_interrupted(thread, false)) { never@3156: return; never@3156: } never@3156: never@3156: // Next, demultiplex/decode time arguments never@3156: struct timespec absTime; never@3156: if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all never@3156: return; never@3156: } never@3156: if (time > 0) { never@3156: unpackTime(&absTime, isAbsolute, time); never@3156: } never@3156: never@3156: never@3156: // Enter safepoint region never@3156: // Beware of deadlocks such as 6317397. never@3156: // The per-thread Parker:: mutex is a classic leaf-lock. never@3156: // In particular a thread must never block on the Threads_lock while never@3156: // holding the Parker:: mutex. If safepoints are pending both the never@3156: // the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock. never@3156: ThreadBlockInVM tbivm(jt); never@3156: never@3156: // Don't wait if cannot get lock since interference arises from never@3156: // unblocking. Also. check interrupt before trying wait never@3156: if (Thread::is_interrupted(thread, false) || pthread_mutex_trylock(_mutex) != 0) { never@3156: return; never@3156: } never@3156: never@3156: int status ; never@3156: if (_counter > 0) { // no wait needed never@3156: _counter = 0; never@3156: status = pthread_mutex_unlock(_mutex); never@3156: assert (status == 0, "invariant") ; dcubed@4471: // Paranoia to ensure our locked and lock-free paths interact dcubed@4471: // correctly with each other and Java-level accesses. never@3156: OrderAccess::fence(); never@3156: return; never@3156: } never@3156: never@3156: #ifdef ASSERT never@3156: // Don't catch signals while blocked; let the running threads have the signals. never@3156: // (This allows a debugger to break into the running thread.) never@3156: sigset_t oldsigs; never@3156: sigset_t* allowdebug_blocked = os::Bsd::allowdebug_blocked_signals(); never@3156: pthread_sigmask(SIG_BLOCK, allowdebug_blocked, &oldsigs); never@3156: #endif never@3156: never@3156: OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); never@3156: jt->set_suspend_equivalent(); never@3156: // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() never@3156: never@3156: if (time == 0) { never@3156: status = pthread_cond_wait (_cond, _mutex) ; never@3156: } else { never@3156: status = os::Bsd::safe_cond_timedwait (_cond, _mutex, &absTime) ; never@3156: if (status != 0 && WorkAroundNPTLTimedWaitHang) { never@3156: pthread_cond_destroy (_cond) ; never@3156: pthread_cond_init (_cond, NULL); never@3156: } never@3156: } never@3156: assert_status(status == 0 || status == EINTR || never@3156: status == ETIMEDOUT, never@3156: status, "cond_timedwait"); never@3156: never@3156: #ifdef ASSERT never@3156: pthread_sigmask(SIG_SETMASK, &oldsigs, NULL); never@3156: #endif never@3156: never@3156: _counter = 0 ; never@3156: status = pthread_mutex_unlock(_mutex) ; never@3156: assert_status(status == 0, status, "invariant") ; dcubed@4471: // Paranoia to ensure our locked and lock-free paths interact dcubed@4471: // correctly with each other and Java-level accesses. dcubed@4471: OrderAccess::fence(); dcubed@4471: never@3156: // If externally suspended while waiting, re-suspend never@3156: if (jt->handle_special_suspend_equivalent_condition()) { never@3156: jt->java_suspend_self(); never@3156: } never@3156: } never@3156: never@3156: void Parker::unpark() { never@3156: int s, status ; never@3156: status = pthread_mutex_lock(_mutex); never@3156: assert (status == 0, "invariant") ; never@3156: s = _counter; never@3156: _counter = 1; never@3156: if (s < 1) { never@3156: if (WorkAroundNPTLTimedWaitHang) { never@3156: status = pthread_cond_signal (_cond) ; never@3156: assert (status == 0, "invariant") ; never@3156: status = pthread_mutex_unlock(_mutex); never@3156: assert (status == 0, "invariant") ; never@3156: } else { never@3156: status = pthread_mutex_unlock(_mutex); never@3156: assert (status == 0, "invariant") ; never@3156: status = pthread_cond_signal (_cond) ; never@3156: assert (status == 0, "invariant") ; never@3156: } never@3156: } else { never@3156: pthread_mutex_unlock(_mutex); never@3156: assert (status == 0, "invariant") ; never@3156: } never@3156: } never@3156: never@3156: never@3156: /* Darwin has no "environ" in a dynamic library. */ never@3156: #ifdef __APPLE__ never@3156: #include never@3156: #define environ (*_NSGetEnviron()) never@3156: #else never@3156: extern char** environ; never@3156: #endif never@3156: never@3156: // Run the specified command in a separate process. Return its exit value, never@3156: // or -1 on failure (e.g. can't fork a new process). never@3156: // Unlike system(), this function can be called from signal handler. It never@3156: // doesn't block SIGINT et al. never@3156: int os::fork_and_exec(char* cmd) { never@3156: const char * argv[4] = {"sh", "-c", cmd, NULL}; never@3156: never@3156: // fork() in BsdThreads/NPTL is not async-safe. It needs to run never@3156: // pthread_atfork handlers and reset pthread library. All we need is a never@3156: // separate process to execve. Make a direct syscall to fork process. never@3156: // On IA64 there's no fork syscall, we have to use fork() and hope for never@3156: // the best... never@3156: pid_t pid = fork(); never@3156: never@3156: if (pid < 0) { never@3156: // fork failed never@3156: return -1; never@3156: never@3156: } else if (pid == 0) { never@3156: // child process never@3156: never@3156: // execve() in BsdThreads will call pthread_kill_other_threads_np() never@3156: // first to kill every thread on the thread list. Because this list is never@3156: // not reset by fork() (see notes above), execve() will instead kill never@3156: // every thread in the parent process. We know this is the only thread never@3156: // in the new process, so make a system call directly. never@3156: // IA64 should use normal execve() from glibc to match the glibc fork() never@3156: // above. never@3156: execve("/bin/sh", (char* const*)argv, environ); never@3156: never@3156: // execve failed never@3156: _exit(-1); never@3156: never@3156: } else { never@3156: // copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't never@3156: // care about the actual exit code, for now. never@3156: never@3156: int status; never@3156: never@3156: // Wait for the child process to exit. This returns immediately if never@3156: // the child has already exited. */ never@3156: while (waitpid(pid, &status, 0) < 0) { never@3156: switch (errno) { never@3156: case ECHILD: return 0; never@3156: case EINTR: break; never@3156: default: return -1; never@3156: } never@3156: } never@3156: never@3156: if (WIFEXITED(status)) { never@3156: // The child exited normally; get its exit code. never@3156: return WEXITSTATUS(status); never@3156: } else if (WIFSIGNALED(status)) { never@3156: // The child exited because of a signal never@3156: // The best value to return is 0x80 + signal number, never@3156: // because that is what all Unix shells do, and because never@3156: // it allows callers to distinguish between process exit and never@3156: // process death by signal. never@3156: return 0x80 + WTERMSIG(status); never@3156: } else { never@3156: // Unknown exit code; pass it through never@3156: return status; never@3156: } never@3156: } never@3156: } never@3156: never@3156: // is_headless_jre() never@3156: // dholmes@3281: // Test for the existence of xawt/libmawt.so or libawt_xawt.so never@3156: // in order to report if we are running in a headless jre never@3156: // dholmes@3281: // Since JDK8 xawt/libmawt.so was moved into the same directory dholmes@3281: // as libawt.so, and renamed libawt_xawt.so dholmes@3281: // never@3156: bool os::is_headless_jre() { never@3156: struct stat statbuf; never@3156: char buf[MAXPATHLEN]; never@3156: char libmawtpath[MAXPATHLEN]; dcubed@3202: const char *xawtstr = "/xawt/libmawt" JNI_LIB_SUFFIX; dcubed@3625: const char *new_xawtstr = "/libawt_xawt" JNI_LIB_SUFFIX; never@3156: char *p; never@3156: never@3156: // Get path to libjvm.so never@3156: os::jvm_path(buf, sizeof(buf)); never@3156: never@3156: // Get rid of libjvm.so never@3156: p = strrchr(buf, '/'); never@3156: if (p == NULL) return false; never@3156: else *p = '\0'; never@3156: never@3156: // Get rid of client or server never@3156: p = strrchr(buf, '/'); never@3156: if (p == NULL) return false; never@3156: else *p = '\0'; never@3156: never@3156: // check xawt/libmawt.so never@3156: strcpy(libmawtpath, buf); never@3156: strcat(libmawtpath, xawtstr); never@3156: if (::stat(libmawtpath, &statbuf) == 0) return false; never@3156: dholmes@3281: // check libawt_xawt.so never@3156: strcpy(libmawtpath, buf); dholmes@3281: strcat(libmawtpath, new_xawtstr); never@3156: if (::stat(libmawtpath, &statbuf) == 0) return false; never@3156: never@3156: return true; never@3156: } mikael@3903: mikael@3903: // Get the default path to the core file mikael@3903: // Returns the length of the string mikael@3903: int os::get_core_path(char* buffer, size_t bufferSize) { mikael@3903: int n = jio_snprintf(buffer, bufferSize, "/cores"); mikael@3903: mikael@3903: // Truncate if theoretical string was longer than bufferSize mikael@3903: n = MIN2(n, (int)bufferSize); mikael@3903: mikael@3903: return n; mikael@3903: }