< prev index next >

src/hotspot/os/posix/os_posix.cpp

Print this page




  23  */
  24 
  25 #include "jvm.h"
  26 #include "utilities/globalDefinitions.hpp"
  27 #include "runtime/frame.inline.hpp"
  28 #include "runtime/interfaceSupport.hpp"
  29 #include "runtime/os.hpp"
  30 #include "utilities/align.hpp"
  31 #include "utilities/macros.hpp"
  32 #include "utilities/vmError.hpp"
  33 
  34 #ifndef __APPLE__
  35 // POSIX unamed semaphores are not supported on OS X.
  36 #include "semaphore_posix.hpp"
  37 #endif
  38 
  39 #include <dlfcn.h>
  40 #include <pthread.h>
  41 #include <semaphore.h>
  42 #include <signal.h>

  43 #include <sys/resource.h>
  44 #include <sys/utsname.h>
  45 #include <time.h>
  46 #include <unistd.h>
  47 
  48 // Todo: provide a os::get_max_process_id() or similar. Number of processes
  49 // may have been configured, can be read more accurately from proc fs etc.
  50 #ifndef MAX_PID
  51 #define MAX_PID INT_MAX
  52 #endif
  53 #define IS_VALID_PID(p) (p > 0 && p < MAX_PID)
  54 














  55 // Check core dump limit and report possible place where core can be found
  56 void os::check_dump_limit(char* buffer, size_t bufferSize) {
  57   if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
  58     jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
  59     VMError::record_coredump_status(buffer, false);
  60     return;
  61   }
  62 
  63   int n;
  64   struct rlimit rlim;
  65   bool success;
  66 
  67   char core_path[PATH_MAX];
  68   n = get_core_path(core_path, PATH_MAX);
  69 
  70   if (n <= 0) {
  71     jio_snprintf(buffer, bufferSize, "core.%d (may not exist)", current_process_id());
  72     success = true;
  73 #ifdef LINUX
  74   } else if (core_path[0] == '"') { // redirect to user process


 128 
 129 bool os::unsetenv(const char* name) {
 130   assert(name != NULL, "Null pointer");
 131   return (::unsetenv(name) == 0);
 132 }
 133 
 134 int os::get_last_error() {
 135   return errno;
 136 }
 137 
 138 bool os::is_debugger_attached() {
 139   // not implemented
 140   return false;
 141 }
 142 
 143 void os::wait_for_keypress_at_exit(void) {
 144   // don't do anything on posix platforms
 145   return;
 146 }
 147 


















































































































 148 // Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
 149 // so on posix, unmap the section at the start and at the end of the chunk that we mapped
 150 // rather than unmapping and remapping the whole chunk to get requested alignment.
 151 char* os::reserve_memory_aligned(size_t size, size_t alignment) {
 152   assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,
 153       "Alignment must be a multiple of allocation granularity (page size)");
 154   assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");
 155 
 156   size_t extra_size = size + alignment;
 157   assert(extra_size >= size, "overflow, size is too large to allow alignment");
 158 
 159   char* extra_base = os::reserve_memory(extra_size, NULL, alignment);













 160 
 161   if (extra_base == NULL) {
 162     return NULL;
 163   }
 164 
 165   // Do manual alignment
 166   char* aligned_base = align_up(extra_base, alignment);
 167 
 168   // [  |                                       |  ]
 169   // ^ extra_base
 170   //    ^ extra_base + begin_offset == aligned_base
 171   //     extra_base + begin_offset + size       ^
 172   //                       extra_base + extra_size ^
 173   // |<>| == begin_offset
 174   //                              end_offset == |<>|
 175   size_t begin_offset = aligned_base - extra_base;
 176   size_t end_offset = (extra_base + extra_size) - (aligned_base + size);
 177 
 178   if (begin_offset > 0) {
 179       os::release_memory(extra_base, begin_offset);
 180   }
 181 
 182   if (end_offset > 0) {
 183       os::release_memory(extra_base + begin_offset + size, end_offset);
 184   }
 185 







 186   return aligned_base;
 187 }
 188 
 189 int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) {
 190     return vsnprintf(buf, len, fmt, args);
 191 }
 192 
 193 int os::get_fileno(FILE* fp) {
 194   return NOT_AIX(::)fileno(fp);
 195 }
 196 
 197 struct tm* os::gmtime_pd(const time_t* clock, struct tm*  res) {
 198   return gmtime_r(clock, res);
 199 }
 200 
 201 void os::Posix::print_load_average(outputStream* st) {
 202   st->print("load average:");
 203   double loadavg[3];
 204   os::loadavg(loadavg, 3);
 205   st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]);


1333   return false;
1334 }
1335 
1336 void os::ThreadCrashProtection::restore() {
1337   assert(_crash_protection != NULL, "must have crash protection");
1338   siglongjmp(_jmpbuf, 1);
1339 }
1340 
1341 void os::ThreadCrashProtection::check_crash_protection(int sig,
1342     Thread* thread) {
1343 
1344   if (thread != NULL &&
1345       thread == _protected_thread &&
1346       _crash_protection != NULL) {
1347 
1348     if (sig == SIGSEGV || sig == SIGBUS) {
1349       _crash_protection->restore();
1350     }
1351   }
1352 }
1353 
1354 #define check_with_errno(check_type, cond, msg)                             \
1355   do {                                                                      \
1356     int err = errno;                                                        \
1357     check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err),   \
1358                os::errno_name(err));                                        \
1359 } while (false)
1360 
1361 #define assert_with_errno(cond, msg)    check_with_errno(assert, cond, msg)
1362 #define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
1363 
1364 // POSIX unamed semaphores are not supported on OS X.
1365 #ifndef __APPLE__
1366 
1367 PosixSemaphore::PosixSemaphore(uint value) {
1368   int ret = sem_init(&_semaphore, 0, value);
1369 
1370   guarantee_with_errno(ret == 0, "Failed to initialize semaphore");
1371 }
1372 
1373 PosixSemaphore::~PosixSemaphore() {
1374   sem_destroy(&_semaphore);
1375 }
1376 
1377 void PosixSemaphore::signal(uint count) {
1378   for (uint i = 0; i < count; i++) {
1379     int ret = sem_post(&_semaphore);
1380 
1381     assert_with_errno(ret == 0, "sem_post failed");
1382   }




  23  */
  24 
  25 #include "jvm.h"
  26 #include "utilities/globalDefinitions.hpp"
  27 #include "runtime/frame.inline.hpp"
  28 #include "runtime/interfaceSupport.hpp"
  29 #include "runtime/os.hpp"
  30 #include "utilities/align.hpp"
  31 #include "utilities/macros.hpp"
  32 #include "utilities/vmError.hpp"
  33 
  34 #ifndef __APPLE__
  35 // POSIX unamed semaphores are not supported on OS X.
  36 #include "semaphore_posix.hpp"
  37 #endif
  38 
  39 #include <dlfcn.h>
  40 #include <pthread.h>
  41 #include <semaphore.h>
  42 #include <signal.h>
  43 #include <sys/mman.h>
  44 #include <sys/resource.h>
  45 #include <sys/utsname.h>
  46 #include <time.h>
  47 #include <unistd.h>
  48 
  49 // Todo: provide a os::get_max_process_id() or similar. Number of processes
  50 // may have been configured, can be read more accurately from proc fs etc.
  51 #ifndef MAX_PID
  52 #define MAX_PID INT_MAX
  53 #endif
  54 #define IS_VALID_PID(p) (p > 0 && p < MAX_PID)
  55 
  56 #ifndef MAP_ANONYMOUS
  57   #define MAP_ANONYMOUS MAP_ANON
  58 #endif
  59 
  60 #define check_with_errno(check_type, cond, msg)                             \
  61   do {                                                                      \
  62     int err = errno;                                                        \
  63     check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err),   \
  64                os::errno_name(err));                                        \
  65 } while (false)
  66 
  67 #define assert_with_errno(cond, msg)    check_with_errno(assert, cond, msg)
  68 #define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
  69 
  70 // Check core dump limit and report possible place where core can be found
  71 void os::check_dump_limit(char* buffer, size_t bufferSize) {
  72   if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
  73     jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
  74     VMError::record_coredump_status(buffer, false);
  75     return;
  76   }
  77 
  78   int n;
  79   struct rlimit rlim;
  80   bool success;
  81 
  82   char core_path[PATH_MAX];
  83   n = get_core_path(core_path, PATH_MAX);
  84 
  85   if (n <= 0) {
  86     jio_snprintf(buffer, bufferSize, "core.%d (may not exist)", current_process_id());
  87     success = true;
  88 #ifdef LINUX
  89   } else if (core_path[0] == '"') { // redirect to user process


 143 
 144 bool os::unsetenv(const char* name) {
 145   assert(name != NULL, "Null pointer");
 146   return (::unsetenv(name) == 0);
 147 }
 148 
 149 int os::get_last_error() {
 150   return errno;
 151 }
 152 
 153 bool os::is_debugger_attached() {
 154   // not implemented
 155   return false;
 156 }
 157 
 158 void os::wait_for_keypress_at_exit(void) {
 159   // don't do anything on posix platforms
 160   return;
 161 }
 162 
 163 int os::create_file_for_heap(const char* dir) {
 164 
 165   const char name_template[] = "/jvmheap.XXXXXX";
 166 
 167   char *fullname = (char*)os::malloc((strlen(dir) + strlen(name_template) + 1), mtInternal);
 168   if (fullname == NULL) {
 169     vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno)));
 170     return -1;
 171   }
 172   (void)strncpy(fullname, dir, strlen(dir)+1);
 173   (void)strncat(fullname, name_template, strlen(name_template));
 174 
 175   os::native_path(fullname);
 176 
 177   sigset_t set, oldset;
 178   int ret = sigfillset(&set);
 179   assert_with_errno(ret == 0, "sigfillset returned error");
 180 
 181   // set the file creation mask.
 182   mode_t file_mode = S_IRUSR | S_IWUSR;
 183 
 184   // create a new file.
 185   int fd = mkstemp(fullname);
 186 
 187   if (fd < 0) {
 188     warning("Could not create file for heap with template %s", fullname);
 189     os::free(fullname);
 190     return -1;
 191   }
 192 
 193   // delete the name from the filesystem. When 'fd' is closed, the file (and space) will be deleted.
 194   ret = unlink(fullname);
 195   assert_with_errno(ret == 0, "unlink returned error");
 196 
 197   os::free(fullname);
 198   return fd;
 199 }
 200 
 201 static char* reserve_mmapped_memory(size_t bytes, char* requested_addr) {
 202   char * addr;
 203   int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS;
 204   if (requested_addr != NULL) {
 205     assert((uintptr_t)requested_addr % os::vm_page_size() == 0, "Requested address should be aligned to OS page size");
 206     flags |= MAP_FIXED;
 207   }
 208 
 209   // Map reserved/uncommitted pages PROT_NONE so we fail early if we
 210   // touch an uncommitted page. Otherwise, the read/write might
 211   // succeed if we have enough swap space to back the physical page.
 212   addr = (char*)::mmap(requested_addr, bytes, PROT_NONE,
 213                        flags, -1, 0);
 214 
 215   if (addr != MAP_FAILED) {
 216     MemTracker::record_virtual_memory_reserve((address)addr, bytes, CALLER_PC);
 217     return addr;
 218   }
 219   return NULL;
 220 }
 221 
 222 static int util_posix_fallocate(int fd, off_t offset, off_t len) {
 223 #ifdef __APPLE__
 224   fstore_t store = { F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, len };
 225   // First we try to get a continuous chunk of disk space
 226   int ret = fcntl(fd, F_PREALLOCATE, &store);
 227   if (ret == -1) {
 228     // Maybe we are too fragmented, try to allocate non-continuous range
 229     store.fst_flags = F_ALLOCATEALL;
 230     ret = fcntl(fd, F_PREALLOCATE, &store);
 231   }
 232   if(ret != -1) {
 233     return ftruncate(fd, len);
 234   }
 235   return -1;
 236 #else
 237   return posix_fallocate(fd, offset, len);
 238 #endif
 239 }
 240 
 241 // Map the given address range to the provided file descriptor.
 242 char* os::map_memory_to_file(char* base, size_t size, int fd) {
 243   assert(fd != -1, "File descriptor is not valid");
 244 
 245   // allocate space for the file
 246   if (util_posix_fallocate(fd, 0, (off_t)size) != 0) {
 247     vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory."));
 248     return NULL;
 249   }
 250 
 251   int prot = PROT_READ | PROT_WRITE;
 252   int flags = MAP_SHARED;
 253   if (base != NULL) {
 254     flags |= MAP_FIXED;
 255   }
 256   char* addr = (char*)mmap(base, size, prot, flags, fd, 0);
 257 
 258   if (addr == MAP_FAILED) {
 259     return NULL;
 260   }
 261   if (base != NULL && addr != base) {
 262     if (!os::release_memory(addr, size)) {
 263       warning("Could not release memory on unsuccessful file mapping");
 264      }
 265     return NULL;
 266   }
 267   return addr;
 268 }
 269 
 270 char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd) {
 271   assert(fd != -1, "File descriptor is not valid");
 272   assert(base != NULL, "Base cannot be NULL");
 273 
 274   return map_memory_to_file(base, size, fd);
 275 }
 276 
 277 // Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
 278 // so on posix, unmap the section at the start and at the end of the chunk that we mapped
 279 // rather than unmapping and remapping the whole chunk to get requested alignment.
 280 char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
 281   assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,
 282       "Alignment must be a multiple of allocation granularity (page size)");
 283   assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");
 284 
 285   size_t extra_size = size + alignment;
 286   assert(extra_size >= size, "overflow, size is too large to allow alignment");
 287 
 288   char* extra_base;
 289   if (file_desc != -1) {
 290     // For file mapping, we do not call os:reserve_memory(extra_size, NULL, alignment, file_desc) because
 291     // we need to deal with shrinking of the file space later when we release extra memory after alignment.
 292     // We also cannot called os:reserve_memory() with file_desc set to -1 because on aix we might get SHM memory.
 293     // So here to call a helper function while reserve memory for us. After we have a aligned base,
 294     // we will replace anonymous mapping with file mapping.
 295     extra_base = reserve_mmapped_memory(extra_size, NULL);
 296     if (extra_base != NULL) {
 297       MemTracker::record_virtual_memory_reserve((address)extra_base, extra_size, CALLER_PC);
 298     }
 299   } else {
 300     extra_base = os::reserve_memory(extra_size, NULL, alignment);
 301   }
 302 
 303   if (extra_base == NULL) {
 304     return NULL;
 305   }
 306 
 307   // Do manual alignment
 308   char* aligned_base = align_up(extra_base, alignment);
 309 
 310   // [  |                                       |  ]
 311   // ^ extra_base
 312   //    ^ extra_base + begin_offset == aligned_base
 313   //     extra_base + begin_offset + size       ^
 314   //                       extra_base + extra_size ^
 315   // |<>| == begin_offset
 316   //                              end_offset == |<>|
 317   size_t begin_offset = aligned_base - extra_base;
 318   size_t end_offset = (extra_base + extra_size) - (aligned_base + size);
 319 
 320   if (begin_offset > 0) {
 321       os::release_memory(extra_base, begin_offset);
 322   }
 323 
 324   if (end_offset > 0) {
 325       os::release_memory(extra_base + begin_offset + size, end_offset);
 326   }
 327 
 328   if (file_desc != -1) {
 329     // After we have an aligned address, we can replace anonymous mapping with file mapping
 330     if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == NULL) {
 331       vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
 332     }
 333     MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC);
 334   }
 335   return aligned_base;
 336 }
 337 
 338 int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) {
 339     return vsnprintf(buf, len, fmt, args);
 340 }
 341 
 342 int os::get_fileno(FILE* fp) {
 343   return NOT_AIX(::)fileno(fp);
 344 }
 345 
 346 struct tm* os::gmtime_pd(const time_t* clock, struct tm*  res) {
 347   return gmtime_r(clock, res);
 348 }
 349 
 350 void os::Posix::print_load_average(outputStream* st) {
 351   st->print("load average:");
 352   double loadavg[3];
 353   os::loadavg(loadavg, 3);
 354   st->print("%0.02f %0.02f %0.02f", loadavg[0], loadavg[1], loadavg[2]);


1482   return false;
1483 }
1484 
1485 void os::ThreadCrashProtection::restore() {
1486   assert(_crash_protection != NULL, "must have crash protection");
1487   siglongjmp(_jmpbuf, 1);
1488 }
1489 
1490 void os::ThreadCrashProtection::check_crash_protection(int sig,
1491     Thread* thread) {
1492 
1493   if (thread != NULL &&
1494       thread == _protected_thread &&
1495       _crash_protection != NULL) {
1496 
1497     if (sig == SIGSEGV || sig == SIGBUS) {
1498       _crash_protection->restore();
1499     }
1500   }
1501 }










1502 
1503 // POSIX unamed semaphores are not supported on OS X.
1504 #ifndef __APPLE__
1505 
1506 PosixSemaphore::PosixSemaphore(uint value) {
1507   int ret = sem_init(&_semaphore, 0, value);
1508 
1509   guarantee_with_errno(ret == 0, "Failed to initialize semaphore");
1510 }
1511 
1512 PosixSemaphore::~PosixSemaphore() {
1513   sem_destroy(&_semaphore);
1514 }
1515 
1516 void PosixSemaphore::signal(uint count) {
1517   for (uint i = 0; i < count; i++) {
1518     int ret = sem_post(&_semaphore);
1519 
1520     assert_with_errno(ret == 0, "sem_post failed");
1521   }


< prev index next >