hotspot/src/os/solaris/vm/os_solaris.cpp
changeset 7405 e6fc8d3926f8
parent 7397 5b173b4ca846
child 7448 11b630d174d5
child 7704 cc9d3ed42704
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Tue Nov 23 13:22:55 2010 -0800
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Dec 01 18:26:32 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"
@@ -115,6 +114,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>
@@ -219,6 +219,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;
@@ -386,7 +389,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) {
 
@@ -1750,13 +1753,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;
 
@@ -1764,13 +1767,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;
 
@@ -1886,7 +1889,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.
@@ -2182,20 +2184,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;
 }
@@ -2258,10 +2269,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);
@@ -2272,7 +2283,7 @@
         st->cr();
         status = true;
       }
-      close(fd);
+      ::close(fd);
     }
   }
   return status;
@@ -2520,8 +2531,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 {
@@ -2545,6 +2554,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
 
@@ -3454,6 +3480,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");
 
@@ -4623,16 +4653,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;
     }
@@ -4653,7 +4683,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");
@@ -4849,7 +4879,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 {
@@ -5019,13 +5049,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.
@@ -5085,17 +5108,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);
@@ -5140,6 +5152,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;
@@ -5159,6 +5290,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,
@@ -5217,7 +5397,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);
     }
@@ -5414,16 +5594,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) {
@@ -6095,4 +6275,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);
+}
+