From 3cf55e2bc095ac6dc345217c993f80d74c6b5714 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Tue, 13 May 2014 18:07:03 +0200 Subject: fix openjdk build errors for arm target --- package/openjdk7/Makefile | 1 + package/openjdk7/patches/openadk.patch | 6514 +++++++++++++++++++++++++++++++- 2 files changed, 6396 insertions(+), 119 deletions(-) (limited to 'package/openjdk7') diff --git a/package/openjdk7/Makefile b/package/openjdk7/Makefile index 41697c9c2..1b654300b 100644 --- a/package/openjdk7/Makefile +++ b/package/openjdk7/Makefile @@ -102,6 +102,7 @@ OPENJDK_NATIVE_ENV:= JAVACFLAGS="-cp ${STAGING_HOST_DIR}/usr/share/java/libgcj-$ BOOTCLASSPATH="$(STAGING_HOST_DIR)/usr/share/jamvm/classes.zip:$(STAGING_HOST_DIR)/usr/share/classpath/glibj.zip" \ FFI_LDFLAGS="$(LDFLAGS_FOR_BUILD)" \ OTHER_LDFLAGS='$(LDFLAGS_FOR_BUILD)' \ + ALT_OPENWIN_HOME=$(STAGING_HOST_DIR)/usr/ \ ALT_CUPS_HEADERS_PATH="$(STAGING_HOST_DIR)/usr/include" \ ALT_FREETYPE_HEADERS_PATH="$(STAGING_HOST_DIR)/usr/include" \ ALT_FREETYPE_LIB_PATH="$(STAGING_HOST_DIR)/usr/lib" \ diff --git a/package/openjdk7/patches/openadk.patch b/package/openjdk7/patches/openadk.patch index dd31ed5ba..3001aff5b 100644 --- a/package/openjdk7/patches/openadk.patch +++ b/package/openjdk7/patches/openadk.patch @@ -12,11 +12,39 @@ 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-08 21:02:03.459173373 +0200 -@@ -0,0 +1,733 @@ ++++ 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-01-28 18:58:08.000000000 +0100 -++++ openjdk/hotspot/src/os/linux/vm/os_linux.cpp 2014-02-10 11:31:48.000000000 +0100 ++--- 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 @@ -48,7 +76,7 @@ diff -Nur icedtea-2.4.7.orig/patches/openadk.patch icedtea-2.4.7/patches/openadk + return f; + } + -+@@ -5312,7 +5306,21 @@ ++@@ -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) { @@ -57,23 +85,6016 @@ diff -Nur icedtea-2.4.7.orig/patches/openadk.patch icedtea-2.4.7/patches/openadk ++ 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); -++ } +++ 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() return