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 } |