src/hotspot/os/linux/os_linux.cpp
changeset 49193 c3ec048aad63
parent 49175 6a5decfc5574
child 49195 1d2cb50c1492
--- a/src/hotspot/os/linux/os_linux.cpp	Thu Mar 01 16:51:22 2018 -0500
+++ b/src/hotspot/os/linux/os_linux.cpp	Thu Mar 01 16:35:36 2018 -0500
@@ -3053,10 +3053,12 @@
   return res  != (uintptr_t) MAP_FAILED;
 }
 
-static address get_stack_commited_bottom(address bottom, size_t size) {
-  address nbot = bottom;
-  address ntop = bottom + size;
-
+// If there is no page mapped/committed, top (bottom + size) is returned
+static address get_stack_mapped_bottom(address bottom,
+                                       size_t size,
+                                       bool committed_only /* must have backing pages */) {
+  // address used to test if the page is mapped/committed
+  address test_addr = bottom + size;
   size_t page_sz = os::vm_page_size();
   unsigned pages = size / page_sz;
 
@@ -3068,38 +3070,39 @@
 
   while (imin < imax) {
     imid = (imax + imin) / 2;
-    nbot = ntop - (imid * page_sz);
+    test_addr = bottom + (imid * page_sz);
 
     // Use a trick with mincore to check whether the page is mapped or not.
     // mincore sets vec to 1 if page resides in memory and to 0 if page
     // is swapped output but if page we are asking for is unmapped
     // it returns -1,ENOMEM
-    mincore_return_value = mincore(nbot, page_sz, vec);
-
-    if (mincore_return_value == -1) {
-      // Page is not mapped go up
-      // to find first mapped page
-      if (errno != EAGAIN) {
-        assert(errno == ENOMEM, "Unexpected mincore errno");
-        imax = imid;
+    mincore_return_value = mincore(test_addr, page_sz, vec);
+
+    if (mincore_return_value == -1 || (committed_only && (vec[0] & 0x01) == 0)) {
+      // Page is not mapped/committed go up
+      // to find first mapped/committed page
+      if ((mincore_return_value == -1 && errno != EAGAIN)
+        || (committed_only && (vec[0] & 0x01) == 0)) {
+        assert(mincore_return_value != -1 || errno == ENOMEM, "Unexpected mincore errno");
+
+        imin = imid + 1;
       }
     } else {
-      // Page is mapped go down
-      // to find first not mapped page
-      imin = imid + 1;
+      // mapped/committed, go down
+      imax= imid;
     }
   }
 
-  nbot = nbot + page_sz;
-
-  // Adjust stack bottom one page up if last checked page is not mapped
-  if (mincore_return_value == -1) {
-    nbot = nbot + page_sz;
-  }
-
-  return nbot;
-}
-
+  // Adjust stack bottom one page up if last checked page is not mapped/committed
+  if (mincore_return_value == -1 || (committed_only && (vec[0] & 0x01) == 0)) {
+    assert(mincore_return_value != -1 || (errno != EAGAIN && errno != ENOMEM),
+      "Should not get to here");
+
+    test_addr = test_addr + page_sz;
+  }
+
+  return test_addr;
+}
 
 // Linux uses a growable mapping for the stack, and if the mapping for
 // the stack guard pages is not removed when we detach a thread the
@@ -3137,9 +3140,9 @@
 
     if (mincore((address)stack_extent, os::vm_page_size(), vec) == -1) {
       // Fallback to slow path on all errors, including EAGAIN
-      stack_extent = (uintptr_t) get_stack_commited_bottom(
-                                                           os::Linux::initial_thread_stack_bottom(),
-                                                           (size_t)addr - stack_extent);
+      stack_extent = (uintptr_t) get_stack_mapped_bottom(os::Linux::initial_thread_stack_bottom(),
+                                                         (size_t)addr - stack_extent,
+                                                         false /* committed_only */);
     }
 
     if (stack_extent < (uintptr_t)addr) {
@@ -3166,6 +3169,11 @@
   return os::uncommit_memory(addr, size);
 }
 
+size_t os::committed_stack_size(address bottom, size_t size) {
+  address bot = get_stack_mapped_bottom(bottom, size, true /* committed_only */);
+  return size_t(bottom + size - bot);
+}
+
 // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
 // at 'requested_addr'. If there are existing memory mappings at the same
 // location, however, they will be overwritten. If 'fixed' is false,