src/hotspot/os/linux/os_linux.cpp
changeset 49349 7194eb9e8f19
parent 49326 20ab04608e3f
child 49407 7fa5375fa6fd
equal deleted inserted replaced
49348:fde3feaaa4ed 49349:7194eb9e8f19
  3051   uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
  3051   uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
  3052                                      MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
  3052                                      MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
  3053   return res  != (uintptr_t) MAP_FAILED;
  3053   return res  != (uintptr_t) MAP_FAILED;
  3054 }
  3054 }
  3055 
  3055 
  3056 // If there is no page mapped/committed, top (bottom + size) is returned
  3056 static address get_stack_commited_bottom(address bottom, size_t size) {
  3057 static address get_stack_mapped_bottom(address bottom,
  3057   address nbot = bottom;
  3058                                        size_t size,
  3058   address ntop = bottom + size;
  3059                                        bool committed_only /* must have backing pages */) {
  3059 
  3060   // address used to test if the page is mapped/committed
       
  3061   address test_addr = bottom + size;
       
  3062   size_t page_sz = os::vm_page_size();
  3060   size_t page_sz = os::vm_page_size();
  3063   unsigned pages = size / page_sz;
  3061   unsigned pages = size / page_sz;
  3064 
  3062 
  3065   unsigned char vec[1];
  3063   unsigned char vec[1];
  3066   unsigned imin = 1, imax = pages + 1, imid;
  3064   unsigned imin = 1, imax = pages + 1, imid;
  3068 
  3066 
  3069   assert(imin <= imax, "Unexpected page size");
  3067   assert(imin <= imax, "Unexpected page size");
  3070 
  3068 
  3071   while (imin < imax) {
  3069   while (imin < imax) {
  3072     imid = (imax + imin) / 2;
  3070     imid = (imax + imin) / 2;
  3073     test_addr = bottom + (imid * page_sz);
  3071     nbot = ntop - (imid * page_sz);
  3074 
  3072 
  3075     // Use a trick with mincore to check whether the page is mapped or not.
  3073     // Use a trick with mincore to check whether the page is mapped or not.
  3076     // mincore sets vec to 1 if page resides in memory and to 0 if page
  3074     // mincore sets vec to 1 if page resides in memory and to 0 if page
  3077     // is swapped output but if page we are asking for is unmapped
  3075     // is swapped output but if page we are asking for is unmapped
  3078     // it returns -1,ENOMEM
  3076     // it returns -1,ENOMEM
  3079     mincore_return_value = mincore(test_addr, page_sz, vec);
  3077     mincore_return_value = mincore(nbot, page_sz, vec);
  3080 
  3078 
  3081     if (mincore_return_value == -1 || (committed_only && (vec[0] & 0x01) == 0)) {
  3079     if (mincore_return_value == -1) {
  3082       // Page is not mapped/committed go up
  3080       // Page is not mapped go up
  3083       // to find first mapped/committed page
  3081       // to find first mapped page
  3084       if ((mincore_return_value == -1 && errno != EAGAIN)
  3082       if (errno != EAGAIN) {
  3085         || (committed_only && (vec[0] & 0x01) == 0)) {
  3083         assert(errno == ENOMEM, "Unexpected mincore errno");
  3086         assert(mincore_return_value != -1 || errno == ENOMEM, "Unexpected mincore errno");
  3084         imax = imid;
  3087 
       
  3088         imin = imid + 1;
       
  3089       }
  3085       }
  3090     } else {
  3086     } else {
  3091       // mapped/committed, go down
  3087       // Page is mapped go down
  3092       imax= imid;
  3088       // to find first not mapped page
  3093     }
  3089       imin = imid + 1;
  3094   }
  3090     }
  3095 
  3091   }
  3096   // Adjust stack bottom one page up if last checked page is not mapped/committed
  3092 
  3097   if (mincore_return_value == -1 || (committed_only && (vec[0] & 0x01) == 0)) {
  3093   nbot = nbot + page_sz;
  3098     assert(mincore_return_value != -1 || (errno != EAGAIN && errno != ENOMEM),
  3094 
  3099       "Should not get to here");
  3095   // Adjust stack bottom one page up if last checked page is not mapped
  3100 
  3096   if (mincore_return_value == -1) {
  3101     test_addr = test_addr + page_sz;
  3097     nbot = nbot + page_sz;
  3102   }
  3098   }
  3103 
  3099 
  3104   return test_addr;
  3100   return nbot;
  3105 }
  3101 }
       
  3102 
  3106 
  3103 
  3107 // Linux uses a growable mapping for the stack, and if the mapping for
  3104 // Linux uses a growable mapping for the stack, and if the mapping for
  3108 // the stack guard pages is not removed when we detach a thread the
  3105 // the stack guard pages is not removed when we detach a thread the
  3109 // stack cannot grow beyond the pages where the stack guard was
  3106 // stack cannot grow beyond the pages where the stack guard was
  3110 // mapped.  If at some point later in the process the stack expands to
  3107 // mapped.  If at some point later in the process the stack expands to
  3138     uintptr_t stack_extent = (uintptr_t) os::Linux::initial_thread_stack_bottom();
  3135     uintptr_t stack_extent = (uintptr_t) os::Linux::initial_thread_stack_bottom();
  3139     unsigned char vec[1];
  3136     unsigned char vec[1];
  3140 
  3137 
  3141     if (mincore((address)stack_extent, os::vm_page_size(), vec) == -1) {
  3138     if (mincore((address)stack_extent, os::vm_page_size(), vec) == -1) {
  3142       // Fallback to slow path on all errors, including EAGAIN
  3139       // Fallback to slow path on all errors, including EAGAIN
  3143       stack_extent = (uintptr_t) get_stack_mapped_bottom(os::Linux::initial_thread_stack_bottom(),
  3140       stack_extent = (uintptr_t) get_stack_commited_bottom(
  3144                                                          (size_t)addr - stack_extent,
  3141                                                            os::Linux::initial_thread_stack_bottom(),
  3145                                                          false /* committed_only */);
  3142                                                            (size_t)addr - stack_extent);
  3146     }
  3143     }
  3147 
  3144 
  3148     if (stack_extent < (uintptr_t)addr) {
  3145     if (stack_extent < (uintptr_t)addr) {
  3149       ::munmap((void*)stack_extent, (uintptr_t)(addr - stack_extent));
  3146       ::munmap((void*)stack_extent, (uintptr_t)(addr - stack_extent));
  3150     }
  3147     }
  3165   if (os::is_primordial_thread()) {
  3162   if (os::is_primordial_thread()) {
  3166     return ::munmap(addr, size) == 0;
  3163     return ::munmap(addr, size) == 0;
  3167   }
  3164   }
  3168 
  3165 
  3169   return os::uncommit_memory(addr, size);
  3166   return os::uncommit_memory(addr, size);
  3170 }
       
  3171 
       
  3172 size_t os::committed_stack_size(address bottom, size_t size) {
       
  3173   address bot = get_stack_mapped_bottom(bottom, size, true /* committed_only */);
       
  3174   return size_t(bottom + size - bot);
       
  3175 }
  3167 }
  3176 
  3168 
  3177 // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
  3169 // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
  3178 // at 'requested_addr'. If there are existing memory mappings at the same
  3170 // at 'requested_addr'. If there are existing memory mappings at the same
  3179 // location, however, they will be overwritten. If 'fixed' is false,
  3171 // location, however, they will be overwritten. If 'fixed' is false,