Mercurial > hg > graal-compiler
diff src/os/linux/vm/os_linux.cpp @ 18041:52b4284cb496
Merge with jdk8u20-b26
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Wed, 15 Oct 2014 16:02:50 +0200 |
parents | 3eed8712d410 f73af4455d7d |
children | 7848fc12602b |
line wrap: on
line diff
--- a/src/os/linux/vm/os_linux.cpp Thu Oct 16 10:21:29 2014 +0200 +++ b/src/os/linux/vm/os_linux.cpp Wed Oct 15 16:02:50 2014 +0200 @@ -101,6 +101,8 @@ # include <inttypes.h> # include <sys/ioctl.h> +PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC + // if RUSAGE_THREAD for getrusage() has not been defined, do it here. The code calling // getrusage() is prepared to handle the associated failure. #ifndef RUSAGE_THREAD @@ -109,6 +111,8 @@ #define MAX_PATH (2 * K) +#define MAX_SECS 100000000 + // for timer info max values which include all bits #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) @@ -139,7 +143,7 @@ // For diagnostics to print a message once. see run_periodic_checks static sigset_t check_signal_done; -static bool check_signals = true;; +static bool check_signals = true; static pid_t _initial_pid = 0; @@ -257,8 +261,10 @@ static char cpu_arch[] = "amd64"; #elif defined(ARM) static char cpu_arch[] = "arm"; -#elif defined(PPC) +#elif defined(PPC32) static char cpu_arch[] = "ppc"; +#elif defined(PPC64) +static char cpu_arch[] = "ppc64"; #elif defined(SPARC) # ifdef _LP64 static char cpu_arch[] = "sparcv9"; @@ -315,9 +321,6 @@ } 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.so. @@ -344,140 +347,101 @@ // 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. - */ +// 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)) #define DEFAULT_LIBPATH "/usr/lib64:/lib64:/lib:/usr/lib" #else #define DEFAULT_LIBPATH "/lib:/usr/lib" #endif +// Base path of extensions installed on the system. +#define SYS_EXT_DIR "/usr/java/packages" #define EXTENSIONS_DIR "/lib/ext" #define ENDORSED_DIR "/lib/endorsed" -#define REG_DIR "/usr/java/packages" - + + // Buffer that fits several sprintfs. + // Note that the space for the colon and the trailing null are provided + // by the nulls included by the sizeof operator. + const size_t bufsize = + MAX3((size_t)MAXPATHLEN, // For dll_dir & friends. + (size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR), // extensions dir + (size_t)MAXPATHLEN + sizeof(ENDORSED_DIR)); // endorsed dir + char *buf = (char *)NEW_C_HEAP_ARRAY(char, bufsize, mtInternal); + + // sysclasspath, java_home, dll_dir { - /* 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 <java_home>/jre if we can. - *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */ + char *pslash; + os::jvm_path(buf, bufsize); + + // Found the full path to libjvm.so. + // Now cut the path to <java_home>/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}. + } + Arguments::set_dll_dir(buf); + + if (pslash != NULL) { + pslash = strrchr(buf, '/'); + if (pslash != NULL) { + *pslash = '\0'; // Get rid of /<arch>. 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 /<arch> */ - pslash = strrchr(buf, '/'); - if (pslash != NULL) - *pslash = '\0'; /* get rid of /lib */ - } + *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 + Arguments::set_java_home(buf); + set_boot_path('/', ':'); + } + + // 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. + { + // Get the user setting of LD_LIBRARY_PATH, and prepended it. It + // should always exist (until the legacy problem cited above is + // addressed). + const char *v = ::getenv("LD_LIBRARY_PATH"); + const char *v_colon = ":"; + if (v == NULL) { v = ""; v_colon = ""; } + // That's +1 for the colon and +1 for the trailing '\0'. + char *ld_library_path = (char *)NEW_C_HEAP_ARRAY(char, + strlen(v) + 1 + + sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1, + mtInternal); + sprintf(ld_library_path, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch); + Arguments::set_library_path(ld_library_path); + FREE_C_HEAP_ARRAY(char, ld_library_path, mtInternal); + } + + // Extensions directories. + sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home()); + Arguments::set_ext_dirs(buf); + + // Endorsed standards default directory. + sprintf(buf, "%s" ENDORSED_DIR, Arguments::get_java_home()); + Arguments::set_endorsed_dirs(buf); + + FREE_C_HEAP_ARRAY(char, buf, mtInternal); + +#undef DEFAULT_LIBPATH +#undef SYS_EXT_DIR #undef EXTENSIONS_DIR #undef ENDORSED_DIR - - // Done - return; } //////////////////////////////////////////////////////////////////////////////// @@ -530,6 +494,9 @@ sigaddset(&unblocked_sigs, SIGSEGV); sigaddset(&unblocked_sigs, SIGBUS); sigaddset(&unblocked_sigs, SIGFPE); +#if defined(PPC64) + sigaddset(&unblocked_sigs, SIGTRAP); +#endif sigaddset(&unblocked_sigs, SR_signum); if (!ReduceSignalUsage) { @@ -1067,9 +1034,20 @@ ////////////////////////////////////////////////////////////////////////////// // thread local storage +// Restore the thread pointer if the destructor is called. This is in case +// someone from JNI code sets up a destructor with pthread_key_create to run +// detachCurrentThread on thread death. Unless we restore the thread pointer we +// will hang or crash. When detachCurrentThread is called the key will be set +// to null and we will not be called again. If detachCurrentThread is never +// called we could loop forever depending on the pthread implementation. +static void restore_thread_pointer(void* p) { + Thread* thread = (Thread*) p; + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} + int os::allocate_thread_local_storage() { pthread_key_t key; - int rslt = pthread_key_create(&key, NULL); + int rslt = pthread_key_create(&key, restore_thread_pointer); assert(rslt == 0, "cannot allocate thread local storage"); return (int)key; } @@ -1953,7 +1931,11 @@ {EM_SPARC32PLUS, EM_SPARC, ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"}, {EM_SPARCV9, EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"}, {EM_PPC, EM_PPC, ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"}, +#if defined(VM_LITTLE_ENDIAN) + {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2LSB, (char*)"Power PC 64"}, +#else {EM_PPC64, EM_PPC64, ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"}, +#endif {EM_ARM, EM_ARM, ELFCLASS32, ELFDATA2LSB, (char*)"ARM"}, {EM_S390, EM_S390, ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"}, {EM_ALPHA, EM_ALPHA, ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"}, @@ -2101,6 +2083,9 @@ return res; } +void* os::get_default_process_handle() { + return (void*)::dlopen(NULL, RTLD_LAZY); +} static bool _print_ascii_file(const char* filename, outputStream* st) { int fd = ::open(filename, O_RDONLY); @@ -2151,7 +2136,7 @@ // Print warning if unsafe chroot environment detected if (unsafe_chroot_detected) { st->print("WARNING!! "); - st->print_cr(unstable_chroot_error); + st->print_cr("%s", unstable_chroot_error); } os::Linux::print_libversion_info(st); @@ -2212,8 +2197,8 @@ void os::Linux::print_libversion_info(outputStream* st) { // libc, pthread st->print("libc:"); - st->print(os::Linux::glibc_version()); st->print(" "); - st->print(os::Linux::libpthread_version()); st->print(" "); + st->print("%s ", os::Linux::glibc_version()); + st->print("%s ", os::Linux::libpthread_version()); if (os::Linux::is_LinuxThreads()) { st->print("(%s stack)", os::Linux::is_floating_stack() ? "floating" : "fixed"); } @@ -2254,58 +2239,12 @@ st->cr(); } -// Taken from /usr/include/bits/siginfo.h Supposed to be architecture specific -// but they're the same for all the linux arch that we support -// and they're the same for solaris but there's no common place to put this. -const char *ill_names[] = { "ILL0", "ILL_ILLOPC", "ILL_ILLOPN", "ILL_ILLADR", - "ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG", - "ILL_COPROC", "ILL_BADSTK" }; - -const char *fpe_names[] = { "FPE0", "FPE_INTDIV", "FPE_INTOVF", "FPE_FLTDIV", - "FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES", - "FPE_FLTINV", "FPE_FLTSUB", "FPE_FLTDEN" }; - -const char *segv_names[] = { "SEGV0", "SEGV_MAPERR", "SEGV_ACCERR" }; - -const char *bus_names[] = { "BUS0", "BUS_ADRALN", "BUS_ADRERR", "BUS_OBJERR" }; - void os::print_siginfo(outputStream* st, void* siginfo) { - st->print("siginfo:"); - - const int buflen = 100; - char buf[buflen]; - siginfo_t *si = (siginfo_t*)siginfo; - st->print("si_signo=%s: ", os::exception_name(si->si_signo, buf, buflen)); - if (si->si_errno != 0 && strerror_r(si->si_errno, buf, buflen) == 0) { - st->print("si_errno=%s", buf); - } else { - st->print("si_errno=%d", si->si_errno); - } - const int c = si->si_code; - assert(c > 0, "unexpected si_code"); - switch (si->si_signo) { - case SIGILL: - st->print(", si_code=%d (%s)", c, c > 8 ? "" : ill_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGFPE: - st->print(", si_code=%d (%s)", c, c > 9 ? "" : fpe_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGSEGV: - st->print(", si_code=%d (%s)", c, c > 2 ? "" : segv_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - case SIGBUS: - st->print(", si_code=%d (%s)", c, c > 3 ? "" : bus_names[c]); - st->print(", si_addr=" PTR_FORMAT, si->si_addr); - break; - default: - st->print(", si_code=%d", si->si_code); - // no si_addr - } - - if ((si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && + const siginfo_t* si = (const siginfo_t*)siginfo; + + os::Posix::print_siginfo_brief(st, si); + + if (si && (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) && UseSharedSpaces) { FileMapInfo* mapinfo = FileMapInfo::current_info(); if (mapinfo->is_in_shared_space(si->si_addr)) { @@ -2335,6 +2274,9 @@ print_signal_handler(st, SHUTDOWN2_SIGNAL , buf, buflen); print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen); print_signal_handler(st, BREAK_SIGNAL, buf, buflen); +#if defined(PPC64) + print_signal_handler(st, SIGTRAP, buf, buflen); +#endif } static char saved_jvm_path[MAXPATHLEN] = {0}; @@ -2466,7 +2408,6 @@ sem_t _semaphore; }; - Semaphore::Semaphore() { sem_init(&_semaphore, 0, 0); } @@ -2488,8 +2429,22 @@ } bool Semaphore::timedwait(unsigned int sec, int nsec) { + struct timespec ts; - unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + // Semaphore's are always associated with CLOCK_REALTIME + os::Linux::clock_gettime(CLOCK_REALTIME, &ts); + // see unpackTime for discussion on overflow checking + if (sec >= MAX_SECS) { + ts.tv_sec += MAX_SECS; + ts.tv_nsec = 0; + } else { + ts.tv_sec += sec; + ts.tv_nsec += nsec; + if (ts.tv_nsec >= NANOSECS_PER_SEC) { + ts.tv_nsec -= NANOSECS_PER_SEC; + ++ts.tv_sec; // note: this must be <= max_secs + } + } while (1) { int result = sem_timedwait(&_semaphore, &ts); @@ -2994,7 +2949,9 @@ unsigned char vec[1]; unsigned imin = 1, imax = pages + 1, imid; - int mincore_return_value; + int mincore_return_value = 0; + + assert(imin <= imax, "Unexpected page size"); while (imin < imax) { imid = (imax + imin) / 2; @@ -3458,7 +3415,7 @@ // the system is still "fresh". if (warn_on_failure) { jio_snprintf(msg, sizeof(msg), "Failed to reserve shared memory (errno = %d).", errno); - warning(msg); + warning("%s", msg); } return NULL; } @@ -3476,7 +3433,7 @@ if ((intptr_t)addr == -1) { if (warn_on_failure) { jio_snprintf(msg, sizeof(msg), "Failed to attach shared memory (errno = %d).", err); - warning(msg); + warning("%s", msg); } return NULL; } @@ -3496,7 +3453,7 @@ char msg[128]; jio_snprintf(msg, sizeof(msg), "Failed to reserve large pages memory req_addr: " PTR_FORMAT " bytes: " SIZE_FORMAT " (errno = %d).", req_addr, bytes, error); - warning(msg); + warning("%s", msg); } } @@ -3866,9 +3823,33 @@ } } -int os::naked_sleep() { - // %% make the sleep time an integer flag. for now use 1 millisec. - return os::sleep(Thread::current(), 1, false); +// +// Short sleep, direct OS call. +// +// Note: certain versions of Linux CFS scheduler (since 2.6.23) do not guarantee +// sched_yield(2) will actually give up the CPU: +// +// * Alone on this pariticular CPU, keeps running. +// * Before the introduction of "skip_buddy" with "compat_yield" disabled +// (pre 2.6.39). +// +// So calling this with 0 is an alternative. +// +void os::naked_short_sleep(jlong ms) { + struct timespec req; + + assert(ms < 1000, "Un-interruptable sleep, short time use only"); + req.tv_sec = 0; + if (ms > 0) { + req.tv_nsec = (ms % 1000) * 1000000; + } + else { + req.tv_nsec = 1; + } + + nanosleep(&req, NULL); + + return; } // Sleep forever; naked call to OS-specific sleep; use with CAUTION @@ -4465,6 +4446,9 @@ set_signal_handler(SIGBUS, true); set_signal_handler(SIGILL, true); set_signal_handler(SIGFPE, true); +#if defined(PPC64) + set_signal_handler(SIGTRAP, true); +#endif set_signal_handler(SIGXFSZ, true); if (libjsig_is_loaded) { @@ -4558,7 +4542,8 @@ st->print("[%s]", get_signal_handler_name(handler, buf, buflen)); } - st->print(", sa_mask[0]=" PTR32_FORMAT, *(uint32_t*)&sa.sa_mask); + st->print(", sa_mask[0]="); + os::Posix::print_signal_set_short(st, &sa.sa_mask); address rh = VMError::get_resetted_sighandler(sig); // May be, handler was resetted by VMError? @@ -4567,7 +4552,8 @@ sa.sa_flags = VMError::get_resetted_sigflags(sig) & SIGNIFICANT_SIGNAL_MASK; } - st->print(", sa_flags=" PTR32_FORMAT, sa.sa_flags); + st->print(", sa_flags="); + os::Posix::print_sa_flags(st, sa.sa_flags); // Check: is it our handler? if(handler == CAST_FROM_FN_PTR(address, (sa_sigaction_t)signalHandler) || @@ -4605,7 +4591,9 @@ DO_SIGNAL_CHECK(SIGBUS); DO_SIGNAL_CHECK(SIGPIPE); DO_SIGNAL_CHECK(SIGXFSZ); - +#if defined(PPC64) + DO_SIGNAL_CHECK(SIGTRAP); +#endif // ReduceSignalUsage allows the user to override these handlers // see comments at the very top and jvm_solaris.h @@ -4927,7 +4915,7 @@ // the future if the appropriate cleanup code can be added to the // VM_Exit VMOperation's doit method. if (atexit(perfMemory_exit_helper) != 0) { - warning("os::init2 atexit(perfMemory_exit_helper) failed"); + warning("os::init_2 atexit(perfMemory_exit_helper) failed"); } } @@ -4938,8 +4926,7 @@ } // this is called at the end of vm_initialization -void os::init_3(void) -{ +void os::init_3(void) { #ifdef JAVASE_EMBEDDED // Start the MemNotifyThread if (LowMemoryProtection) { @@ -5410,6 +5397,8 @@ // -1 on error. // +PRAGMA_DIAG_PUSH +PRAGMA_FORMAT_NONLITERAL_IGNORED static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { static bool proc_task_unchecked = true; static const char *proc_stat_path = "/proc/%d/stat"; @@ -5471,6 +5460,7 @@ return (jlong)user_time * (1000000000 / clock_tics_per_sec); } } +PRAGMA_DIAG_POP void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits @@ -5784,7 +5774,6 @@ * is no need to track notifications. */ -#define MAX_SECS 100000000 /* * This code is common to linux and solaris and will be moved to a * common place in dolphin.