From dfecd740e315f8af5f122a8b9c63a056542ec4d1 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Tue, 17 Jun 2014 19:10:16 +0200 Subject: fix openjdk7 build for glibc --- package/openjdk7/Makefile | 3 +- package/openjdk7/patches/openadk.patch | 6389 +------------------------------- 2 files changed, 32 insertions(+), 6360 deletions(-) (limited to 'package/openjdk7') diff --git a/package/openjdk7/Makefile b/package/openjdk7/Makefile index 18578561c..027309fbf 100644 --- a/package/openjdk7/Makefile +++ b/package/openjdk7/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:= openjdk7 PKG_VERSION:= 2.4.7 -PKG_RELEASE:= 5 +PKG_RELEASE:= 6 PKG_MD5SUM:= f6b28633b9978fadc724247cfc264ff0 PKG_DESCR:= java virtual machine PKG_SECTION:= dev/lang @@ -21,6 +21,7 @@ PKG_DEPENDS+= libpng giflib libgtk glib fontconfig PKG_URL:= http://openjdk.org/ PKG_SITES:= http://icedtea.classpath.org/download/source/ +PKG_BUILDDEP_UCLIBC:= libiconv-tiny DISTFILES:= icedtea-$(PKG_VERSION).tar.xz WRKDIST= ${WRKDIR}/icedtea-${PKG_VERSION} diff --git a/package/openjdk7/patches/openadk.patch b/package/openjdk7/patches/openadk.patch index 601640a92..16f4fae8c 100644 --- a/package/openjdk7/patches/openadk.patch +++ b/package/openjdk7/patches/openadk.patch @@ -1,6 +1,6 @@ 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 ++++ icedtea-2.4.7/Makefile.in 2014-06-17 17:37:10.283965087 +0200 @@ -712,7 +712,7 @@ $(am__append_14) $(am__append_15) $(DISTRIBUTION_PATCHES) @@ -12,11 +12,11 @@ diff -Nur icedtea-2.4.7.orig/Makefile.in icedtea-2.4.7/Makefile.in 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-15 15:52:54.503242117 +0200 -@@ -0,0 +1,7020 @@ ++++ icedtea-2.4.7/patches/openadk.patch 2014-06-17 17:42:10.926234673 +0200 +@@ -0,0 +1,691 @@ +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 +++++ openjdk/hotspot/make/linux/makefiles/zeroshark.make 2014-06-17 17:39:28.697018938 +0200 +@@ -39,20 +39,20 @@ + + offsets_arm.s: mkoffsets @@ -44,7 +44,7 @@ diff -Nur icedtea-2.4.7.orig/patches/openadk.patch icedtea-2.4.7/patches/openadk + 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 +++++ openjdk/hotspot/src/os/linux/vm/os_linux.cpp 2014-06-17 17:39:28.701018968 +0200 +@@ -112,7 +112,6 @@ + # include + # include @@ -99,6002 +99,9 @@ diff -Nur icedtea-2.4.7.orig/patches/openadk.patch icedtea-2.4.7/patches/openadk + } + + 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 pname