diff -Nur icedtea-2.4.7.orig/Makefile.in icedtea-2.4.7/Makefile.in --- icedtea-2.4.7.orig/Makefile.in 2014-04-16 06:20:44.689988653 +0200 +++ icedtea-2.4.7/Makefile.in 2014-05-01 13:34:58.421434811 +0200 @@ -712,7 +712,7 @@ $(am__append_14) $(am__append_15) $(DISTRIBUTION_PATCHES) # Bootstrapping patches -ICEDTEA_BOOT_PATCHES = patches/boot/javafiles.patch \ +ICEDTEA_BOOT_PATCHES = patches/openadk.patch patches/boot/javafiles.patch \ patches/boot/ant-javac.patch patches/boot/corba-idlj.patch \ patches/boot/corba-no-gen.patch patches/boot/corba-orb.patch \ patches/boot/demos.patch patches/boot/fphexconstants.patch \ diff -Nur icedtea-2.4.7.orig/patches/openadk.patch icedtea-2.4.7/patches/openadk.patch --- icedtea-2.4.7.orig/patches/openadk.patch 1970-01-01 01:00:00.000000000 +0100 +++ icedtea-2.4.7/patches/openadk.patch 2014-05-13 16:57:07.173804037 +0200 @@ -0,0 +1,7009 @@ +diff -Nur openjdk.orig/hotspot/make/linux/makefiles/zeroshark.make openjdk/hotspot/make/linux/makefiles/zeroshark.make +--- openjdk.orig/hotspot/make/linux/makefiles/zeroshark.make 2014-02-20 19:51:45.000000000 +0100 ++++ openjdk/hotspot/make/linux/makefiles/zeroshark.make 2014-05-13 16:56:38.917714592 +0200 +@@ -39,20 +39,20 @@ + + offsets_arm.s: mkoffsets + @echo Generating assembler offsets +- ./mkoffsets > $@ ++ $(QEMU) ./mkoffsets > $@ + + bytecodes_arm.s: bytecodes_arm.def mkbc + @echo Generating ARM assembler bytecode sequences +- $(CXX_COMPILE) -E -x c++ - < $< | ./mkbc - $@ $(COMPILE_DONE) ++ $(CXX_COMPILE) -E -x c++ - < $< | $(QEMU) ./mkbc - $@ $(COMPILE_DONE) + + mkbc: $(GAMMADIR)/tools/mkbc.c + @echo Compiling mkbc tool +- $(CC_COMPILE) -o $@ $< $(COMPILE_DONE) ++ $(CC_COMPILE) -static -o $@ $< $(COMPILE_DONE) + + mkoffsets: asm_helper.cpp + @echo Compiling offset generator + $(QUIETLY) $(REMOVE_TARGET) +- $(CXX_COMPILE) -DSTATIC_OFFSETS -o $@ $< $(COMPILE_DONE) ++ $(CXX_COMPILE) -static -DSTATIC_OFFSETS -o $@ $< $(COMPILE_DONE) + + endif + endif +diff -Nur openjdk.orig/hotspot/src/os/linux/vm/os_linux.cpp openjdk/hotspot/src/os/linux/vm/os_linux.cpp +--- openjdk.orig/hotspot/src/os/linux/vm/os_linux.cpp 2014-02-20 19:51:45.000000000 +0100 ++++ openjdk/hotspot/src/os/linux/vm/os_linux.cpp 2014-05-13 16:14:56.637091447 +0200 +@@ -112,7 +112,6 @@ + # include + # include + # include +-# include + # include + # include + # include +@@ -650,9 +649,7 @@ + os::Linux::set_glibc_version(str); + } else { + // _CS_GNU_LIBC_VERSION is not supported, try gnu_get_libc_version() +- static char _gnu_libc_version[32]; +- jio_snprintf(_gnu_libc_version, sizeof(_gnu_libc_version), +- "glibc %s %s", gnu_get_libc_version(), gnu_get_libc_release()); ++ static char _gnu_libc_version[32] = "2.9"; + os::Linux::set_glibc_version(_gnu_libc_version); + } + +@@ -2951,10 +2948,7 @@ + // If we are running with earlier version, which did not have symbol versions, + // we should use the base version. + void* os::Linux::libnuma_dlsym(void* handle, const char *name) { +- void *f = dlvsym(handle, name, "libnuma_1.1"); +- if (f == NULL) { +- f = dlsym(handle, name); +- } ++ void *f = dlsym(handle, name); + return f; + } + +@@ -5329,7 +5323,21 @@ + // Linux doesn't yet have a (official) notion of processor sets, + // so just return the system wide load average. + int os::loadavg(double loadavg[], int nelem) { +- return ::getloadavg(loadavg, nelem); ++ FILE *LOADAVG; ++ double avg[3] = { 0.0, 0.0, 0.0 }; ++ int i, res = -1;; ++ ++ if ((LOADAVG = fopen("/proc/loadavg", "r"))) { ++ fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]); ++ res = 0; ++ fclose(LOADAVG); ++ } ++ ++ for (i = 0; (i < nelem) && (i < 3); i++) { ++ loadavg[i] = avg[i]; ++ } ++ ++ return res; + } + + void os::pause() { +diff -Nur openjdk.orig/hotspot/src/os/linux/vm/os_linux.cpp.orig openjdk/hotspot/src/os/linux/vm/os_linux.cpp.orig +--- openjdk.orig/hotspot/src/os/linux/vm/os_linux.cpp.orig 1970-01-01 01:00:00.000000000 +0100 ++++ openjdk/hotspot/src/os/linux/vm/os_linux.cpp.orig 2014-02-20 19:51:45.000000000 +0100 +@@ -0,0 +1,5989 @@ ++/* ++ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ * ++ */ ++ ++// no precompiled headers ++#include "classfile/classLoader.hpp" ++#include "classfile/systemDictionary.hpp" ++#include "classfile/vmSymbols.hpp" ++#include "code/icBuffer.hpp" ++#include "code/vtableStubs.hpp" ++#include "compiler/compileBroker.hpp" ++#include "interpreter/interpreter.hpp" ++#include "jvm_linux.h" ++#include "memory/allocation.inline.hpp" ++#include "memory/filemap.hpp" ++#include "mutex_linux.inline.hpp" ++#include "oops/oop.inline.hpp" ++#include "os_share_linux.hpp" ++#include "prims/jniFastGetField.hpp" ++#include "prims/jvm.h" ++#include "prims/jvm_misc.hpp" ++#include "runtime/arguments.hpp" ++#include "runtime/extendedPC.hpp" ++#include "runtime/globals.hpp" ++#include "runtime/interfaceSupport.hpp" ++#include "runtime/init.hpp" ++#include "runtime/java.hpp" ++#include "runtime/javaCalls.hpp" ++#include "runtime/mutexLocker.hpp" ++#include "runtime/objectMonitor.hpp" ++#include "runtime/osThread.hpp" ++#include "runtime/perfMemory.hpp" ++#include "runtime/sharedRuntime.hpp" ++#include "runtime/statSampler.hpp" ++#include "runtime/stubRoutines.hpp" ++#include "runtime/threadCritical.hpp" ++#include "runtime/timer.hpp" ++#include "services/attachListener.hpp" ++#include "services/memTracker.hpp" ++#include "services/runtimeService.hpp" ++#include "thread_linux.inline.hpp" ++#include "utilities/decoder.hpp" ++#include "utilities/defaultStream.hpp" ++#include "utilities/events.hpp" ++#include "utilities/elfFile.hpp" ++#include "utilities/growableArray.hpp" ++#include "utilities/vmError.hpp" ++#ifdef TARGET_ARCH_x86 ++# include "assembler_x86.inline.hpp" ++# include "nativeInst_x86.hpp" ++#endif ++#ifdef TARGET_ARCH_sparc ++# include "assembler_sparc.inline.hpp" ++# include "nativeInst_sparc.hpp" ++#endif ++#ifdef TARGET_ARCH_zero ++# include "assembler_zero.inline.hpp" ++# include "nativeInst_zero.hpp" ++#endif ++#ifdef TARGET_ARCH_arm ++# include "assembler_arm.inline.hpp" ++# include "nativeInst_arm.hpp" ++#endif ++#ifdef TARGET_ARCH_ppc ++# include "assembler_ppc.inline.hpp" ++# include "nativeInst_ppc.hpp" ++#endif ++ ++// put OS-includes here ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++ ++#define MAX_PATH (2 * K) ++ ++// for timer info max values which include all bits ++#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) ++ ++#define LARGEPAGES_BIT (1 << 6) ++ ++#ifndef EM_AARCH64 ++#define EM_AARCH64 183 /* ARM AARCH64 */ ++#endif ++ ++//////////////////////////////////////////////////////////////////////////////// ++// global variables ++julong os::Linux::_physical_memory = 0; ++ ++address os::Linux::_initial_thread_stack_bottom = NULL; ++uintptr_t os::Linux::_initial_thread_stack_size = 0; ++ ++int (*os::Linux::_clock_gettime)(clockid_t, struct timespec *) = NULL; ++int (*os::Linux::_pthread_getcpuclockid)(pthread_t, clockid_t *) = NULL; ++Mutex* os::Linux::_createThread_lock = NULL; ++pthread_t os::Linux::_main_thread; ++int os::Linux::_page_size = -1; ++const int os::Linux::_vm_default_page_size = (8 * K); ++bool os::Linux::_is_floating_stack = false; ++bool os::Linux::_is_NPTL = false; ++bool os::Linux::_supports_fast_thread_cpu_time = false; ++const char * os::Linux::_glibc_version = NULL; ++const char * os::Linux::_libpthread_version = NULL; ++ ++static jlong initial_time_count=0; ++ ++static int clock_tics_per_sec = 100; ++ ++// For diagnostics to print a message once. see run_periodic_checks ++static sigset_t check_signal_done; ++static bool check_signals = true;; ++ ++static pid_t _initial_pid = 0; ++ ++/* Signal number used to suspend/resume a thread */ ++ ++/* do not use any signal number less than SIGSEGV, see 4355769 */ ++static int SR_signum = SIGUSR2; ++sigset_t SR_sigset; ++ ++/* Used to protect dlsym() calls */ ++static pthread_mutex_t dl_mutex; ++ ++// Declarations ++static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); ++ ++#ifdef JAVASE_EMBEDDED ++class MemNotifyThread: public Thread { ++ friend class VMStructs; ++ public: ++ virtual void run(); ++ ++ private: ++ static MemNotifyThread* _memnotify_thread; ++ int _fd; ++ ++ public: ++ ++ // Constructor ++ MemNotifyThread(int fd); ++ ++ // Tester ++ bool is_memnotify_thread() const { return true; } ++ ++ // Printing ++ char* name() const { return (char*)"Linux MemNotify Thread"; } ++ ++ // Returns the single instance of the MemNotifyThread ++ static MemNotifyThread* memnotify_thread() { return _memnotify_thread; } ++ ++ // Create and start the single instance of MemNotifyThread ++ static void start(); ++}; ++#endif // JAVASE_EMBEDDED ++ ++// utility functions ++ ++static int SR_initialize(); ++static int SR_finalize(); ++ ++julong os::available_memory() { ++ return Linux::available_memory(); ++} ++ ++julong os::Linux::available_memory() { ++ // values in struct sysinfo are "unsigned long" ++ struct sysinfo si; ++ sysinfo(&si); ++ ++ return (julong)si.freeram * si.mem_unit; ++} ++ ++julong os::physical_memory() { ++ return Linux::physical_memory(); ++} ++ ++julong os::allocatable_physical_memory(julong size) { ++#ifdef _LP64 ++ return size; ++#else ++ julong result = MIN2(size, (julong)3800*M); ++ if (!is_allocatable(result)) { ++ // See comments under solaris for alignment considerations ++ julong reasonable_size = (julong)2*G - 2 * os::vm_page_size(); ++ result = MIN2(size, reasonable_size); ++ } ++ return result; ++#endif // _LP64 ++} ++ ++//////////////////////////////////////////////////////////////////////////////// ++// environment support ++ ++bool os::getenv(const char* name, char* buf, int len) { ++ const char* val = ::getenv(name); ++ if (val != NULL && strlen(val) < (size_t)len) { ++ strcpy(buf, val); ++ return true; ++ } ++ if (len > 0) buf[0] = 0; // return a null string ++ return false; ++} ++ ++ ++// Return true if user is running as root. ++ ++bool os::have_special_privileges() { ++ static bool init = false; ++ static bool privileges = false; ++ if (!init) { ++ privileges = (getuid() != geteuid()) || (getgid() != getegid()); ++ init = true; ++ } ++ return privileges; ++} ++ ++ ++#ifndef SYS_gettid ++// i386: 224, ia64: 1105, amd64: 186, sparc 143 ++#ifdef __ia64__ ++#define SYS_gettid 1105 ++#elif __i386__ ++#define SYS_gettid 224 ++#elif __amd64__ ++#define SYS_gettid 186 ++#elif __sparc__ ++#define SYS_gettid 143 ++#else ++#error define gettid for the arch ++#endif ++#endif ++ ++// Cpu architecture string ++#if defined(ZERO) ++static char cpu_arch[] = ZERO_LIBARCH; ++#elif defined(IA64) ++static char cpu_arch[] = "ia64"; ++#elif defined(IA32) ++static char cpu_arch[] = "i386"; ++#elif defined(AMD64) ++static char cpu_arch[] = "amd64"; ++#elif defined(ARM) ++static char cpu_arch[] = "arm"; ++#elif defined(PPC) ++static char cpu_arch[] = "ppc"; ++#elif defined(SPARC) ++# ifdef _LP64 ++static char cpu_arch[] = "sparcv9"; ++# else ++static char cpu_arch[] = "sparc"; ++# endif ++#else ++#error Add appropriate cpu_arch setting ++#endif ++ ++ ++// pid_t gettid() ++// ++// Returns the kernel thread id of the currently running thread. Kernel ++// thread id is used to access /proc. ++// ++// (Note that getpid() on LinuxThreads returns kernel thread id too; but ++// on NPTL, it returns the same pid for all threads, as required by POSIX.) ++// ++pid_t os::Linux::gettid() { ++ int rslt = syscall(SYS_gettid); ++ if (rslt == -1) { ++ // old kernel, no NPTL support ++ return getpid(); ++ } else { ++ return (pid_t)rslt; ++ } ++} ++ ++// Most versions of linux have a bug where the number of processors are ++// determined by looking at the /proc file system. In a chroot environment, ++// the system call returns 1. This causes the VM to act as if it is ++// a single processor and elide locking (see is_MP() call). ++static bool unsafe_chroot_detected = false; ++static const char *unstable_chroot_error = "/proc file system not found.\n" ++ "Java may be unstable running multithreaded in a chroot " ++ "environment on Linux when /proc filesystem is not mounted."; ++ ++void os::Linux::initialize_system_info() { ++ set_processor_count(sysconf(_SC_NPROCESSORS_CONF)); ++ if (processor_count() == 1) { ++ pid_t pid = os::Linux::gettid(); ++ char fname[32]; ++ jio_snprintf(fname, sizeof(fname), "/proc/%d", pid); ++ FILE *fp = fopen(fname, "r"); ++ if (fp == NULL) { ++ unsafe_chroot_detected = true; ++ } else { ++ fclose(fp); ++ } ++ } ++ _physical_memory = (julong)sysconf(_SC_PHYS_PAGES) * (julong)sysconf(_SC_PAGESIZE); ++ assert(processor_count() > 0, "linux error"); ++} ++ ++void os::init_system_properties_values() { ++// char arch[12]; ++// sysinfo(SI_ARCHITECTURE, arch, sizeof(arch)); ++ ++ // The next steps are taken in the product version: ++ // ++ // Obtain the JAVA_HOME value from the location of libjvm[_g].so. ++ // This library should be located at: ++ // /jre/lib//{client|server}/libjvm[_g].so. ++ // ++ // If "/jre/lib/" appears at the right place in the path, then we ++ // assume libjvm[_g].so is installed in a JDK and we use this path. ++ // ++ // Otherwise exit with message: "Could not create the Java virtual machine." ++ // ++ // The following extra steps are taken in the debugging version: ++ // ++ // If "/jre/lib/" does NOT appear at the right place in the path ++ // instead of exit check for $JAVA_HOME environment variable. ++ // ++ // If it is defined and we are able to locate $JAVA_HOME/jre/lib/, ++ // then we append a fake suffix "hotspot/libjvm[_g].so" to this path so ++ // it looks like libjvm[_g].so is installed there ++ // /jre/lib//hotspot/libjvm[_g].so. ++ // ++ // Otherwise exit. ++ // ++ // Important note: if the location of libjvm.so changes this ++ // code needs to be changed accordingly. ++ ++ // The next few definitions allow the code to be verbatim: ++#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal) ++#define getenv(n) ::getenv(n) ++ ++/* ++ * See ld(1): ++ * The linker uses the following search paths to locate required ++ * shared libraries: ++ * 1: ... ++ * ... ++ * 7: The default directories, normally /lib and /usr/lib. ++ */ ++#if defined(AMD64) || defined(_LP64) && (defined(SPARC) || defined(PPC) || defined(S390) || defined(AARCH64)) ++#define DEFAULT_LIBPATH "/usr/lib64:/lib64:/lib:/usr/lib" ++#else ++#define DEFAULT_LIBPATH "/lib:/usr/lib" ++#endif ++ ++#define EXTENSIONS_DIR "/lib/ext" ++#define ENDORSED_DIR "/lib/endorsed" ++#define REG_DIR "/usr/java/packages" ++ ++ { ++ /* sysclasspath, java_home, dll_dir */ ++ { ++ char *home_path; ++ char *dll_path; ++ char *pslash; ++ char buf[MAXPATHLEN]; ++ os::jvm_path(buf, sizeof(buf)); ++ ++ // Found the full path to libjvm.so. ++ // Now cut the path to /jre if we can. ++ *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */ ++ pslash = strrchr(buf, '/'); ++ if (pslash != NULL) ++ *pslash = '\0'; /* get rid of /{client|server|hotspot} */ ++ dll_path = malloc(strlen(buf) + 1); ++ if (dll_path == NULL) ++ return; ++ strcpy(dll_path, buf); ++ Arguments::set_dll_dir(dll_path); ++ ++ if (pslash != NULL) { ++ pslash = strrchr(buf, '/'); ++ if (pslash != NULL) { ++ *pslash = '\0'; /* get rid of / */ ++ pslash = strrchr(buf, '/'); ++ if (pslash != NULL) ++ *pslash = '\0'; /* get rid of /lib */ ++ } ++ } ++ ++ home_path = malloc(strlen(buf) + 1); ++ if (home_path == NULL) ++ return; ++ strcpy(home_path, buf); ++ Arguments::set_java_home(home_path); ++ ++ if (!set_boot_path('/', ':')) ++ return; ++ } ++ ++ /* ++ * Where to look for native libraries ++ * ++ * Note: Due to a legacy implementation, most of the library path ++ * is set in the launcher. This was to accomodate linking restrictions ++ * on legacy Linux implementations (which are no longer supported). ++ * Eventually, all the library path setting will be done here. ++ * ++ * However, to prevent the proliferation of improperly built native ++ * libraries, the new path component /usr/java/packages is added here. ++ * Eventually, all the library path setting will be done here. ++ */ ++ { ++ char *ld_library_path; ++ ++ /* ++ * Construct the invariant part of ld_library_path. Note that the ++ * space for the colon and the trailing null are provided by the ++ * nulls included by the sizeof operator (so actually we allocate ++ * a byte more than necessary). ++ */ ++ ld_library_path = (char *) malloc(sizeof(REG_DIR) + sizeof("/lib/") + ++ strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH)); ++ sprintf(ld_library_path, REG_DIR "/lib/%s:" DEFAULT_LIBPATH, cpu_arch); ++ ++ /* ++ * Get the user setting of LD_LIBRARY_PATH, and prepended it. It ++ * should always exist (until the legacy problem cited above is ++ * addressed). ++ */ ++ char *v = getenv("LD_LIBRARY_PATH"); ++ if (v != NULL) { ++ char *t = ld_library_path; ++ /* That's +1 for the colon and +1 for the trailing '\0' */ ++ ld_library_path = (char *) malloc(strlen(v) + 1 + strlen(t) + 1); ++ sprintf(ld_library_path, "%s:%s", v, t); ++ } ++ Arguments::set_library_path(ld_library_path); ++ } ++ ++ /* ++ * Extensions directories. ++ * ++ * Note that the space for the colon and the trailing null are provided ++ * by the nulls included by the sizeof operator (so actually one byte more ++ * than necessary is allocated). ++ */ ++ { ++ char *buf = malloc(strlen(Arguments::get_java_home()) + ++ sizeof(EXTENSIONS_DIR) + sizeof(REG_DIR) + sizeof(EXTENSIONS_DIR)); ++ sprintf(buf, "%s" EXTENSIONS_DIR ":" REG_DIR EXTENSIONS_DIR, ++ Arguments::get_java_home()); ++ Arguments::set_ext_dirs(buf); ++ } ++ ++ /* Endorsed standards default directory. */ ++ { ++ char * buf; ++ buf = malloc(strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR)); ++ sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home()); ++ Arguments::set_endorsed_dirs(buf); ++ } ++ } ++ ++#undef malloc ++#undef getenv ++#undef EXTENSIONS_DIR ++#undef ENDORSED_DIR ++ ++ // Done ++ return; ++} ++ ++//////////////////////////////////////////////////////////////////////////////// ++// breakpoint support ++ ++void os::breakpoint() { ++ BREAKPOINT; ++} ++ ++extern "C" void breakpoint() { ++ // use debugger to set breakpoint here ++} ++ ++//////////////////////////////////////////////////////////////////////////////// ++// signal support ++ ++debug_only(static bool signal_sets_initialized = false); ++static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs; ++ ++bool os::Linux::is_sig_ignored(int sig) { ++ struct sigaction oact; ++ sigaction(sig, (struct sigaction*)NULL, &oact); ++ void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction) ++ : CAST_FROM_FN_PTR(void*, oact.sa_handler); ++ if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN)) ++ return true; ++ else ++ return false; ++} ++ ++void os::Linux::signal_sets_init() { ++ // Should also have an assertion stating we are still single-threaded. ++ assert(!signal_sets_initialized, "Already initialized"); ++ // Fill in signals that are necessarily unblocked for all threads in ++ // the VM. Currently, we unblock the following signals: ++ // SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden ++ // by -Xrs (=ReduceSignalUsage)); ++ // BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all ++ // other threads. The "ReduceSignalUsage" boolean tells us not to alter ++ // the dispositions or masks wrt these signals. ++ // Programs embedding the VM that want to use the above signals for their ++ // own purposes must, at this time, use the "-Xrs" option to prevent ++ // interference with shutdown hooks and BREAK_SIGNAL thread dumping. ++ // (See bug 4345157, and other related bugs). ++ // In reality, though, unblocking these signals is really a nop, since ++ // these signals are not blocked by default. ++ sigemptyset(&unblocked_sigs); ++ sigemptyset(&allowdebug_blocked_sigs); ++ sigaddset(&unblocked_sigs, SIGILL); ++ sigaddset(&unblocked_sigs, SIGSEGV); ++ sigaddset(&unblocked_sigs, SIGBUS); ++ sigaddset(&unblocked_sigs, SIGFPE); ++ sigaddset(&unblocked_sigs, SR_signum); ++ ++ if (!ReduceSignalUsage) { ++ if (!os::Linux::is_sig_ignored(SHUTDOWN1_SIGNAL)) { ++ sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL); ++ sigaddset(&allowdebug_blocked_sigs, SHUTDOWN1_SIGNAL); ++ } ++ if (!os::Linux::is_sig_ignored(SHUTDOWN2_SIGNAL)) { ++ sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL); ++ sigaddset(&allowdebug_blocked_sigs, SHUTDOWN2_SIGNAL); ++ } ++ if (!os::Linux::is_sig_ignored(SHUTDOWN3_SIGNAL)) { ++ sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL); ++ sigaddset(&allowdebug_blocked_sigs, SHUTDOWN3_SIGNAL); ++ } ++ } ++ // Fill in signals that are blocked by all but the VM thread. ++ sigemptyset(&vm_sigs); ++ if (!ReduceSignalUsage) ++ sigaddset(&vm_sigs, BREAK_SIGNAL); ++ debug_only(signal_sets_initialized = true); ++ ++} ++ ++// These are signals that are unblocked while a thread is running Java. ++// (For some reason, they get blocked by default.) ++sigset_t* os::Linux::unblocked_signals() { ++ assert(signal_sets_initialized, "Not initialized"); ++ return &unblocked_sigs; ++} ++ ++// These are the signals that are blocked while a (non-VM) thread is ++// running Java. Only the VM thread handles these signals. ++sigset_t* os::Linux::vm_signals() { ++ assert(signal_sets_initialized, "Not initialized"); ++ return &vm_sigs; ++} ++ ++// These are signals that are blocked during cond_wait to allow debugger in ++sigset_t* os::Linux::allowdebug_blocked_signals() { ++ assert(signal_sets_initialized, "Not initialized"); ++ return &allowdebug_blocked_sigs; ++} ++ ++void os::Linux::hotspot_sigmask(Thread* thread) { ++ ++ //Save caller's signal mask before setting VM signal mask ++ sigset_t caller_sigmask; ++ pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask); ++ ++ OSThread* osthread = thread->osthread(); ++ osthread->set_caller_sigmask(caller_sigmask); ++ ++ pthread_sigmask(SIG_UNBLOCK, os::Linux::unblocked_signals(), NULL); ++ ++ if (!ReduceSignalUsage) { ++ if (thread->is_VM_thread()) { ++ // Only the VM thread handles BREAK_SIGNAL ... ++ pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL); ++ } else { ++ // ... all other threads block BREAK_SIGNAL ++ pthread_sigmask(SIG_BLOCK, vm_signals(), NULL); ++ } ++ } ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// detecting pthread library ++ ++void os::Linux::libpthread_init() { ++ // Save glibc and pthread version strings. Note that _CS_GNU_LIBC_VERSION ++ // and _CS_GNU_LIBPTHREAD_VERSION are supported in glibc >= 2.3.2. Use a ++ // generic name for earlier versions. ++ // Define macros here so we can build HotSpot on old systems. ++# ifndef _CS_GNU_LIBC_VERSION ++# define _CS_GNU_LIBC_VERSION 2 ++# endif ++# ifndef _CS_GNU_LIBPTHREAD_VERSION ++# define _CS_GNU_LIBPTHREAD_VERSION 3 ++# endif ++ ++ size_t n = confstr(_CS_GNU_LIBC_VERSION, NULL, 0); ++ if (n > 0) { ++ char *str = (char *)malloc(n, mtInternal); ++ confstr(_CS_GNU_LIBC_VERSION, str, n); ++ os::Linux::set_glibc_version(str); ++ } else { ++ // _CS_GNU_LIBC_VERSION is not supported, try gnu_get_libc_version() ++ static char _gnu_libc_version[32]; ++ jio_snprintf(_gnu_libc_version, sizeof(_gnu_libc_version), ++ "glibc %s %s", gnu_get_libc_version(), gnu_get_libc_release()); ++ os::Linux::set_glibc_version(_gnu_libc_version); ++ } ++ ++ n = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, 0); ++ if (n > 0) { ++ char *str = (char *)malloc(n, mtInternal); ++ confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n); ++ // Vanilla RH-9 (glibc 2.3.2) has a bug that confstr() always tells ++ // us "NPTL-0.29" even we are running with LinuxThreads. Check if this ++ // is the case. LinuxThreads has a hard limit on max number of threads. ++ // So sysconf(_SC_THREAD_THREADS_MAX) will return a positive value. ++ // On the other hand, NPTL does not have such a limit, sysconf() ++ // will return -1 and errno is not changed. Check if it is really NPTL. ++ if (strcmp(os::Linux::glibc_version(), "glibc 2.3.2") == 0 && ++ strstr(str, "NPTL") && ++ sysconf(_SC_THREAD_THREADS_MAX) > 0) { ++ free(str); ++ os::Linux::set_libpthread_version("linuxthreads"); ++ } else { ++ os::Linux::set_libpthread_version(str); ++ } ++ } else { ++ // glibc before 2.3.2 only has LinuxThreads. ++ os::Linux::set_libpthread_version("linuxthreads"); ++ } ++ ++ if (strstr(libpthread_version(), "NPTL")) { ++ os::Linux::set_is_NPTL(); ++ } else { ++ os::Linux::set_is_LinuxThreads(); ++ } ++ ++ // LinuxThreads have two flavors: floating-stack mode, which allows variable ++ // stack size; and fixed-stack mode. NPTL is always floating-stack. ++ if (os::Linux::is_NPTL() || os::Linux::supports_variable_stack_size()) { ++ os::Linux::set_is_floating_stack(); ++ } ++} ++ ++///////////////////////////////////////////////////////////////////////////// ++// thread stack ++ ++// Force Linux kernel to expand current thread stack. If "bottom" is close ++// to the stack guard, caller should block all signals. ++// ++// MAP_GROWSDOWN: ++// A special mmap() flag that is used to implement thread stacks. It tells ++// kernel that the memory region should extend downwards when needed. This ++// allows early versions of LinuxThreads to only mmap the first few pages ++// when creating a new thread. Linux kernel will automatically expand thread ++// stack as needed (on page faults). ++// ++// However, because the memory region of a MAP_GROWSDOWN stack can grow on ++// demand, if a page fault happens outside an already mapped MAP_GROWSDOWN ++// region, it's hard to tell if the fault is due to a legitimate stack ++// access or because of reading/writing non-exist memory (e.g. buffer ++// overrun). As a rule, if the fault happens below current stack pointer, ++// Linux kernel does not expand stack, instead a SIGSEGV is sent to the ++// application (see Linux kernel fault.c). ++// ++// This Linux feature can cause SIGSEGV when VM bangs thread stack for ++// stack overflow detection. ++// ++// Newer version of LinuxThreads (since glibc-2.2, or, RH-7.x) and NPTL do ++// not use this flag. However, the stack of initial thread is not created ++// by pthread, it is still MAP_GROWSDOWN. Also it's possible (though ++// unlikely) that user code can create a thread with MAP_GROWSDOWN stack ++// and then attach the thread to JVM. ++// ++// To get around the problem and allow stack banging on Linux, we need to ++// manually expand thread stack after receiving the SIGSEGV. ++// ++// There are two ways to expand thread stack to address "bottom", we used ++// both of them in JVM before 1.5: ++// 1. adjust stack pointer first so that it is below "bottom", and then ++// touch "bottom" ++// 2. mmap() the page in question ++// ++// Now alternate signal stack is gone, it's harder to use 2. For instance, ++// if current sp is already near the lower end of page 101, and we need to ++// call mmap() to map page 100, it is possible that part of the mmap() frame ++// will be placed in page 100. When page 100 is mapped, it is zero-filled. ++// That will destroy the mmap() frame and cause VM to crash. ++// ++// The following code works by adjusting sp first, then accessing the "bottom" ++// page to force a page fault. Linux kernel will then automatically expand the ++// stack mapping. ++// ++// _expand_stack_to() assumes its frame size is less than page size, which ++// should always be true if the function is not inlined. ++ ++#if __GNUC__ < 3 // gcc 2.x does not support noinline attribute ++#define NOINLINE ++#else ++#define NOINLINE __attribute__ ((noinline)) ++#endif ++ ++static void _expand_stack_to(address bottom) NOINLINE; ++ ++static void _expand_stack_to(address bottom) { ++ address sp; ++ size_t size; ++ volatile char *p; ++ ++ // Adjust bottom to point to the largest address within the same page, it ++ // gives us a one-page buffer if alloca() allocates slightly more memory. ++ bottom = (address)align_size_down((uintptr_t)bottom, os::Linux::page_size()); ++ bottom += os::Linux::page_size() - 1; ++ ++ // sp might be slightly above current stack pointer; if that's the case, we ++ // will alloca() a little more space than necessary, which is OK. Don't use ++ // os::current_stack_pointer(), as its result can be slightly below current ++ // stack pointer, causing us to not alloca enough to reach "bottom". ++ sp = (address)&sp; ++ ++ if (sp > bottom) { ++ size = sp - bottom; ++ p = (volatile char *)alloca(size); ++ assert(p != NULL && p <= (volatile char *)bottom, "alloca problem?"); ++ p[0] = '\0'; ++ } ++} ++ ++bool os::Linux::manually_expand_stack(JavaThread * t, address addr) { ++ assert(t!=NULL, "just checking"); ++ assert(t->osthread()->expanding_stack(), "expand should be set"); ++ assert(t->stack_base() != NULL, "stack_base was not initialized"); ++ ++ if (addr < t->stack_base() && addr >= t->stack_yellow_zone_base()) { ++ sigset_t mask_all, old_sigset; ++ sigfillset(&mask_all); ++ pthread_sigmask(SIG_SETMASK, &mask_all, &old_sigset); ++ _expand_stack_to(addr); ++ pthread_sigmask(SIG_SETMASK, &old_sigset, NULL); ++ return true; ++ } ++ return false; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// create new thread ++ ++static address highest_vm_reserved_address(); ++ ++// check if it's safe to start a new thread ++static bool _thread_safety_check(Thread* thread) { ++ if (os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack()) { ++ // Fixed stack LinuxThreads (SuSE Linux/x86, and some versions of Redhat) ++ // Heap is mmap'ed at lower end of memory space. Thread stacks are ++ // allocated (MAP_FIXED) from high address space. Every thread stack ++ // occupies a fixed size slot (usually 2Mbytes, but user can change ++ // it to other values if they rebuild LinuxThreads). ++ // ++ // Problem with MAP_FIXED is that mmap() can still succeed even part of ++ // the memory region has already been mmap'ed. That means if we have too ++ // many threads and/or very large heap, eventually thread stack will ++ // collide with heap. ++ // ++ // Here we try to prevent heap/stack collision by comparing current ++ // stack bottom with the highest address that has been mmap'ed by JVM ++ // plus a safety margin for memory maps created by native code. ++ // ++ // This feature can be disabled by setting ThreadSafetyMargin to 0 ++ // ++ if (ThreadSafetyMargin > 0) { ++ address stack_bottom = os::current_stack_base() - os::current_stack_size(); ++ ++ // not safe if our stack extends below the safety margin ++ return stack_bottom - ThreadSafetyMargin >= highest_vm_reserved_address(); ++ } else { ++ return true; ++ } ++ } else { ++ // Floating stack LinuxThreads or NPTL: ++ // Unlike fixed stack LinuxThreads, thread stacks are not MAP_FIXED. When ++ // there's not enough space left, pthread_create() will fail. If we come ++ // here, that means enough space has been reserved for stack. ++ return true; ++ } ++} ++ ++// Thread start routine for all newly created threads ++static void *java_start(Thread *thread) { ++ // Try to randomize the cache line index of hot stack frames. ++ // This helps when threads of the same stack traces evict each other's ++ // cache lines. The threads can be either from the same JVM instance, or ++ // from different JVM instances. The benefit is especially true for ++ // processors with hyperthreading technology. ++ static int counter = 0; ++ int pid = os::current_process_id(); ++ alloca(((pid ^ counter++) & 7) * 128); ++ ++ ThreadLocalStorage::set_thread(thread); ++ ++ OSThread* osthread = thread->osthread(); ++ Monitor* sync = osthread->startThread_lock(); ++ ++ // non floating stack LinuxThreads needs extra check, see above ++ if (!_thread_safety_check(thread)) { ++ // notify parent thread ++ MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); ++ osthread->set_state(ZOMBIE); ++ sync->notify_all(); ++ return NULL; ++ } ++ ++ // thread_id is kernel thread id (similar to Solaris LWP id) ++ osthread->set_thread_id(os::Linux::gettid()); ++ ++ if (UseNUMA) { ++ int lgrp_id = os::numa_get_group_id(); ++ if (lgrp_id != -1) { ++ thread->set_lgrp_id(lgrp_id); ++ } ++ } ++ // initialize signal mask for this thread ++ os::Linux::hotspot_sigmask(thread); ++ ++ // initialize floating point control register ++ os::Linux::init_thread_fpu_state(); ++ ++ // handshaking with parent thread ++ { ++ MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); ++ ++ // notify parent thread ++ osthread->set_state(INITIALIZED); ++ sync->notify_all(); ++ ++ // wait until os::start_thread() ++ while (osthread->get_state() == INITIALIZED) { ++ sync->wait(Mutex::_no_safepoint_check_flag); ++ } ++ } ++ ++ // call one more level start routine ++ thread->run(); ++ ++ return 0; ++} ++ ++bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { ++ assert(thread->osthread() == NULL, "caller responsible"); ++ ++ // Allocate the OSThread object ++ OSThread* osthread = new OSThread(NULL, NULL); ++ if (osthread == NULL) { ++ return false; ++ } ++ ++ // set the correct thread state ++ osthread->set_thread_type(thr_type); ++ ++ // Initial state is ALLOCATED but not INITIALIZED ++ osthread->set_state(ALLOCATED); ++ ++ thread->set_osthread(osthread); ++ ++ // init thread attributes ++ pthread_attr_t attr; ++ pthread_attr_init(&attr); ++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ++ ++ // stack size ++ if (os::Linux::supports_variable_stack_size()) { ++ // calculate stack size if it's not specified by caller ++ if (stack_size == 0) { ++ stack_size = os::Linux::default_stack_size(thr_type); ++ ++ switch (thr_type) { ++ case os::java_thread: ++ // Java threads use ThreadStackSize which default value can be ++ // changed with the flag -Xss ++ assert (JavaThread::stack_size_at_create() > 0, "this should be set"); ++ stack_size = JavaThread::stack_size_at_create(); ++ break; ++ case os::compiler_thread: ++ if (CompilerThreadStackSize > 0) { ++ stack_size = (size_t)(CompilerThreadStackSize * K); ++ break; ++ } // else fall through: ++ // use VMThreadStackSize if CompilerThreadStackSize is not defined ++ case os::vm_thread: ++ case os::pgc_thread: ++ case os::cgc_thread: ++ case os::watcher_thread: ++ if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); ++ break; ++ } ++ } ++ ++ stack_size = MAX2(stack_size, os::Linux::min_stack_allowed); ++ pthread_attr_setstacksize(&attr, stack_size); ++ } else { ++ // let pthread_create() pick the default value. ++ } ++ ++ // glibc guard page ++ pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type)); ++ ++ ThreadState state; ++ ++ { ++ // Serialize thread creation if we are running with fixed stack LinuxThreads ++ bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack(); ++ if (lock) { ++ os::Linux::createThread_lock()->lock_without_safepoint_check(); ++ } ++ ++ pthread_t tid; ++ int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); ++ ++ pthread_attr_destroy(&attr); ++ ++ if (ret != 0) { ++ if (PrintMiscellaneous && (Verbose || WizardMode)) { ++ perror("pthread_create()"); ++ } ++ // Need to clean up stuff we've allocated so far ++ thread->set_osthread(NULL); ++ delete osthread; ++ if (lock) os::Linux::createThread_lock()->unlock(); ++ return false; ++ } ++ ++ // Store pthread info into the OSThread ++ osthread->set_pthread_id(tid); ++ ++ // Wait until child thread is either initialized or aborted ++ { ++ Monitor* sync_with_child = osthread->startThread_lock(); ++ MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); ++ while ((state = osthread->get_state()) == ALLOCATED) { ++ sync_with_child->wait(Mutex::_no_safepoint_check_flag); ++ } ++ } ++ ++ if (lock) { ++ os::Linux::createThread_lock()->unlock(); ++ } ++ } ++ ++ // Aborted due to thread limit being reached ++ if (state == ZOMBIE) { ++ thread->set_osthread(NULL); ++ delete osthread; ++ return false; ++ } ++ ++ // The thread is returned suspended (in state INITIALIZED), ++ // and is started higher up in the call chain ++ assert(state == INITIALIZED, "race condition"); ++ return true; ++} ++ ++///////////////////////////////////////////////////////////////////////////// ++// attach existing thread ++ ++// bootstrap the main thread ++bool os::create_main_thread(JavaThread* thread) { ++ assert(os::Linux::_main_thread == pthread_self(), "should be called inside main thread"); ++ return create_attached_thread(thread); ++} ++ ++bool os::create_attached_thread(JavaThread* thread) { ++#ifdef ASSERT ++ thread->verify_not_published(); ++#endif ++ ++ // Allocate the OSThread object ++ OSThread* osthread = new OSThread(NULL, NULL); ++ ++ if (osthread == NULL) { ++ return false; ++ } ++ ++ // Store pthread info into the OSThread ++ osthread->set_thread_id(os::Linux::gettid()); ++ osthread->set_pthread_id(::pthread_self()); ++ ++ // initialize floating point control register ++ os::Linux::init_thread_fpu_state(); ++ ++ // Initial thread state is RUNNABLE ++ osthread->set_state(RUNNABLE); ++ ++ thread->set_osthread(osthread); ++ ++ if (UseNUMA) { ++ int lgrp_id = os::numa_get_group_id(); ++ if (lgrp_id != -1) { ++ thread->set_lgrp_id(lgrp_id); ++ } ++ } ++ ++ if (os::Linux::is_initial_thread()) { ++ // If current thread is initial thread, its stack is mapped on demand, ++ // see notes about MAP_GROWSDOWN. Here we try to force kernel to map ++ // the entire stack region to avoid SEGV in stack banging. ++ // It is also useful to get around the heap-stack-gap problem on SuSE ++ // kernel (see 4821821 for details). We first expand stack to the top ++ // of yellow zone, then enable stack yellow zone (order is significant, ++ // enabling yellow zone first will crash JVM on SuSE Linux), so there ++ // is no gap between the last two virtual memory regions. ++ ++ JavaThread *jt = (JavaThread *)thread; ++ address addr = jt->stack_yellow_zone_base(); ++ assert(addr != NULL, "initialization problem?"); ++ assert(jt->stack_available(addr) > 0, "stack guard should not be enabled"); ++ ++ osthread->set_expanding_stack(); ++ os::Linux::manually_expand_stack(jt, addr); ++ osthread->clear_expanding_stack(); ++ } ++ ++ // initialize signal mask for this thread ++ // and save the caller's signal mask ++ os::Linux::hotspot_sigmask(thread); ++ ++ return true; ++} ++ ++void os::pd_start_thread(Thread* thread) { ++ OSThread * osthread = thread->osthread(); ++ assert(osthread->get_state() != INITIALIZED, "just checking"); ++ Monitor* sync_with_child = osthread->startThread_lock(); ++ MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); ++ sync_with_child->notify(); ++} ++ ++// Free Linux resources related to the OSThread ++void os::free_thread(OSThread* osthread) { ++ assert(osthread != NULL, "osthread not set"); ++ ++ if (Thread::current()->osthread() == osthread) { ++ // Restore caller's signal mask ++ sigset_t sigmask = osthread->caller_sigmask(); ++ pthread_sigmask(SIG_SETMASK, &sigmask, NULL); ++ } ++ ++ delete osthread; ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// thread local storage ++ ++int os::allocate_thread_local_storage() { ++ pthread_key_t key; ++ int rslt = pthread_key_create(&key, NULL); ++ assert(rslt == 0, "cannot allocate thread local storage"); ++ return (int)key; ++} ++ ++// Note: This is currently not used by VM, as we don't destroy TLS key ++// on VM exit. ++void os::free_thread_local_storage(int index) { ++ int rslt = pthread_key_delete((pthread_key_t)index); ++ assert(rslt == 0, "invalid index"); ++} ++ ++void os::thread_local_storage_at_put(int index, void* value) { ++ int rslt = pthread_setspecific((pthread_key_t)index, value); ++ assert(rslt == 0, "pthread_setspecific failed"); ++} ++ ++extern "C" Thread* get_thread() { ++ return ThreadLocalStorage::thread(); ++} ++ ++////////////////////////////////////////////////////////////////////////////// ++// initial thread ++ ++// Check if current thread is the initial thread, similar to Solaris thr_main. ++bool os::Linux::is_initial_thread(void) { ++ char dummy; ++ // If called before init complete, thread stack bottom will be null. ++ // Can be called if fatal error occurs before initialization. ++ if (initial_thread_stack_bottom() == NULL) return false; ++ assert(initial_thread_stack_bottom() != NULL && ++ initial_thread_stack_size() != 0, ++ "os::init did not locate initial thread's stack region"); ++ if ((address)&dummy >= initial_thread_stack_bottom() && ++ (address)&dummy < initial_thread_stack_bottom() + initial_thread_stack_size()) ++ return true; ++ else return false; ++} ++ ++// Find the virtual memory area that contains addr ++static bool find_vma(address addr, address* vma_low, address* vma_high) { ++ FILE *fp = fopen("/proc/self/maps", "r"); ++ if (fp) { ++ address low, high; ++ while (!feof(fp)) { ++ if (fscanf(fp, "%p-%p", &low, &high) == 2) { ++ if (low <= addr && addr < high) { ++ if (vma_low) *vma_low = low; ++ if (vma_high) *vma_high = high; ++ fclose (fp); ++ return true; ++ } ++ } ++ for (;;) { ++ int ch = fgetc(fp); ++ if (ch == EOF || ch == (int)'\n') break; ++ } ++ } ++ fclose(fp); ++ } ++ return false; ++} ++ ++// Locate initial thread stack. This special handling of initial thread stack ++// is needed because pthread_getattr_np() on most (all?) Linux distros returns ++// bogus value for initial thread. ++void os::Linux::capture_initial_stack(size_t max_size) { ++ // stack size is the easy part, get it from RLIMIT_STACK ++ size_t stack_size; ++ struct rlimit rlim; ++ getrlimit(RLIMIT_STACK, &rlim); ++ stack_size = rlim.rlim_cur; ++ ++ // 6308388: a bug in ld.so will relocate its own .data section to the ++ // lower end of primordial stack; reduce ulimit -s value a little bit ++ // so we won't install guard page on ld.so's data section. ++ stack_size -= 2 * page_size(); ++ ++ // 4441425: avoid crash with "unlimited" stack size on SuSE 7.1 or Redhat ++ // 7.1, in both cases we will get 2G in return value. ++ // 4466587: glibc 2.2.x compiled w/o "--enable-kernel=2.4.0" (RH 7.0, ++ // SuSE 7.2, Debian) can not handle alternate signal stack correctly ++ // for initial thread if its stack size exceeds 6M. Cap it at 2M, ++ // in case other parts in glibc still assumes 2M max stack size. ++ // FIXME: alt signal stack is gone, maybe we can relax this constraint? ++#ifndef IA64 ++ if (stack_size > 2 * K * K) stack_size = 2 * K * K; ++#else ++ // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small ++ if (stack_size > 4 * K * K) stack_size = 4 * K * K; ++#endif ++ ++ // Try to figure out where the stack base (top) is. This is harder. ++ // ++ // When an application is started, glibc saves the initial stack pointer in ++ // a global variable "__libc_stack_end", which is then used by system ++ // libraries. __libc_stack_end should be pretty close to stack top. The ++ // variable is available since the very early days. However, because it is ++ // a private interface, it could disappear in the future. ++ // ++ // Linux kernel saves start_stack information in /proc//stat. Similar ++ // to __libc_stack_end, it is very close to stack top, but isn't the real ++ // stack top. Note that /proc may not exist if VM is running as a chroot ++ // program, so reading /proc//stat could fail. Also the contents of ++ // /proc//stat could change in the future (though unlikely). ++ // ++ // We try __libc_stack_end first. If that doesn't work, look for ++ // /proc//stat. If neither of them works, we use current stack pointer ++ // as a hint, which should work well in most cases. ++ ++ uintptr_t stack_start; ++ ++ // try __libc_stack_end first ++ uintptr_t *p = (uintptr_t *)dlsym(RTLD_DEFAULT, "__libc_stack_end"); ++ if (p && *p) { ++ stack_start = *p; ++ } else { ++ // see if we can get the start_stack field from /proc/self/stat ++ FILE *fp; ++ int pid; ++ char state; ++ int ppid; ++ int pgrp; ++ int session; ++ int nr; ++ int tpgrp; ++ unsigned long flags; ++ unsigned long minflt; ++ unsigned long cminflt; ++ unsigned long majflt; ++ unsigned long cmajflt; ++ unsigned long utime; ++ unsigned long stime; ++ long cutime; ++ long cstime; ++ long prio; ++ long nice; ++ long junk; ++ long it_real; ++ uintptr_t start; ++ uintptr_t vsize; ++ intptr_t rss; ++ uintptr_t rsslim; ++ uintptr_t scodes; ++ uintptr_t ecode; ++ int i; ++ ++ // Figure what the primordial thread stack base is. Code is inspired ++ // by email from Hans Boehm. /proc/self/stat begins with current pid, ++ // followed by command name surrounded by parentheses, state, etc. ++ char stat[2048]; ++ int statlen; ++ ++ fp = fopen("/proc/self/stat", "r"); ++ if (fp) { ++ statlen = fread(stat, 1, 2047, fp); ++ stat[statlen] = '\0'; ++ fclose(fp); ++ ++ // Skip pid and the command string. Note that we could be dealing with ++ // weird command names, e.g. user could decide to rename java launcher ++ // to "java 1.4.2 :)", then the stat file would look like ++ // 1234 (java 1.4.2 :)) R ... ... ++ // We don't really need to know the command string, just find the last ++ // occurrence of ")" and then start parsing from there. See bug 4726580. ++ char * s = strrchr(stat, ')'); ++ ++ i = 0; ++ if (s) { ++ // Skip blank chars ++ do s++; while (isspace(*s)); ++ ++#define _UFM UINTX_FORMAT ++#define _DFM INTX_FORMAT ++ ++ /* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 */ ++ /* 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 */ ++ i = sscanf(s, "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld " _UFM _UFM _DFM _UFM _UFM _UFM _UFM, ++ &state, /* 3 %c */ ++ &ppid, /* 4 %d */ ++ &pgrp, /* 5 %d */ ++ &session, /* 6 %d */ ++ &nr, /* 7 %d */ ++ &tpgrp, /* 8 %d */ ++ &flags, /* 9 %lu */ ++ &minflt, /* 10 %lu */ ++ &cminflt, /* 11 %lu */ ++ &majflt, /* 12 %lu */ ++ &cmajflt, /* 13 %lu */ ++ &utime, /* 14 %lu */ ++ &stime, /* 15 %lu */ ++ &cutime, /* 16 %ld */ ++ &cstime, /* 17 %ld */ ++ &prio, /* 18 %ld */ ++ &nice, /* 19 %ld */ ++ &junk, /* 20 %ld */ ++ &it_real, /* 21 %ld */ ++ &start, /* 22 UINTX_FORMAT */ ++ &vsize, /* 23 UINTX_FORMAT */ ++ &rss, /* 24 INTX_FORMAT */ ++ &rsslim, /* 25 UINTX_FORMAT */ ++ &scodes, /* 26 UINTX_FORMAT */ ++ &ecode, /* 27 UINTX_FORMAT */ ++ &stack_start); /* 28 UINTX_FORMAT */ ++ } ++ ++#undef _UFM ++#undef _DFM ++ ++ if (i != 28 - 2) { ++ assert(false, "Bad conversion from /proc/self/stat"); ++ // product mode - assume we are the initial thread, good luck in the ++ // embedded case. ++ warning("Can't detect initial thread stack location - bad conversion"); ++ stack_start = (uintptr_t) &rlim; ++ } ++ } else { ++ // For some reason we can't open /proc/self/stat (for example, running on ++ // FreeBSD with a Linux emulator, or inside chroot), this should work for ++ // most cases, so don't abort: ++ warning("Can't detect initial thread stack location - no /proc/self/stat"); ++ stack_start = (uintptr_t) &rlim; ++ } ++ } ++ ++ // Now we have a pointer (stack_start) very close to the stack top, the ++ // next thing to do is to figure out the exact location of stack top. We ++ // can find out the virtual memory area that contains stack_start by ++ // reading /proc/self/maps, it should be the last vma in /proc/self/maps, ++ // and its upper limit is the real stack top. (again, this would fail if ++ // running inside chroot, because /proc may not exist.) ++ ++ uintptr_t stack_top; ++ address low, high; ++ if (find_vma((address)stack_start, &low, &high)) { ++ // success, "high" is the true stack top. (ignore "low", because initial ++ // thread stack grows on demand, its real bottom is high - RLIMIT_STACK.) ++ stack_top = (uintptr_t)high; ++ } else { ++ // failed, likely because /proc/self/maps does not exist ++ warning("Can't detect initial thread stack location - find_vma failed"); ++ // best effort: stack_start is normally within a few pages below the real ++ // stack top, use it as stack top, and reduce stack size so we won't put ++ // guard page outside stack. ++ stack_top = stack_start; ++ stack_size -= 16 * page_size(); ++ } ++ ++ // stack_top could be partially down the page so align it ++ stack_top = align_size_up(stack_top, page_size()); ++ ++ if (max_size && stack_size > max_size) { ++ _initial_thread_stack_size = max_size; ++ } else { ++ _initial_thread_stack_size = stack_size; ++ } ++ ++ _initial_thread_stack_size = align_size_down(_initial_thread_stack_size, page_size()); ++ _initial_thread_stack_bottom = (address)stack_top - _initial_thread_stack_size; ++} ++ ++//////////////////////////////////////////////////////////////////////////////// ++// time support ++ ++// Time since start-up in seconds to a fine granularity. ++// Used by VMSelfDestructTimer and the MemProfiler. ++double os::elapsedTime() { ++ ++ return (double)(os::elapsed_counter()) * 0.000001; ++} ++ ++jlong os::elapsed_counter() { ++ timeval time; ++ int status = gettimeofday(&time, NULL); ++ return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count; ++} ++ ++jlong os::elapsed_frequency() { ++ return (1000 * 1000); ++} ++ ++// For now, we say that linux does not support vtime. I have no idea ++// whether it can actually be made to (DLD, 9/13/05). ++ ++bool os::supports_vtime() { return false; } ++bool os::enable_vtime() { return false; } ++bool os::vtime_enabled() { return false; } ++double os::elapsedVTime() { ++ // better than nothing, but not much ++ return elapsedTime(); ++} ++ ++jlong os::javaTimeMillis() { ++ timeval time; ++ int status = gettimeofday(&time, NULL); ++ assert(status != -1, "linux error"); ++ return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000); ++} ++ ++#ifndef CLOCK_MONOTONIC ++#define CLOCK_MONOTONIC (1) ++#endif ++ ++void os::Linux::clock_init() { ++ // we do dlopen's in this particular order due to bug in linux ++ // dynamical loader (see 6348968) leading to crash on exit ++ void* handle = dlopen("librt.so.1", RTLD_LAZY); ++ if (handle == NULL) { ++ handle = dlopen("librt.so", RTLD_LAZY); ++ } ++ ++ if (handle) { ++ int (*clock_getres_func)(clockid_t, struct timespec*) = ++ (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_getres"); ++ int (*clock_gettime_func)(clockid_t, struct timespec*) = ++ (int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_gettime"); ++ if (clock_getres_func && clock_gettime_func) { ++ // See if monotonic clock is supported by the kernel. Note that some ++ // early implementations simply return kernel jiffies (updated every ++ // 1/100 or 1/1000 second). It would be bad to use such a low res clock ++ // for nano time (though the monotonic property is still nice to have). ++ // It's fixed in newer kernels, however clock_getres() still returns ++ // 1/HZ. We check if clock_getres() works, but will ignore its reported ++ // resolution for now. Hopefully as people move to new kernels, this ++ // won't be a problem. ++ struct timespec res; ++ struct timespec tp; ++ if (clock_getres_func (CLOCK_MONOTONIC, &res) == 0 && ++ clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) { ++ // yes, monotonic clock is supported ++ _clock_gettime = clock_gettime_func; ++ } else { ++ // close librt if there is no monotonic clock ++ dlclose(handle); ++ } ++ } ++ } ++} ++ ++#ifndef SYS_clock_getres ++ ++#if defined(IA32) || defined(AMD64) ++#define SYS_clock_getres IA32_ONLY(266) AMD64_ONLY(229) ++#define sys_clock_getres(x,y) ::syscall(SYS_clock_getres, x, y) ++#else ++#warning "SYS_clock_getres not defined for this platform, disabling fast_thread_cpu_time" ++#define sys_clock_getres(x,y) -1 ++#endif ++ ++#else ++#define sys_clock_getres(x,y) ::syscall(SYS_clock_getres, x, y) ++#endif ++ ++void os::Linux::fast_thread_clock_init() { ++ if (!UseLinuxPosixThreadCPUClocks) { ++ return; ++ } ++ clockid_t clockid; ++ struct timespec tp; ++ int (*pthread_getcpuclockid_func)(pthread_t, clockid_t *) = ++ (int(*)(pthread_t, clockid_t *)) dlsym(RTLD_DEFAULT, "pthread_getcpuclockid"); ++ ++ // Switch to using fast clocks for thread cpu time if ++ // the sys_clock_getres() returns 0 error code. ++ // Note, that some kernels may support the current thread ++ // clock (CLOCK_THREAD_CPUTIME_ID) but not the clocks ++ // returned by the pthread_getcpuclockid(). ++ // If the fast Posix clocks are supported then the sys_clock_getres() ++ // must return at least tp.tv_sec == 0 which means a resolution ++ // better than 1 sec. This is extra check for reliability. ++ ++ if(pthread_getcpuclockid_func && ++ pthread_getcpuclockid_func(_main_thread, &clockid) == 0 && ++ sys_clock_getres(clockid, &tp) == 0 && tp.tv_sec == 0) { ++ ++ _supports_fast_thread_cpu_time = true; ++ _pthread_getcpuclockid = pthread_getcpuclockid_func; ++ } ++} ++ ++jlong os::javaTimeNanos() { ++ if (Linux::supports_monotonic_clock()) { ++ struct timespec tp; ++ int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp); ++ assert(status == 0, "gettime error"); ++ jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec); ++ return result; ++ } else { ++ timeval time; ++ int status = gettimeofday(&time, NULL); ++ assert(status != -1, "linux error"); ++ jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec); ++ return 1000 * usecs; ++ } ++} ++ ++void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { ++ if (Linux::supports_monotonic_clock()) { ++ info_ptr->max_value = ALL_64_BITS; ++ ++ // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past ++ info_ptr->may_skip_backward = false; // not subject to resetting or drifting ++ info_ptr->may_skip_forward = false; // not subject to resetting or drifting ++ } else { ++ // gettimeofday - based on time in seconds since the Epoch thus does not wrap ++ info_ptr->max_value = ALL_64_BITS; ++ ++ // gettimeofday is a real time clock so it skips ++ info_ptr->may_skip_backward = true; ++ info_ptr->may_skip_forward = true; ++ } ++ ++ info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time ++} ++ ++// Return the real, user, and system times in seconds from an ++// arbitrary fixed point in the past. ++bool os::getTimesSecs(double* process_real_time, ++ double* process_user_time, ++ double* process_system_time) { ++ struct tms ticks; ++ clock_t real_ticks = times(&ticks); ++ ++ if (real_ticks == (clock_t) (-1)) { ++ return false; ++ } else { ++ double ticks_per_second = (double) clock_tics_per_sec; ++ *process_user_time = ((double) ticks.tms_utime) / ticks_per_second; ++ *process_system_time = ((double) ticks.tms_stime) / ticks_per_second; ++ *process_real_time = ((double) real_ticks) / ticks_per_second; ++ ++ return true; ++ } ++} ++ ++ ++char * os::local_time_string(char *buf, size_t buflen) { ++ struct tm t; ++ time_t long_time; ++ time(&long_time); ++ localtime_r(&long_time, &t); ++ jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d", ++ t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, ++ t.tm_hour, t.tm_min, t.tm_sec); ++ return buf; ++} ++ ++struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { ++ return localtime_r(clock, res); ++} ++ ++//////////////////////////////////////////////////////////////////////////////// ++// runtime exit support ++ ++// Note: os::shutdown() might be called very early during initialization, or ++// called from signal handler. Before adding something to os::shutdown(), make ++// sure it is async-safe and can handle partially initialized VM. ++void os::shutdown() { ++ ++ // allow PerfMemory to attempt cleanup of any persistent resources ++ perfMemory_exit(); ++ ++ // needs to remove object in file system ++ AttachListener::abort(); ++ ++ // flush buffered output, finish log files ++ ostream_abort(); ++ ++ // Check for abort hook ++ abort_hook_t abort_hook = Arguments::abort_hook(); ++ if (abort_hook != NULL) { ++ abort_hook(); ++ } ++ ++} ++ ++// Note: os::abort() might be called very early during initialization, or ++// called from signal handler. Before adding something to os::abort(), make ++// sure it is async-safe and can handle partially initialized VM. ++void os::abort(bool dump_core) { ++ os::shutdown(); ++ if (dump_core) { ++#ifndef PRODUCT ++ fdStream out(defaultStream::output_fd()); ++ out.print_raw("Current thread is "); ++ char buf[16]; ++ jio_snprintf(buf, sizeof(buf), UINTX_FORMAT, os::current_thread_id()); ++ out.print_raw_cr(buf); ++ out.print_raw_cr("Dumping core ..."); ++#endif ++ ::abort(); // dump core ++ } ++ ++ ::exit(1); ++} ++ ++// Die immediately, no exit hook, no abort hook, no cleanup. ++void os::die() { ++ // _exit() on LinuxThreads only kills current thread ++ ::abort(); ++} ++ ++// unused on linux for now. ++void os::set_error_file(const char *logfile) {} ++ ++ ++// This method is a copy of JDK's sysGetLastErrorString ++// from src/solaris/hpi/src/system_md.c ++ ++size_t os::lasterror(char *buf, size_t len) { ++ ++ if (errno == 0) return 0; ++ ++ const char *s = ::strerror(errno); ++ size_t n = ::strlen(s); ++ if (n >= len) { ++ n = len - 1; ++ } ++ ::strncpy(buf, s, n); ++ buf[n] = '\0'; ++ return n; ++} ++ ++intx os::current_thread_id() { return (intx)pthread_self(); } ++int os::current_process_id() { ++ ++ // Under the old linux thread library, linux gives each thread ++ // its own process id. Because of this each thread will return ++ // a different pid if this method were to return the result ++ // of getpid(2). Linux provides no api that returns the pid ++ // of the launcher thread for the vm. This implementation ++ // returns a unique pid, the pid of the launcher thread ++ // that starts the vm 'process'. ++ ++ // Under the NPTL, getpid() returns the same pid as the ++ // launcher thread rather than a unique pid per thread. ++ // Use gettid() if you want the old pre NPTL behaviour. ++ ++ // if you are looking for the result of a call to getpid() that ++ // returns a unique pid for the calling thread, then look at the ++ // OSThread::thread_id() method in osThread_linux.hpp file ++ ++ return (int)(_initial_pid ? _initial_pid : getpid()); ++} ++ ++// DLL functions ++ ++const char* os::dll_file_extension() { return ".so"; } ++ ++// This must be hard coded because it's the system's temporary ++// directory not the java application's temp directory, ala java.io.tmpdir. ++const char* os::get_temp_directory() { return "/tmp"; } ++ ++static bool file_exists(const char* filename) { ++ struct stat statbuf; ++ if (filename == NULL || strlen(filename) == 0) { ++ return false; ++ } ++ return os::stat(filename, &statbuf) == 0; ++} ++ ++void os::dll_build_name(char* buffer, size_t buflen, ++ const char* pname, const char* fname) { ++ // Copied from libhpi ++ const size_t pnamelen = pname ? strlen(pname) : 0; ++ ++ // Quietly truncate on buffer overflow. Should be an error. ++ if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { ++ *buffer = '\0'; ++ return; ++ } ++ ++ if (pnamelen == 0) { ++ snprintf(buffer, buflen, "lib%s.so", fname); ++ } else if (strchr(pname, *os::path_separator()) != NULL) { ++ int n; ++ char** pelements = split_path(pname, &n); ++ for (int i = 0 ; i < n ; i++) { ++ // Really shouldn't be NULL, but check can't hurt ++ if (pelements[i] == NULL || strlen(pelements[i]) == 0) { ++ continue; // skip the empty path values ++ } ++ snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname); ++ if (file_exists(buffer)) { ++ break; ++ } ++ } ++ // release the storage ++ for (int i = 0 ; i < n ; i++) { ++ if (pelements[i] != NULL) { ++ FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal); ++ } ++ } ++ if (pelements != NULL) { ++ FREE_C_HEAP_ARRAY(char*, pelements, mtInternal); ++ } ++ }