hotspot/src/os/solaris/vm/os_solaris.cpp
changeset 18702 e6fa43c6d215
parent 18086 f44cf213a775
child 18703 2a39dd8382ab
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Tue Jul 09 22:00:04 2013 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 10 13:33:56 2013 -0700
@@ -115,45 +115,6 @@
 // for timer info max values which include all bits
 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
 
-#ifdef _GNU_SOURCE
-// See bug #6514594
-extern "C" int madvise(caddr_t, size_t, int);
-extern "C" int memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg,
-                       int attr, int mask);
-#endif //_GNU_SOURCE
-
-/*
-  MPSS Changes Start.
-  The JVM binary needs to be built and run on pre-Solaris 9
-  systems, but the constants needed by MPSS are only in Solaris 9
-  header files.  They are textually replicated here to allow
-  building on earlier systems.  Once building on Solaris 8 is
-  no longer a requirement, these #defines can be replaced by ordinary
-  system .h inclusion.
-
-  In earlier versions of the  JDK and Solaris, we used ISM for large pages.
-  But ISM requires shared memory to achieve this and thus has many caveats.
-  MPSS is a fully transparent and is a cleaner way to get large pages.
-  Although we still require keeping ISM for backward compatiblitiy as well as
-  giving the opportunity to use large pages on older systems it is
-  recommended that MPSS be used for Solaris 9 and above.
-
-*/
-
-#ifndef MC_HAT_ADVISE
-
-struct memcntl_mha {
-  uint_t          mha_cmd;        /* command(s) */
-  uint_t          mha_flags;
-  size_t          mha_pagesize;
-};
-#define MC_HAT_ADVISE   7       /* advise hat map size */
-#define MHA_MAPSIZE_VA  0x1     /* set preferred page size */
-#define MAP_ALIGN       0x200   /* addr specifies alignment */
-
-#endif
-// MPSS Changes End.
-
 
 // Here are some liblgrp types from sys/lgrp_user.h to be able to
 // compile on older systems without this header file.
@@ -172,32 +133,6 @@
 # define LGRP_RSRC_MEM           1       /* memory resources */
 #endif
 
-// Some more macros from sys/mman.h that are not present in Solaris 8.
-
-#ifndef MAX_MEMINFO_CNT
-/*
- * info_req request type definitions for meminfo
- * request types starting with MEMINFO_V are used for Virtual addresses
- * and should not be mixed with MEMINFO_PLGRP which is targeted for Physical
- * addresses
- */
-# define MEMINFO_SHIFT           16
-# define MEMINFO_MASK            (0xFF << MEMINFO_SHIFT)
-# define MEMINFO_VPHYSICAL       (0x01 << MEMINFO_SHIFT) /* get physical addr */
-# define MEMINFO_VLGRP           (0x02 << MEMINFO_SHIFT) /* get lgroup */
-# define MEMINFO_VPAGESIZE       (0x03 << MEMINFO_SHIFT) /* size of phys page */
-# define MEMINFO_VREPLCNT        (0x04 << MEMINFO_SHIFT) /* no. of replica */
-# define MEMINFO_VREPL           (0x05 << MEMINFO_SHIFT) /* physical replica */
-# define MEMINFO_VREPL_LGRP      (0x06 << MEMINFO_SHIFT) /* lgrp of replica */
-# define MEMINFO_PLGRP           (0x07 << MEMINFO_SHIFT) /* lgroup for paddr */
-
-/* maximum number of addresses meminfo() can process at a time */
-# define MAX_MEMINFO_CNT 256
-
-/* maximum number of request types */
-# define MAX_MEMINFO_REQ 31
-#endif
-
 // see thr_setprio(3T) for the basis of these numbers
 #define MinimumPriority 0
 #define NormalPriority  64
@@ -2859,7 +2794,7 @@
                                     size_t alignment_hint, bool exec) {
   int err = Solaris::commit_memory_impl(addr, bytes, exec);
   if (err == 0) {
-    if (UseMPSS && alignment_hint > (size_t)vm_page_size()) {
+    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
@@ -2878,7 +2813,7 @@
         page_size = alignment_hint;
       }
       // Since this is a hint, ignore any failures.
-      (void)Solaris::set_mpss_range(addr, bytes, page_size);
+      (void)Solaris::setup_large_pages(addr, bytes, page_size);
     }
   }
   return err;
@@ -2921,8 +2856,8 @@
 void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
   assert((intptr_t)addr % alignment_hint == 0, "Address should be aligned.");
   assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned.");
-  if (UseLargePages && UseMPSS) {
-    Solaris::set_mpss_range(addr, bytes, alignment_hint);
+  if (UseLargePages) {
+    Solaris::setup_large_pages(addr, bytes, alignment_hint);
   }
 }
 
@@ -3321,47 +3256,8 @@
 }
 
 // Large page support
-
-// UseLargePages is the master flag to enable/disable large page memory.
-// UseMPSS and UseISM are supported for compatibility reasons. Their combined
-// effects can be described in the following table:
-//
-// UseLargePages UseMPSS UseISM
-//    false         *       *   => UseLargePages is the master switch, turning
-//                                 it off will turn off both UseMPSS and
-//                                 UseISM. VM will not use large page memory
-//                                 regardless the settings of UseMPSS/UseISM.
-//     true      false    false => Unless future Solaris provides other
-//                                 mechanism to use large page memory, this
-//                                 combination is equivalent to -UseLargePages,
-//                                 VM will not use large page memory
-//     true      true     false => JVM will use MPSS for large page memory.
-//                                 This is the default behavior.
-//     true      false    true  => JVM will use ISM for large page memory.
-//     true      true     true  => JVM will use ISM if it is available.
-//                                 Otherwise, JVM will fall back to MPSS.
-//                                 Becaues ISM is now available on all
-//                                 supported Solaris versions, this combination
-//                                 is equivalent to +UseISM -UseMPSS.
-
 static size_t _large_page_size = 0;
 
-bool os::Solaris::ism_sanity_check(bool warn, size_t * page_size) {
-  // x86 uses either 2M or 4M page, depending on whether PAE (Physical Address
-  // Extensions) mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. Sparc
-  // can support multiple page sizes.
-
-  // Don't bother to probe page size because getpagesizes() comes with MPSS.
-  // ISM is only recommended on old Solaris where there is no MPSS support.
-  // Simply choose a conservative value as default.
-  *page_size = LargePageSizeInBytes ? LargePageSizeInBytes :
-               SPARC_ONLY(4 * M) IA32_ONLY(4 * M) AMD64_ONLY(2 * M)
-               ARM_ONLY(2 * M);
-
-  // ISM is available on all supported Solaris versions
-  return true;
-}
-
 // Insertion sort for small arrays (descending order).
 static void insertion_sort_descending(size_t* array, int len) {
   for (int i = 0; i < len; i++) {
@@ -3374,7 +3270,7 @@
   }
 }
 
-bool os::Solaris::mpss_sanity_check(bool warn, size_t * page_size) {
+bool os::Solaris::mpss_sanity_check(bool warn, size_t* page_size) {
   const unsigned int usable_count = VM_Version::page_size_count();
   if (usable_count == 1) {
     return false;
@@ -3440,41 +3336,24 @@
 }
 
 void os::large_page_init() {
-  if (!UseLargePages) {
-    UseISM = false;
-    UseMPSS = false;
-    return;
-  }
-
-  // print a warning if any large page related flag is specified on command line
-  bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages)        ||
-                         !FLAG_IS_DEFAULT(UseISM)               ||
-                         !FLAG_IS_DEFAULT(UseMPSS)              ||
-                         !FLAG_IS_DEFAULT(LargePageSizeInBytes);
-  UseISM = UseISM &&
-           Solaris::ism_sanity_check(warn_on_failure, &_large_page_size);
-  if (UseISM) {
-    // ISM disables MPSS to be compatible with old JDK behavior
-    UseMPSS = false;
-    _page_sizes[0] = _large_page_size;
-    _page_sizes[1] = vm_page_size();
-  }
-
-  UseMPSS = UseMPSS &&
-            Solaris::mpss_sanity_check(warn_on_failure, &_large_page_size);
-
-  UseLargePages = UseISM || UseMPSS;
-}
-
-bool os::Solaris::set_mpss_range(caddr_t start, size_t bytes, size_t align) {
+  if (UseLargePages) {
+    // print a warning if any large page related flag is specified on command line
+    bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages)        ||
+                           !FLAG_IS_DEFAULT(LargePageSizeInBytes);
+
+    UseLargePages = Solaris::mpss_sanity_check(warn_on_failure, &_large_page_size);
+  }
+}
+
+bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) {
   // Signal to OS that we want large pages for addresses
   // from addr, addr + bytes
   struct memcntl_mha mpss_struct;
   mpss_struct.mha_cmd = MHA_MAPSIZE_VA;
   mpss_struct.mha_pagesize = align;
   mpss_struct.mha_flags = 0;
-  if (memcntl(start, bytes, MC_HAT_ADVISE,
-              (caddr_t) &mpss_struct, 0, 0) < 0) {
+  // Upon successful completion, memcntl() returns 0
+  if (memcntl(start, bytes, MC_HAT_ADVISE, (caddr_t) &mpss_struct, 0, 0)) {
     debug_only(warning("Attempt to use MPSS failed."));
     return false;
   }
@@ -3482,72 +3361,13 @@
 }
 
 char* os::reserve_memory_special(size_t size, char* addr, bool exec) {
-  // "exec" is passed in but not used.  Creating the shared image for
-  // the code cache doesn't have an SHM_X executable permission to check.
-  assert(UseLargePages && UseISM, "only for ISM large pages");
-
-  char* retAddr = NULL;
-  int shmid;
-  key_t ismKey;
-
-  bool warn_on_failure = UseISM &&
-                        (!FLAG_IS_DEFAULT(UseLargePages)         ||
-                         !FLAG_IS_DEFAULT(UseISM)                ||
-                         !FLAG_IS_DEFAULT(LargePageSizeInBytes)
-                        );
-  char msg[128];
-
-  ismKey = IPC_PRIVATE;
-
-  // Create a large shared memory region to attach to based on size.
-  // Currently, size is the total size of the heap
-  shmid = shmget(ismKey, size, SHM_R | SHM_W | IPC_CREAT);
-  if (shmid == -1){
-     if (warn_on_failure) {
-       jio_snprintf(msg, sizeof(msg), "Failed to reserve shared memory (errno = %d).", errno);
-       warning(msg);
-     }
-     return NULL;
-  }
-
-  // Attach to the region
-  retAddr = (char *) shmat(shmid, 0, SHM_SHARE_MMU | SHM_R | SHM_W);
-  int err = errno;
-
-  // Remove shmid. If shmat() is successful, the actual shared memory segment
-  // will be deleted when it's detached by shmdt() or when the process
-  // terminates. If shmat() is not successful this will remove the shared
-  // segment immediately.
-  shmctl(shmid, IPC_RMID, NULL);
-
-  if (retAddr == (char *) -1) {
-    if (warn_on_failure) {
-      jio_snprintf(msg, sizeof(msg), "Failed to attach shared memory (errno = %d).", err);
-      warning(msg);
-    }
-    return NULL;
-  }
-  if ((retAddr != NULL) && UseNUMAInterleaving) {
-    numa_make_global(retAddr, size);
-  }
-
-  // The memory is committed
-  MemTracker::record_virtual_memory_reserve_and_commit((address)retAddr, size, mtNone, CURRENT_PC);
-
-  return retAddr;
+  fatal("os::reserve_memory_special should not be called on Solaris.");
+  return NULL;
 }
 
 bool os::release_memory_special(char* base, size_t bytes) {
-  MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
-  // detaching the SHM segment will also delete it, see reserve_memory_special()
-  int rslt = shmdt(base);
-  if (rslt == 0) {
-    tkr.record((address)base, bytes);
-    return true;
-  } else {
-    tkr.discard();
-    return false;
-  }
+  fatal("os::release_memory_special should not be called on Solaris.");
+  return false;
 }
 
 size_t os::large_page_size() {
@@ -3557,11 +3377,11 @@
 // MPSS allows application to commit large page memory on demand; with ISM
 // the entire memory region must be allocated as shared memory.
 bool os::can_commit_large_page_memory() {
-  return UseISM ? false : true;
+  return true;
 }
 
 bool os::can_execute_large_page_memory() {
-  return UseISM ? false : true;
+  return true;
 }
 
 static int os_sleep(jlong millis, bool interruptible) {
@@ -3835,28 +3655,6 @@
 static const int criticalPrio = 60; // FX/60 is critical thread class/priority on T4
 static int java_MaxPriority_to_os_priority = 0; // Saved mapping
 
-// Call the version of priocntl suitable for all supported versions
-// of Solaris. We need to call through this wrapper so that we can
-// build on Solaris 9 and run on Solaris 8, 9 and 10.
-//
-// This code should be removed if we ever stop supporting Solaris 8
-// and earlier releases.
-
-static long priocntl_stub(int pcver, idtype_t idtype, id_t id, int cmd, caddr_t arg);
-typedef long (*priocntl_type)(int pcver, idtype_t idtype, id_t id, int cmd, caddr_t arg);
-static priocntl_type priocntl_ptr = priocntl_stub;
-
-// Stub to set the value of the real pointer, and then call the real
-// function.
-
-static long priocntl_stub(int pcver, idtype_t idtype, id_t id, int cmd, caddr_t arg) {
-  // Try Solaris 8- name only.
-  priocntl_type tmp = (priocntl_type)dlsym(RTLD_DEFAULT, "__priocntl");
-  guarantee(tmp != NULL, "priocntl function not found.");
-  priocntl_ptr = tmp;
-  return (*priocntl_ptr)(PC_VERSION, idtype, id, cmd, arg);
-}
-
 
 // lwp_priocntl_init
 //
@@ -3864,9 +3662,7 @@
 //
 // Return errno or 0 if OK.
 //
-static
-int     lwp_priocntl_init ()
-{
+static int lwp_priocntl_init () {
   int rslt;
   pcinfo_t ClassInfo;
   pcparms_t ParmInfo;
@@ -3906,7 +3702,7 @@
 
   strcpy(ClassInfo.pc_clname, "TS");
   ClassInfo.pc_cid = -1;
-  rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
+  rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
   if (rslt < 0) return errno;
   assert(ClassInfo.pc_cid != -1, "cid for TS class is -1");
   tsLimits.schedPolicy = ClassInfo.pc_cid;
@@ -3915,7 +3711,7 @@
 
   strcpy(ClassInfo.pc_clname, "IA");
   ClassInfo.pc_cid = -1;
-  rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
+  rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
   if (rslt < 0) return errno;
   assert(ClassInfo.pc_cid != -1, "cid for IA class is -1");
   iaLimits.schedPolicy = ClassInfo.pc_cid;
@@ -3924,7 +3720,7 @@
 
   strcpy(ClassInfo.pc_clname, "RT");
   ClassInfo.pc_cid = -1;
-  rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
+  rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
   if (rslt < 0) return errno;
   assert(ClassInfo.pc_cid != -1, "cid for RT class is -1");
   rtLimits.schedPolicy = ClassInfo.pc_cid;
@@ -3933,7 +3729,7 @@
 
   strcpy(ClassInfo.pc_clname, "FX");
   ClassInfo.pc_cid = -1;
-  rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
+  rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo);
   if (rslt < 0) return errno;
   assert(ClassInfo.pc_cid != -1, "cid for FX class is -1");
   fxLimits.schedPolicy = ClassInfo.pc_cid;
@@ -3944,7 +3740,7 @@
   // This will normally be IA, TS or, rarely, FX or RT.
   memset(&ParmInfo, 0, sizeof(ParmInfo));
   ParmInfo.pc_cid = PC_CLNULL;
-  rslt = (*priocntl_ptr) (PC_VERSION, P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
+  rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
   if (rslt < 0) return errno;
   myClass = ParmInfo.pc_cid;
 
@@ -3952,7 +3748,7 @@
   // about the class.
   ClassInfo.pc_cid = myClass;
   ClassInfo.pc_clname[0] = 0;
-  rslt = (*priocntl_ptr) (PC_VERSION, (idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo);
+  rslt = priocntl((idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo);
   if (rslt < 0) return errno;
 
   if (ThreadPriorityVerbose) {
@@ -3961,7 +3757,7 @@
 
   memset(&ParmInfo, 0, sizeof(pcparms_t));
   ParmInfo.pc_cid = PC_CLNULL;
-  rslt = (*priocntl_ptr)(PC_VERSION, P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
+  rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo);
   if (rslt < 0) return errno;
 
   if (ParmInfo.pc_cid == rtLimits.schedPolicy) {
@@ -4065,7 +3861,7 @@
 
   memset(&ParmInfo, 0, sizeof(pcparms_t));
   ParmInfo.pc_cid = PC_CLNULL;
-  rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo);
+  rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo);
   if (rslt < 0) return errno;
 
   int cur_class = ParmInfo.pc_cid;
@@ -4133,7 +3929,7 @@
     return EINVAL;    // no clue, punt
   }
 
-  rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo);
+  rslt = priocntl(P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo);
   if (ThreadPriorityVerbose && rslt) {
     tty->print_cr ("PC_SETPARMS ->%d %d\n", rslt, errno);
   }
@@ -4152,7 +3948,7 @@
 
   memset(&ReadBack, 0, sizeof(pcparms_t));
   ReadBack.pc_cid = PC_CLNULL;
-  rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ReadBack);
+  rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ReadBack);
   assert(rslt >= 0, "priocntl failed");
   Actual = Expected = 0xBAD;
   assert(ParmInfo.pc_cid == ReadBack.pc_cid, "cid's don't match");
@@ -5244,11 +5040,6 @@
   return _getisax(array, n);
 }
 
-// Symbol doesn't exist in Solaris 8 pset.h
-#ifndef PS_MYID
-#define PS_MYID -3
-#endif
-
 // int pset_getloadavg(psetid_t pset, double loadavg[], int nelem);
 typedef long (*pset_getloadavg_type)(psetid_t pset, double loadavg[], int nelem);
 static pset_getloadavg_type pset_getloadavg_ptr = NULL;
@@ -5418,20 +5209,6 @@
         UseNUMA = false;
       }
     }
-    // ISM is not compatible with the NUMA allocator - it always allocates
-    // pages round-robin across the lgroups.
-    if (UseNUMA && UseLargePages && UseISM) {
-      if (!FLAG_IS_DEFAULT(UseNUMA)) {
-        if (FLAG_IS_DEFAULT(UseLargePages) && FLAG_IS_DEFAULT(UseISM)) {
-          UseLargePages = false;
-        } else {
-          warning("UseNUMA is not compatible with ISM large pages, disabling NUMA allocator");
-          UseNUMA = false;
-        }
-      } else {
-        UseNUMA = false;
-      }
-    }
     if (!UseNUMA && ForceNUMA) {
       UseNUMA = true;
     }