Mercurial > hg > graal-jvmci-8
diff src/os/solaris/vm/os_solaris.cpp @ 2023:54f5dd2aa1d9
Merge
author | zgu |
---|---|
date | Sat, 11 Dec 2010 13:46:36 -0500 |
parents | 2d4762ec74af 828eafbd85cc |
children | 1e637defdda6 |
line wrap: on
line diff
--- a/src/os/solaris/vm/os_solaris.cpp Sat Dec 11 13:20:56 2010 -0500 +++ b/src/os/solaris/vm/os_solaris.cpp Sat Dec 11 13:46:36 2010 -0500 @@ -42,7 +42,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -116,6 +115,7 @@ # include <sys/iapriocntl.h> # include <sys/loadavg.h> # include <string.h> +# include <stdio.h> # define _STRUCTURED_PROC 1 // this gets us the new structured proc interfaces of 5.6 & later # include <sys/procfs.h> // see comment in <sys/procfs.h> @@ -220,6 +220,9 @@ // System parameters used internally static clock_t clock_tics_per_sec = 100; +// Track if we have called enable_extended_FILE_stdio (on Solaris 10u4+) +static bool enabled_extended_FILE_stdio = false; + // For diagnostics to print a message once. see run_periodic_checks static bool check_addr0_done = false; static sigset_t check_signal_done; @@ -387,7 +390,7 @@ // The saved state is used to restore the thread to // its former state whether or not an interrupt is received. // Used by classloader os::read -// hpi calls skip this layer and stay in _thread_in_native +// os::restartable_read calls skip this layer and stay in _thread_in_native void os::Solaris::setup_interruptible(JavaThread* thread) { @@ -1751,13 +1754,13 @@ bool os::supports_vtime() { return true; } bool os::enable_vtime() { - int fd = open("/proc/self/ctl", O_WRONLY); + int fd = ::open("/proc/self/ctl", O_WRONLY); if (fd == -1) return false; long cmd[] = { PCSET, PR_MSACCT }; - int res = write(fd, cmd, sizeof(long) * 2); - close(fd); + int res = ::write(fd, cmd, sizeof(long) * 2); + ::close(fd); if (res != sizeof(long) * 2) return false; @@ -1765,13 +1768,13 @@ } bool os::vtime_enabled() { - int fd = open("/proc/self/status", O_RDONLY); + int fd = ::open("/proc/self/status", O_RDONLY); if (fd == -1) return false; pstatus_t status; - int res = read(fd, (void*) &status, sizeof(pstatus_t)); - close(fd); + int res = os::read(fd, (void*) &status, sizeof(pstatus_t)); + ::close(fd); if (res != sizeof(pstatus_t)) return false; @@ -1887,7 +1890,6 @@ void os::dll_build_name(char* buffer, size_t buflen, const char* pname, const char* fname) { - // Copied from libhpi const size_t pnamelen = pname ? strlen(pname) : 0; // Quietly truncate on buffer overflow. Should be an error. @@ -2198,20 +2200,29 @@ return dlsym(handle, name); } - -bool _print_ascii_file(const char* filename, outputStream* st) { - int fd = open(filename, O_RDONLY); +int os::stat(const char *path, struct stat *sbuf) { + char pathbuf[MAX_PATH]; + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + os::native_path(strcpy(pathbuf, path)); + return ::stat(pathbuf, sbuf); +} + +static bool _print_ascii_file(const char* filename, outputStream* st) { + int fd = ::open(filename, O_RDONLY); if (fd == -1) { return false; } char buf[32]; int bytes; - while ((bytes = read(fd, buf, sizeof(buf))) > 0) { + while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) { st->print_raw(buf, bytes); } - close(fd); + ::close(fd); return true; } @@ -2274,10 +2285,10 @@ static bool check_addr0(outputStream* st) { jboolean status = false; - int fd = open("/proc/self/map",O_RDONLY); + int fd = ::open("/proc/self/map",O_RDONLY); if (fd >= 0) { prmap_t p; - while(read(fd, &p, sizeof(p)) > 0) { + while(::read(fd, &p, sizeof(p)) > 0) { if (p.pr_vaddr == 0x0) { st->print("Warning: Address: 0x%x, Size: %dK, ",p.pr_vaddr, p.pr_size/1024, p.pr_mapname); st->print("Mapped file: %s, ", p.pr_mapname[0] == '\0' ? "None" : p.pr_mapname); @@ -2288,7 +2299,7 @@ st->cr(); status = true; } - close(fd); + ::close(fd); } } return status; @@ -2536,8 +2547,6 @@ // Use current module name "libjvm[_g].so" instead of // "libjvm"debug_only("_g")".so" since for fastdebug version // we should have "libjvm.so" but debug_only("_g") adds "_g"! - // It is used when we are choosing the HPI library's name - // "libhpi[_g].so" in hpi::initialize_get_interface(). len = strlen(buf); snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p); } else { @@ -2561,6 +2570,23 @@ // no suffix required } +// 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; +} + // sun.misc.Signal @@ -3470,6 +3496,10 @@ INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); } +size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { + INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); +} + int os::sleep(Thread* thread, jlong millis, bool interruptible) { assert(thread == Thread::current(), "thread consistency check"); @@ -4639,16 +4669,16 @@ #define ADR(x) ((uintptr_t)(x)) #define LWPINDEX(ary,ix) ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1)))) - lwpFile = open("/proc/self/lstatus", O_RDONLY, 0); + lwpFile = ::open("/proc/self/lstatus", O_RDONLY, 0); if (lwpFile < 0) { if (ThreadPriorityVerbose) warning ("Couldn't open /proc/self/lstatus\n"); return false; } lwpSize = 16*1024; for (;;) { - lseek (lwpFile, 0, SEEK_SET); + ::lseek64 (lwpFile, 0, SEEK_SET); lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize); - if (read(lwpFile, lwpArray, lwpSize) < 0) { + if (::read(lwpFile, lwpArray, lwpSize) < 0) { if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n"); break; } @@ -4669,7 +4699,7 @@ } FREE_C_HEAP_ARRAY(char, lwpArray); - close (lwpFile); + ::close (lwpFile); if (ThreadPriorityVerbose) { if (isT2) tty->print_cr("We are running with a T2 libthread\n"); else tty->print_cr("We are not running with a T2 libthread\n"); @@ -4865,7 +4895,7 @@ // if we need them. Solaris::misc_sym_init(); - int fd = open("/dev/zero", O_RDWR); + int fd = ::open("/dev/zero", O_RDWR); if (fd < 0) { fatal(err_msg("os::init: cannot open /dev/zero (%s)", strerror(errno))); } else { @@ -5035,13 +5065,6 @@ } } - // Initialize HPI. - jint hpi_result = hpi::initialize(); - if (hpi_result != JNI_OK) { - tty->print_cr("There was an error trying to initialize the HPI library."); - return hpi_result; - } - // Calculate theoretical max. size of Threads to guard gainst // artifical out-of-memory situations, where all available address- // space has been reserved by thread stacks. Default stack size is 1Mb. @@ -5101,17 +5124,6 @@ // OS interface. -int os::stat(const char *path, struct stat *sbuf) { - char pathbuf[MAX_PATH]; - if (strlen(path) > MAX_PATH - 1) { - errno = ENAMETOOLONG; - return -1; - } - hpi::native_path(strcpy(pathbuf, path)); - return ::stat(pathbuf, sbuf); -} - - bool os::check_heap(bool force) { return true; } typedef int (*vsnprintf_t)(char* buf, size_t count, const char* fmt, va_list argptr); @@ -5156,6 +5168,125 @@ return result; } +// This code originates from JDK's sysOpen and open64_w +// from src/solaris/hpi/src/system_md.c + +#ifndef O_DELETE +#define O_DELETE 0x10000 +#endif + +// Open a file. Unlink the file immediately after open returns +// if the specified oflag has the O_DELETE flag set. +// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c + +int os::open(const char *path, int oflag, int mode) { + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + int fd; + int o_delete = (oflag & O_DELETE); + oflag = oflag & ~O_DELETE; + + fd = ::open(path, oflag, mode); + if (fd == -1) return -1; + + //If the open succeeded, the file might still be a directory + { + struct stat64 buf64; + int ret = ::fstat64(fd, &buf64); + int st_mode = buf64.st_mode; + + if (ret != -1) { + if ((st_mode & S_IFMT) == S_IFDIR) { + errno = EISDIR; + ::close(fd); + return -1; + } + } else { + ::close(fd); + return -1; + } + } + /* + * 32-bit Solaris systems suffer from: + * + * - an historical default soft limit of 256 per-process file + * descriptors that is too low for many Java programs. + * + * - a design flaw where file descriptors created using stdio + * fopen must be less than 256, _even_ when the first limit above + * has been raised. This can cause calls to fopen (but not calls to + * open, for example) to fail mysteriously, perhaps in 3rd party + * native code (although the JDK itself uses fopen). One can hardly + * criticize them for using this most standard of all functions. + * + * We attempt to make everything work anyways by: + * + * - raising the soft limit on per-process file descriptors beyond + * 256 + * + * - As of Solaris 10u4, we can request that Solaris raise the 256 + * stdio fopen limit by calling function enable_extended_FILE_stdio. + * This is done in init_2 and recorded in enabled_extended_FILE_stdio + * + * - If we are stuck on an old (pre 10u4) Solaris system, we can + * workaround the bug by remapping non-stdio file descriptors below + * 256 to ones beyond 256, which is done below. + * + * See: + * 1085341: 32-bit stdio routines should support file descriptors >255 + * 6533291: Work around 32-bit Solaris stdio limit of 256 open files + * 6431278: Netbeans crash on 32 bit Solaris: need to call + * enable_extended_FILE_stdio() in VM initialisation + * Giri Mandalika's blog + * http://technopark02.blogspot.com/2005_05_01_archive.html + */ +#ifndef _LP64 + if ((!enabled_extended_FILE_stdio) && fd < 256) { + int newfd = ::fcntl(fd, F_DUPFD, 256); + if (newfd != -1) { + ::close(fd); + fd = newfd; + } + } +#endif // 32-bit Solaris + /* + * All file descriptors that are opened in the JVM and not + * specifically destined for a subprocess should have the + * close-on-exec flag set. If we don't set it, then careless 3rd + * party native code might fork and exec without closing all + * appropriate file descriptors (e.g. as we do in closeDescriptors in + * UNIXProcess.c), and this in turn might: + * + * - cause end-of-file to fail to be detected on some file + * descriptors, resulting in mysterious hangs, or + * + * - might cause an fopen in the subprocess to fail on a system + * suffering from bug 1085341. + * + * (Yes, the default setting of the close-on-exec flag is a Unix + * design flaw) + * + * See: + * 1085341: 32-bit stdio routines should support file descriptors >255 + * 4843136: (process) pipe file descriptor from Runtime.exec not being closed + * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 + */ +#ifdef FD_CLOEXEC + { + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1) + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } +#endif + + if (o_delete != 0) { + ::unlink(path); + } + return fd; +} + // create binary file, rewriting existing file if required int os::create_binary_file(const char* path, bool rewrite_existing) { int oflags = O_WRONLY | O_CREAT; @@ -5175,6 +5306,55 @@ return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET); } +jlong os::lseek(int fd, jlong offset, int whence) { + return (jlong) ::lseek64(fd, offset, whence); +} + +char * os::native_path(char *path) { + return path; +} + +int os::ftruncate(int fd, jlong length) { + return ::ftruncate64(fd, length); +} + +int os::fsync(int fd) { + RESTARTABLE_RETURN_INT(::fsync(fd)); +} + +int os::available(int fd, jlong *bytes) { + jlong cur, end; + int mode; + struct stat64 buf64; + + if (::fstat64(fd, &buf64) >= 0) { + mode = buf64.st_mode; + if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { + /* + * XXX: is the following call interruptible? If so, this might + * need to go through the INTERRUPT_IO() wrapper as for other + * blocking, interruptible calls in this file. + */ + int n,ioctl_return; + + INTERRUPTIBLE(::ioctl(fd, FIONREAD, &n),ioctl_return,os::Solaris::clear_interrupted); + if (ioctl_return>= 0) { + *bytes = n; + return 1; + } + } + } + if ((cur = ::lseek64(fd, 0L, SEEK_CUR)) == -1) { + return 0; + } else if ((end = ::lseek64(fd, 0L, SEEK_END)) == -1) { + return 0; + } else if (::lseek64(fd, cur, SEEK_SET) == -1) { + return 0; + } + *bytes = end - cur; + return 1; +} + // Map a block of memory. char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, @@ -5233,7 +5413,7 @@ int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd != -1) { struct stat buf; - close(fd); + ::close(fd); while (::stat(filename, &buf) == 0) { (void)::poll(NULL, 0, 100); } @@ -5430,16 +5610,16 @@ sprintf(proc_name, "/proc/%d/lwp/%d/lwpusage", getpid(), thread->osthread()->lwp_id()); - fd = open(proc_name, O_RDONLY); + fd = ::open(proc_name, O_RDONLY); if ( fd == -1 ) return -1; do { - count = pread(fd, + count = ::pread(fd, (void *)&prusage.pr_utime, thr_time_size, thr_time_off); } while (count < 0 && errno == EINTR); - close(fd); + ::close(fd); if ( count < 0 ) return -1; if (user_sys_cpu_time) { @@ -6111,4 +6291,127 @@ return true; } - +size_t os::write(int fd, const void *buf, unsigned int nBytes) { + INTERRUPTIBLE_RETURN_INT(::write(fd, buf, nBytes), os::Solaris::clear_interrupted); +} + +int os::close(int fd) { + RESTARTABLE_RETURN_INT(::close(fd)); +} + +int os::socket_close(int fd) { + RESTARTABLE_RETURN_INT(::close(fd)); +} + +int os::recv(int fd, char *buf, int nBytes, int flags) { + INTERRUPTIBLE_RETURN_INT(::recv(fd, buf, nBytes, flags), os::Solaris::clear_interrupted); +} + + +int os::send(int fd, char *buf, int nBytes, int flags) { + INTERRUPTIBLE_RETURN_INT(::send(fd, buf, nBytes, flags), os::Solaris::clear_interrupted); +} + +int os::raw_send(int fd, char *buf, int nBytes, int flags) { + RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, flags)); +} + +// As both poll and select can be interrupted by signals, we have to be +// prepared to restart the system call after updating the timeout, unless +// a poll() is done with timeout == -1, in which case we repeat with this +// "wait forever" value. + +int os::timeout(int fd, long timeout) { + int res; + struct timeval t; + julong prevtime, newtime; + static const char* aNull = 0; + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLIN; + + gettimeofday(&t, &aNull); + prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; + + for(;;) { + INTERRUPTIBLE_NORESTART(::poll(&pfd, 1, timeout), res, os::Solaris::clear_interrupted); + if(res == OS_ERR && errno == EINTR) { + if(timeout != -1) { + gettimeofday(&t, &aNull); + newtime = ((julong)t.tv_sec * 1000) + t.tv_usec /1000; + timeout -= newtime - prevtime; + if(timeout <= 0) + return OS_OK; + prevtime = newtime; + } + } else return res; + } +} + +int os::connect(int fd, struct sockaddr *him, int len) { + int _result; + INTERRUPTIBLE_NORESTART(::connect(fd, him, len), _result, + os::Solaris::clear_interrupted); + + // Depending on when thread interruption is reset, _result could be + // one of two values when errno == EINTR + + if (((_result == OS_INTRPT) || (_result == OS_ERR)) + && (errno == EINTR)) { + /* restarting a connect() changes its errno semantics */ + INTERRUPTIBLE(::connect(fd, him, len), _result, + os::Solaris::clear_interrupted); + /* undo these changes */ + if (_result == OS_ERR) { + if (errno == EALREADY) { + errno = EINPROGRESS; /* fall through */ + } else if (errno == EISCONN) { + errno = 0; + return OS_OK; + } + } + } + return _result; + } + +int os::accept(int fd, struct sockaddr *him, int *len) { + if (fd < 0) + return OS_ERR; + INTERRUPTIBLE_RETURN_INT((int)::accept(fd, him,\ + (socklen_t*) len), os::Solaris::clear_interrupted); + } + +int os::recvfrom(int fd, char *buf, int nBytes, int flags, + sockaddr *from, int *fromlen) { + //%%note jvm_r11 + INTERRUPTIBLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes,\ + flags, from, fromlen), os::Solaris::clear_interrupted); +} + +int os::sendto(int fd, char *buf, int len, int flags, + struct sockaddr *to, int tolen) { + //%%note jvm_r11 + INTERRUPTIBLE_RETURN_INT((int)::sendto(fd, buf, len, flags,\ + to, tolen), os::Solaris::clear_interrupted); +} + +int os::socket_available(int fd, jint *pbytes) { + if (fd < 0) + return OS_OK; + + int ret; + + RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret); + + //%% note ioctl can return 0 when successful, JVM_SocketAvailable + // is expected to return 0 on failure and 1 on success to the jdk. + + return (ret == OS_ERR) ? 0 : 1; +} + + +int os::bind(int fd, struct sockaddr *him, int len) { + INTERRUPTIBLE_RETURN_INT_NORESTART(::bind(fd, him, len),\ + os::Solaris::clear_interrupted); +} +