diff options
Diffstat (limited to 'src/os')
-rw-r--r-- | src/os/aix/vm/os_aix.cpp | 12 | ||||
-rw-r--r-- | src/os/aix/vm/perfMemory_aix.cpp | 33 | ||||
-rw-r--r-- | src/os/bsd/dtrace/hotspot.d | 6 | ||||
-rw-r--r-- | src/os/bsd/vm/jsig.c | 34 | ||||
-rw-r--r-- | src/os/bsd/vm/os_bsd.cpp | 22 | ||||
-rw-r--r-- | src/os/bsd/vm/perfMemory_bsd.cpp | 27 | ||||
-rw-r--r-- | src/os/linux/vm/os_linux.cpp | 207 | ||||
-rw-r--r-- | src/os/linux/vm/perfMemory_linux.cpp | 27 | ||||
-rw-r--r-- | src/os/solaris/vm/jvm_solaris.h | 4 | ||||
-rw-r--r-- | src/os/solaris/vm/os_solaris.cpp | 198 | ||||
-rw-r--r-- | src/os/solaris/vm/os_solaris.hpp | 2 | ||||
-rw-r--r-- | src/os/solaris/vm/perfMemory_solaris.cpp | 27 | ||||
-rw-r--r-- | src/os/solaris/vm/thread_solaris.inline.hpp | 19 | ||||
-rw-r--r-- | src/os/windows/vm/os_windows.cpp | 32 |
14 files changed, 245 insertions, 405 deletions
diff --git a/src/os/aix/vm/os_aix.cpp b/src/os/aix/vm/os_aix.cpp index 9a65f741a..4cd28b868 100644 --- a/src/os/aix/vm/os_aix.cpp +++ b/src/os/aix/vm/os_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2014 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -3727,6 +3727,11 @@ void os::Aix::check_signal_handler(int sig) { tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN)); // No need to check this sig any longer sigaddset(&check_signal_done, sig); + // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN + if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) { + tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell", + exception_name(sig, buf, O_BUFLEN)); + } } else if (os::Aix::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Aix::get_our_sigflags(sig)) { tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN)); tty->print("expected:" PTR32_FORMAT, os::Aix::get_our_sigflags(sig)); @@ -3987,11 +3992,6 @@ jint os::init_2(void) { return JNI_OK; } -// this is called at the end of vm_initialization -void os::init_3(void) { - return; -} - // Mark the polling page as unreadable void os::make_polling_page_unreadable(void) { if (!guard_memory((char*)_polling_page, Aix::page_size())) { diff --git a/src/os/aix/vm/perfMemory_aix.cpp b/src/os/aix/vm/perfMemory_aix.cpp index 7d64b5f83..be6e855d9 100644 --- a/src/os/aix/vm/perfMemory_aix.cpp +++ b/src/os/aix/vm/perfMemory_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2013 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -201,6 +201,7 @@ static pid_t filename_to_pid(const char* filename) { // the backing store files. Returns true if the directory is considered // a secure location. Returns false if the statbuf is a symbolic link or // if an error occurred. +// static bool is_statbuf_secure(struct stat *statp) { if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) { // The path represents a link or some non-directory file type, @@ -209,15 +210,18 @@ static bool is_statbuf_secure(struct stat *statp) { return false; } // We have an existing directory, check if the permissions are safe. + // if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) { // The directory is open for writing and could be subjected // to a symlink or a hard link attack. Declare it insecure. + // return false; } - // See if the uid of the directory matches the effective uid of the process. - // - if (statp->st_uid != geteuid()) { + // If user is not root then see if the uid of the directory matches the effective uid of the process. + uid_t euid = geteuid(); + if ((euid != 0) && (statp->st_uid != euid)) { // The directory was not created by this user, declare it insecure. + // return false; } return true; @@ -228,6 +232,7 @@ static bool is_statbuf_secure(struct stat *statp) { // the backing store files. Returns true if the directory exists // and is considered a secure location. Returns false if the path // is a symbolic link or if an error occurred. +// static bool is_directory_secure(const char* path) { struct stat statbuf; int result = 0; @@ -454,13 +459,27 @@ static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { *saved_cwd_fd = result; } - // Set the current directory to dirname by using the fd of the directory. + // Set the current directory to dirname by using the fd of the directory and + // handle errors, otherwise shared memory files will be created in cwd. result = fchdir(fd); - - return dirp; + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not change to directory %s", dirname); + } + if (*saved_cwd_fd != -1) { + ::close(*saved_cwd_fd); + *saved_cwd_fd = -1; + } + // Close the directory. + os::closedir(dirp); + return NULL; + } else { + return dirp; + } } // Close the directory and restore the current working directory. +// static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) { int result; diff --git a/src/os/bsd/dtrace/hotspot.d b/src/os/bsd/dtrace/hotspot.d index 0e4802b51..996e1d782 100644 --- a/src/os/bsd/dtrace/hotspot.d +++ b/src/os/bsd/dtrace/hotspot.d @@ -47,8 +47,8 @@ provider hotspot { probe mem__pool__gc__end( char*, uintptr_t, char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); - probe thread__probe__start(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); - probe thread__probe__stop(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); + probe thread__start(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); + probe thread__stop(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); probe thread__sleep__begin(long long); probe thread__sleep__end(int); probe thread__yield(); @@ -68,7 +68,7 @@ provider hotspot { probe monitor__contended__entered(uintptr_t, uintptr_t, char*, uintptr_t); probe monitor__contended__exit(uintptr_t, uintptr_t, char*, uintptr_t); probe monitor__wait(uintptr_t, uintptr_t, char*, uintptr_t, uintptr_t); - probe monitor__probe__waited(uintptr_t, uintptr_t, char*, uintptr_t); + probe monitor__waited(uintptr_t, uintptr_t, char*, uintptr_t); probe monitor__notify(uintptr_t, uintptr_t, char*, uintptr_t); probe monitor__notifyAll(uintptr_t, uintptr_t, char*, uintptr_t); diff --git a/src/os/bsd/vm/jsig.c b/src/os/bsd/vm/jsig.c index a8d98a084..a3ea0fdd4 100644 --- a/src/os/bsd/vm/jsig.c +++ b/src/os/bsd/vm/jsig.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, 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 @@ -36,6 +36,7 @@ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> +#include <string.h> #define MAXSIGNUM 32 #define MASK(sig) ((unsigned int)1 << sig) @@ -43,6 +44,9 @@ static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */ static unsigned int jvmsigs = 0; /* signals used by jvm */ +static pthread_key_t reentry_flag_key; +static pthread_once_t reentry_key_init_once = PTHREAD_ONCE_INIT; + /* used to synchronize the installation of signal handlers */ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; @@ -59,6 +63,15 @@ static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ static bool jvm_signal_installing = false; static bool jvm_signal_installed = false; +#define check_status(cmd) \ + do { \ + int status = (cmd); \ + if (status != 0) { \ + printf("error %s (%d) in " #cmd "\n", strerror(status), status); \ + exit(1); \ + } \ + } while (0) + static void signal_lock() { pthread_mutex_lock(&mutex); /* When the jvm is installing its set of signal handlers, threads @@ -74,8 +87,15 @@ static void signal_unlock() { pthread_mutex_unlock(&mutex); } +static void reentry_tls_init() { + // value for reentry_flag_key will default to NULL (false) + check_status(pthread_key_create(&reentry_flag_key, NULL)); +} + static sa_handler_t call_os_signal(int sig, sa_handler_t disp, bool is_sigset) { + sa_handler_t res; + if (os_signal == NULL) { if (!is_sigset) { os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); @@ -87,7 +107,12 @@ static sa_handler_t call_os_signal(int sig, sa_handler_t disp, exit(0); } } - return (*os_signal)(sig, disp); + check_status(pthread_once(&reentry_key_init_once, reentry_tls_init)); + // set reentry_flag_key to non-NULL to show reentry + check_status(pthread_setspecific(reentry_flag_key, &res)); + res = (*os_signal)(sig, disp); + check_status(pthread_setspecific(reentry_flag_key, NULL)); + return res; } static void save_signal_handler(int sig, sa_handler_t disp) { @@ -161,6 +186,11 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { bool sigused; struct sigaction oldAct; + check_status(pthread_once(&reentry_key_init_once, reentry_tls_init)); + if (pthread_getspecific(reentry_flag_key) != NULL) { + return call_os_sigaction(sig, act, oact); + } + signal_lock(); sigused = (MASK(sig) & jvmsigs) != 0; diff --git a/src/os/bsd/vm/os_bsd.cpp b/src/os/bsd/vm/os_bsd.cpp index e1c53c5b4..58b58967c 100644 --- a/src/os/bsd/vm/os_bsd.cpp +++ b/src/os/bsd/vm/os_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -1197,12 +1197,18 @@ pid_t os::Bsd::gettid() { guarantee(retval != 0, "just checking"); return retval; -#elif __FreeBSD__ +#else + #ifdef __FreeBSD__ retval = syscall(SYS_thr_self); -#elif __OpenBSD__ + #else + #ifdef __OpenBSD__ retval = syscall(SYS_getthrid); -#elif __NetBSD__ + #else + #ifdef __NetBSD__ retval = (pid_t) syscall(SYS__lwp_self); + #endif + #endif + #endif #endif if (retval == -1) { @@ -3545,6 +3551,11 @@ void os::Bsd::check_signal_handler(int sig) { tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN)); // No need to check this sig any longer sigaddset(&check_signal_done, sig); + // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN + if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) { + tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell", + exception_name(sig, buf, O_BUFLEN)); + } } else if(os::Bsd::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Bsd::get_our_sigflags(sig)) { tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN)); tty->print("expected:" PTR32_FORMAT, os::Bsd::get_our_sigflags(sig)); @@ -3745,9 +3756,6 @@ jint os::init_2(void) return JNI_OK; } -// this is called at the end of vm_initialization -void os::init_3(void) { } - // Mark the polling page as unreadable void os::make_polling_page_unreadable(void) { if( !guard_memory((char*)_polling_page, Bsd::page_size()) ) diff --git a/src/os/bsd/vm/perfMemory_bsd.cpp b/src/os/bsd/vm/perfMemory_bsd.cpp index 5ee992ec0..f25c39d9e 100644 --- a/src/os/bsd/vm/perfMemory_bsd.cpp +++ b/src/os/bsd/vm/perfMemory_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, 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 @@ -217,9 +217,9 @@ static bool is_statbuf_secure(struct stat *statp) { // return false; } - // See if the uid of the directory matches the effective uid of the process. - // - if (statp->st_uid != geteuid()) { + // If user is not root then see if the uid of the directory matches the effective uid of the process. + uid_t euid = geteuid(); + if ((euid != 0) && (statp->st_uid != euid)) { // The directory was not created by this user, declare it insecure. // return false; @@ -375,10 +375,23 @@ static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { *saved_cwd_fd = result; } - // Set the current directory to dirname by using the fd of the directory. + // Set the current directory to dirname by using the fd of the directory and + // handle errors, otherwise shared memory files will be created in cwd. result = fchdir(fd); - - return dirp; + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not change to directory %s", dirname); + } + if (*saved_cwd_fd != -1) { + ::close(*saved_cwd_fd); + *saved_cwd_fd = -1; + } + // Close the directory. + os::closedir(dirp); + return NULL; + } else { + return dirp; + } } // Close the directory and restore the current working directory. diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp index 3a24939a1..4f7c38ab3 100644 --- a/src/os/linux/vm/os_linux.cpp +++ b/src/os/linux/vm/os_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -160,35 +160,6 @@ 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(); @@ -238,44 +209,27 @@ bool os::have_special_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 + #ifdef __ia64__ + #define SYS_gettid 1105 + #else + #ifdef __i386__ + #define SYS_gettid 224 + #else + #ifdef __amd64__ + #define SYS_gettid 186 + #else + #ifdef __sparc__ + #define SYS_gettid 143 + #else + #error define gettid for the arch + #endif + #endif + #endif + #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(PPC32) -static char cpu_arch[] = "ppc"; -#elif defined(PPC64) -static char cpu_arch[] = "ppc64"; -#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 - +static char cpu_arch[] = HOTSPOT_LIB_ARCH; // pid_t gettid() // @@ -4681,6 +4635,11 @@ void os::Linux::check_signal_handler(int sig) { tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN)); // No need to check this sig any longer sigaddset(&check_signal_done, sig); + // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN + if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) { + tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell", + exception_name(sig, buf, O_BUFLEN)); + } } else if(os::Linux::get_our_sigflags(sig) != 0 && (int)act.sa_flags != os::Linux::get_our_sigflags(sig)) { tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN)); tty->print("expected:" PTR32_FORMAT, os::Linux::get_our_sigflags(sig)); @@ -4936,17 +4895,6 @@ jint os::init_2(void) return JNI_OK; } -// this is called at the end of vm_initialization -void os::init_3(void) { -#ifdef JAVASE_EMBEDDED - // Start the MemNotifyThread - if (LowMemoryProtection) { - MemNotifyThread::start(); - } - return; -#endif -} - // Mark the polling page as unreadable void os::make_polling_page_unreadable(void) { if( !guard_memory((char*)_polling_page, Linux::page_size()) ) @@ -5974,9 +5922,11 @@ void Parker::unpark() { status = pthread_mutex_unlock(_mutex); assert (status == 0, "invariant"); } else { + // must capture correct index before unlocking + int index = _cur_index; status = pthread_mutex_unlock(_mutex); assert (status == 0, "invariant"); - status = pthread_cond_signal (&_cond[_cur_index]); + status = pthread_cond_signal (&_cond[index]); assert (status == 0, "invariant"); } } else { @@ -5992,14 +5942,6 @@ void Parker::unpark() { extern char** environ; -#ifndef __NR_fork -#define __NR_fork IA32_ONLY(2) IA64_ONLY(not defined) AMD64_ONLY(57) -#endif - -#ifndef __NR_execve -#define __NR_execve IA32_ONLY(11) IA64_ONLY(1033) AMD64_ONLY(59) -#endif - // Run the specified command in a separate process. Return its exit value, // or -1 on failure (e.g. can't fork a new process). // Unlike system(), this function can be called from signal handler. It @@ -6007,13 +5949,7 @@ extern char** environ; int os::fork_and_exec(char* cmd) { const char * argv[4] = {"sh", "-c", cmd, NULL}; - // fork() in LinuxThreads/NPTL is not async-safe. It needs to run - // pthread_atfork handlers and reset pthread library. All we need is a - // separate process to execve. Make a direct syscall to fork process. - // On IA64 there's no fork syscall, we have to use fork() and hope for - // the best... - pid_t pid = NOT_IA64(syscall(__NR_fork);) - IA64_ONLY(fork();) + pid_t pid = fork(); if (pid < 0) { // fork failed @@ -6022,15 +5958,7 @@ int os::fork_and_exec(char* cmd) { } else if (pid == 0) { // child process - // execve() in LinuxThreads will call pthread_kill_other_threads_np() - // first to kill every thread on the thread list. Because this list is - // not reset by fork() (see notes above), execve() will instead kill - // every thread in the parent process. We know this is the only thread - // in the new process, so make a system call directly. - // IA64 should use normal execve() from glibc to match the glibc fork() - // above. - NOT_IA64(syscall(__NR_execve, "/bin/sh", argv, environ);) - IA64_ONLY(execve("/bin/sh", (char* const*)argv, environ);) + execve("/bin/sh", (char* const*)argv, environ); // execve failed _exit(-1); @@ -6123,83 +6051,6 @@ int os::get_core_path(char* buffer, size_t bufferSize) { return strlen(buffer); } -#ifdef JAVASE_EMBEDDED -// -// A thread to watch the '/dev/mem_notify' device, which will tell us when the OS is running low on memory. -// -MemNotifyThread* MemNotifyThread::_memnotify_thread = NULL; - -// ctor -// -MemNotifyThread::MemNotifyThread(int fd): Thread() { - assert(memnotify_thread() == NULL, "we can only allocate one MemNotifyThread"); - _fd = fd; - - if (os::create_thread(this, os::os_thread)) { - _memnotify_thread = this; - os::set_priority(this, NearMaxPriority); - os::start_thread(this); - } -} - -// Where all the work gets done -// -void MemNotifyThread::run() { - assert(this == memnotify_thread(), "expected the singleton MemNotifyThread"); - - // Set up the select arguments - fd_set rfds; - if (_fd != -1) { - FD_ZERO(&rfds); - FD_SET(_fd, &rfds); - } - - // Now wait for the mem_notify device to wake up - while (1) { - // Wait for the mem_notify device to signal us.. - int rc = select(_fd+1, _fd != -1 ? &rfds : NULL, NULL, NULL, NULL); - if (rc == -1) { - perror("select!\n"); - break; - } else if (rc) { - //ssize_t free_before = os::available_memory(); - //tty->print ("Notified: Free: %dK \n",os::available_memory()/1024); - - // The kernel is telling us there is not much memory left... - // try to do something about that - - // If we are not already in a GC, try one. - if (!Universe::heap()->is_gc_active()) { - Universe::heap()->collect(GCCause::_allocation_failure); - - //ssize_t free_after = os::available_memory(); - //tty->print ("Post-Notify: Free: %dK\n",free_after/1024); - //tty->print ("GC freed: %dK\n", (free_after - free_before)/1024); - } - // We might want to do something like the following if we find the GC's are not helping... - // Universe::heap()->size_policy()->set_gc_time_limit_exceeded(true); - } - } -} - -// -// See if the /dev/mem_notify device exists, and if so, start a thread to monitor it. -// -void MemNotifyThread::start() { - int fd; - fd = open ("/dev/mem_notify", O_RDONLY, 0); - if (fd < 0) { - return; - } - - if (memnotify_thread() == NULL) { - new MemNotifyThread(fd); - } -} - -#endif // JAVASE_EMBEDDED - - /////////////// Unit tests /////////////// #ifndef PRODUCT diff --git a/src/os/linux/vm/perfMemory_linux.cpp b/src/os/linux/vm/perfMemory_linux.cpp index 9beb1113e..8510abbac 100644 --- a/src/os/linux/vm/perfMemory_linux.cpp +++ b/src/os/linux/vm/perfMemory_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, 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 @@ -217,9 +217,9 @@ static bool is_statbuf_secure(struct stat *statp) { // return false; } - // See if the uid of the directory matches the effective uid of the process. - // - if (statp->st_uid != geteuid()) { + // If user is not root then see if the uid of the directory matches the effective uid of the process. + uid_t euid = geteuid(); + if ((euid != 0) && (statp->st_uid != euid)) { // The directory was not created by this user, declare it insecure. // return false; @@ -374,10 +374,23 @@ static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { *saved_cwd_fd = result; } - // Set the current directory to dirname by using the fd of the directory. + // Set the current directory to dirname by using the fd of the directory and + // handle errors, otherwise shared memory files will be created in cwd. result = fchdir(fd); - - return dirp; + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not change to directory %s", dirname); + } + if (*saved_cwd_fd != -1) { + ::close(*saved_cwd_fd); + *saved_cwd_fd = -1; + } + // Close the directory. + os::closedir(dirp); + return NULL; + } else { + return dirp; + } } // Close the directory and restore the current working directory. diff --git a/src/os/solaris/vm/jvm_solaris.h b/src/os/solaris/vm/jvm_solaris.h index 57b32ac16..f1fa075bc 100644 --- a/src/os/solaris/vm/jvm_solaris.h +++ b/src/os/solaris/vm/jvm_solaris.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -41,7 +41,9 @@ * JNI conversion, which should be sorted out later. */ +#define __USE_LEGACY_PROTOTYPES__ #include <dirent.h> /* For DIR */ +#undef __USE_LEGACY_PROTOTYPES__ #include <sys/param.h> /* For MAXPATHLEN */ #include <sys/socket.h> /* For socklen_t */ #include <unistd.h> /* For F_OK, R_OK, W_OK */ diff --git a/src/os/solaris/vm/os_solaris.cpp b/src/os/solaris/vm/os_solaris.cpp index c74dc70c6..2b4e33c66 100644 --- a/src/os/solaris/vm/os_solaris.cpp +++ b/src/os/solaris/vm/os_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -178,75 +178,6 @@ extern "C" { static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); -// Thread Local Storage -// This is common to all Solaris platforms so it is defined here, -// in this common file. -// The declarations are in the os_cpu threadLS*.hpp files. -// -// Static member initialization for TLS -Thread* ThreadLocalStorage::_get_thread_cache[ThreadLocalStorage::_pd_cache_size] = {NULL}; - -#ifndef PRODUCT -#define _PCT(n,d) ((100.0*(double)(n))/(double)(d)) - -int ThreadLocalStorage::_tcacheHit = 0; -int ThreadLocalStorage::_tcacheMiss = 0; - -void ThreadLocalStorage::print_statistics() { - int total = _tcacheMiss+_tcacheHit; - tty->print_cr("Thread cache hits %d misses %d total %d percent %f\n", - _tcacheHit, _tcacheMiss, total, _PCT(_tcacheHit, total)); -} -#undef _PCT -#endif // PRODUCT - -Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id, - int index) { - Thread *thread = get_thread_slow(); - if (thread != NULL) { - address sp = os::current_stack_pointer(); - guarantee(thread->_stack_base == NULL || - (sp <= thread->_stack_base && - sp >= thread->_stack_base - thread->_stack_size) || - is_error_reported(), - "sp must be inside of selected thread stack"); - - thread->set_self_raw_id(raw_id); // mark for quick retrieval - _get_thread_cache[ index ] = thread; - } - return thread; -} - - -static const double all_zero[ sizeof(Thread) / sizeof(double) + 1 ] = {0}; -#define NO_CACHED_THREAD ((Thread*)all_zero) - -void ThreadLocalStorage::pd_set_thread(Thread* thread) { - - // Store the new value before updating the cache to prevent a race - // between get_thread_via_cache_slowly() and this store operation. - os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); - - // Update thread cache with new thread if setting on thread create, - // or NO_CACHED_THREAD (zeroed) thread if resetting thread on exit. - uintptr_t raw = pd_raw_thread_id(); - int ix = pd_cache_index(raw); - _get_thread_cache[ix] = thread == NULL ? NO_CACHED_THREAD : thread; -} - -void ThreadLocalStorage::pd_init() { - for (int i = 0; i < _pd_cache_size; i++) { - _get_thread_cache[i] = NO_CACHED_THREAD; - } -} - -// Invalidate all the caches (happens to be the same as pd_init). -void ThreadLocalStorage::pd_invalidate_all() { pd_init(); } - -#undef NO_CACHED_THREAD - -// END Thread Local Storage - static inline size_t adjust_stack_size(address base, size_t size) { if ((ssize_t)size < 0) { // 4759953: Compensate for ridiculous stack size. @@ -1473,64 +1404,6 @@ int os::current_process_id() { return (int)(_initial_pid ? _initial_pid : getpid()); } -int os::allocate_thread_local_storage() { - // %%% in Win32 this allocates a memory segment pointed to by a - // register. Dan Stein can implement a similar feature in - // Solaris. Alternatively, the VM can do the same thing - // explicitly: malloc some storage and keep the pointer in a - // register (which is part of the thread's context) (or keep it - // in TLS). - // %%% In current versions of Solaris, thr_self and TSD can - // be accessed via short sequences of displaced indirections. - // The value of thr_self is available as %g7(36). - // The value of thr_getspecific(k) is stored in %g7(12)(4)(k*4-4), - // assuming that the current thread already has a value bound to k. - // It may be worth experimenting with such access patterns, - // and later having the parameters formally exported from a Solaris - // interface. I think, however, that it will be faster to - // maintain the invariant that %g2 always contains the - // JavaThread in Java code, and have stubs simply - // treat %g2 as a caller-save register, preserving it in a %lN. - thread_key_t tk; - if (thr_keycreate( &tk, NULL ) ) - fatal(err_msg("os::allocate_thread_local_storage: thr_keycreate failed " - "(%s)", strerror(errno))); - return int(tk); -} - -void os::free_thread_local_storage(int index) { - // %%% don't think we need anything here - // if ( pthread_key_delete((pthread_key_t) tk) ) - // fatal("os::free_thread_local_storage: pthread_key_delete failed"); -} - -#define SMALLINT 32 // libthread allocate for tsd_common is a version specific - // small number - point is NO swap space available -void os::thread_local_storage_at_put(int index, void* value) { - // %%% this is used only in threadLocalStorage.cpp - if (thr_setspecific((thread_key_t)index, value)) { - if (errno == ENOMEM) { - vm_exit_out_of_memory(SMALLINT, OOM_MALLOC_ERROR, - "thr_setspecific: out of swap space"); - } else { - fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed " - "(%s)", strerror(errno))); - } - } else { - ThreadLocalStorage::set_thread_in_slot ((Thread *) value) ; - } -} - -// This function could be called before TLS is initialized, for example, when -// VM receives an async signal or when VM causes a fatal error during -// initialization. Return NULL if thr_getspecific() fails. -void* os::thread_local_storage_at(int index) { - // %%% this is used only in threadLocalStorage.cpp - void* r = NULL; - return thr_getspecific((thread_key_t)index, &r) != 0 ? NULL : r; -} - - // gethrtime() should be monotonic according to the documentation, // but some virtualized platforms are known to break this guarantee. // getTimeNanos() must be guaranteed not to move backwards, so we @@ -2168,7 +2041,9 @@ void os::print_memory_info(outputStream* st) { st->print(", physical " UINT64_FORMAT "k", os::physical_memory()>>10); st->print("(" UINT64_FORMAT "k free)", os::available_memory() >> 10); st->cr(); - (void) check_addr0(st); + if (VMError::fatal_error_in_progress()) { + (void) check_addr0(st); + } } void os::print_siginfo(outputStream* st, void* siginfo) { @@ -2696,29 +2571,30 @@ void os::pd_commit_memory_or_exit(char* addr, size_t bytes, bool exec, } } +size_t os::Solaris::page_size_for_alignment(size_t alignment) { + assert(is_size_aligned(alignment, (size_t) vm_page_size()), + err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, + alignment, (size_t) vm_page_size())); + + for (int i = 0; _page_sizes[i] != 0; i++) { + if (is_size_aligned(alignment, _page_sizes[i])) { + return _page_sizes[i]; + } + } + + return (size_t) vm_page_size(); +} + int os::Solaris::commit_memory_impl(char* addr, size_t bytes, size_t alignment_hint, bool exec) { int err = Solaris::commit_memory_impl(addr, bytes, exec); - if (err == 0) { - if (UseLargePages && (alignment_hint > (size_t)vm_page_size())) { - // If the large page size has been set and the VM - // is using large pages, use the large page size - // if it is smaller than the alignment hint. This is - // a case where the VM wants to use a larger alignment size - // for its own reasons but still want to use large pages - // (which is what matters to setting the mpss range. - size_t page_size = 0; - if (large_page_size() < alignment_hint) { - assert(UseLargePages, "Expected to be here for large page use only"); - page_size = large_page_size(); - } else { - // If the alignment hint is less than the large page - // size, the VM wants a particular alignment (thus the hint) - // for internal reasons. Try to set the mpss range using - // the alignment_hint. - page_size = alignment_hint; - } - // Since this is a hint, ignore any failures. + if (err == 0 && UseLargePages && alignment_hint > 0) { + assert(is_size_aligned(bytes, alignment_hint), + err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, alignment_hint)); + + // The syscall memcntl requires an exact page size (see man memcntl for details). + size_t page_size = page_size_for_alignment(alignment_hint); + if (page_size > (size_t) vm_page_size()) { (void)Solaris::setup_large_pages(addr, bytes, page_size); } } @@ -3251,7 +3127,22 @@ void os::large_page_init() { } } +bool os::Solaris::is_valid_page_size(size_t bytes) { + for (int i = 0; _page_sizes[i] != 0; i++) { + if (_page_sizes[i] == bytes) { + return true; + } + } + return false; +} + bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) { + assert(is_valid_page_size(align), err_msg(SIZE_FORMAT " is not a valid page size", align)); + assert(is_ptr_aligned((void*) start, align), + err_msg(PTR_FORMAT " is not aligned to " SIZE_FORMAT, p2i((void*) start), align)); + assert(is_size_aligned(bytes, align), + err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, align)); + // Signal to OS that we want large pages for addresses // from addr, addr + bytes struct memcntl_mha mpss_struct; @@ -4577,6 +4468,11 @@ void os::Solaris::check_signal_handler(int sig) { tty->print_cr(" found:%s", get_signal_handler_name(thisHandler, buf, O_BUFLEN)); // No need to check this sig any longer sigaddset(&check_signal_done, sig); + // Running under non-interactive shell, SHUTDOWN2_SIGNAL will be reassigned SIG_IGN + if (sig == SHUTDOWN2_SIGNAL && !isatty(fileno(stdin))) { + tty->print_cr("Running in non-interactive shell, %s handler is replaced by shell", + exception_name(sig, buf, O_BUFLEN)); + } } else if(os::Solaris::get_our_sigflags(sig) != 0 && act.sa_flags != os::Solaris::get_our_sigflags(sig)) { tty->print("Warning: %s handler flags ", exception_name(sig, buf, O_BUFLEN)); tty->print("expected:" PTR32_FORMAT, os::Solaris::get_our_sigflags(sig)); @@ -5194,10 +5090,6 @@ jint os::init_2(void) { return JNI_OK; } -void os::init_3(void) { - return; -} - // Mark the polling page as unreadable void os::make_polling_page_unreadable(void) { if( mprotect((char *)_polling_page, page_size, PROT_NONE) != 0 ) diff --git a/src/os/solaris/vm/os_solaris.hpp b/src/os/solaris/vm/os_solaris.hpp index 048534691..a22f0e9fe 100644 --- a/src/os/solaris/vm/os_solaris.hpp +++ b/src/os/solaris/vm/os_solaris.hpp @@ -110,6 +110,8 @@ class Solaris { static meminfo_func_t _meminfo; // Large Page Support + static bool is_valid_page_size(size_t bytes); + static size_t page_size_for_alignment(size_t alignment); static bool setup_large_pages(caddr_t start, size_t bytes, size_t align); static void init_thread_fpu_state(void); diff --git a/src/os/solaris/vm/perfMemory_solaris.cpp b/src/os/solaris/vm/perfMemory_solaris.cpp index 996b6d889..a90623e74 100644 --- a/src/os/solaris/vm/perfMemory_solaris.cpp +++ b/src/os/solaris/vm/perfMemory_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, 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 @@ -219,9 +219,9 @@ static bool is_statbuf_secure(struct stat *statp) { // return false; } - // See if the uid of the directory matches the effective uid of the process. - // - if (statp->st_uid != geteuid()) { + // If user is not root then see if the uid of the directory matches the effective uid of the process. + uid_t euid = geteuid(); + if ((euid != 0) && (statp->st_uid != euid)) { // The directory was not created by this user, declare it insecure. // return false; @@ -377,10 +377,23 @@ static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { *saved_cwd_fd = result; } - // Set the current directory to dirname by using the fd of the directory. + // Set the current directory to dirname by using the fd of the directory and + // handle errors, otherwise shared memory files will be created in cwd. result = fchdir(fd); - - return dirp; + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not change to directory %s", dirname); + } + if (*saved_cwd_fd != -1) { + ::close(*saved_cwd_fd); + *saved_cwd_fd = -1; + } + // Close the directory. + os::closedir(dirp); + return NULL; + } else { + return dirp; + } } // Close the directory and restore the current working directory. diff --git a/src/os/solaris/vm/thread_solaris.inline.hpp b/src/os/solaris/vm/thread_solaris.inline.hpp index d7d6d378f..48c85aaf7 100644 --- a/src/os/solaris/vm/thread_solaris.inline.hpp +++ b/src/os/solaris/vm/thread_solaris.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -40,19 +40,12 @@ // For SPARC, to avoid excessive register window spill-fill faults, // we aggressively inline these routines. -inline Thread* ThreadLocalStorage::thread() { - // don't use specialized code if +UseMallocOnly -- may confuse Purify et al. - debug_only(if (UseMallocOnly) return get_thread_slow();); +inline void ThreadLocalStorage::set_thread(Thread* thread) { + _thr_current = thread; +} - uintptr_t raw = pd_raw_thread_id(); - int ix = pd_cache_index(raw); - Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix]; - if (candidate->self_raw_id() == raw) { - // hit - return candidate; - } else { - return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix); - } +inline Thread* ThreadLocalStorage::thread() { + return _thr_current; } #endif // OS_SOLARIS_VM_THREAD_SOLARIS_INLINE_HPP diff --git a/src/os/windows/vm/os_windows.cpp b/src/os/windows/vm/os_windows.cpp index c2839a187..e329c9fd6 100644 --- a/src/os/windows/vm/os_windows.cpp +++ b/src/os/windows/vm/os_windows.cpp @@ -110,11 +110,13 @@ static FILETIME process_user_time; static FILETIME process_kernel_time; #ifdef _M_IA64 -#define __CPU__ ia64 -#elif _M_AMD64 -#define __CPU__ amd64 + #define __CPU__ ia64 #else -#define __CPU__ i486 + #ifdef _M_AMD64 + #define __CPU__ amd64 + #else + #define __CPU__ i486 + #endif #endif // save DLL module handle, used by GetModuleFileName @@ -2138,20 +2140,22 @@ LONG Handle_Exception(struct _EXCEPTION_POINTERS* exceptionInfo, address handler // at the beginning of the target bundle. exceptionInfo->ContextRecord->StIPSR &= 0xFFFFF9FFFFFFFFFF; assert(((DWORD64)handler & 0xF) == 0, "Target address must point to the beginning of a bundle!"); -#elif _M_AMD64 +#else + #ifdef _M_AMD64 // Do not blow up if no thread info available. if (thread) { thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Rip); } // Set pc to handler exceptionInfo->ContextRecord->Rip = (DWORD64)handler; -#else + #else // Do not blow up if no thread info available. if (thread) { thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Eip); } // Set pc to handler exceptionInfo->ContextRecord->Eip = (DWORD)(DWORD_PTR)handler; + #endif #endif // Continue the execution @@ -2250,7 +2254,8 @@ LONG Handle_IDiv_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) { // (division by zero is handled explicitly) #ifdef _M_IA64 assert(0, "Fix Handle_IDiv_Exception"); -#elif _M_AMD64 +#else + #ifdef _M_AMD64 PCONTEXT ctx = exceptionInfo->ContextRecord; address pc = (address)ctx->Rip; assert(pc[0] == 0xF7, "not an idiv opcode"); @@ -2261,7 +2266,7 @@ LONG Handle_IDiv_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) { ctx->Rax = (DWORD)min_jint; // result ctx->Rdx = (DWORD)0; // remainder // Continue the execution -#else + #else PCONTEXT ctx = exceptionInfo->ContextRecord; address pc = (address)ctx->Eip; assert(pc[0] == 0xF7, "not an idiv opcode"); @@ -2272,6 +2277,7 @@ LONG Handle_IDiv_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) { ctx->Eax = (DWORD)min_jint; // result ctx->Edx = (DWORD)0; // remainder // Continue the execution + #endif #endif return EXCEPTION_CONTINUE_EXECUTION; } @@ -2351,10 +2357,12 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { // This is needed for IA64 because "relocation" / "implicit null check" / "poll instruction" // information is saved in the Unix format. address pc_unix_format = (address) ((((uint64_t)pc) & 0xFFFFFFFFFFFFFFF0) | ((((uint64_t)pc) & 0xF) >> 2)); -#elif _M_AMD64 - address pc = (address) exceptionInfo->ContextRecord->Rip; #else + #ifdef _M_AMD64 + address pc = (address) exceptionInfo->ContextRecord->Rip; + #else address pc = (address) exceptionInfo->ContextRecord->Eip; + #endif #endif Thread* t = ThreadLocalStorage::get_thread_slow(); // slow & steady @@ -4062,10 +4070,6 @@ jint os::init_2(void) { return JNI_OK; } -void os::init_3(void) { - return; -} - // Mark the polling page as unreadable void os::make_polling_page_unreadable(void) { DWORD old_status; |