/* * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// put OS-includes here # include <dlfcn.h> # include <errno.h> # include <fcntl.h> # include <inttypes.h> # include <poll.h> # include <pthread.h> # include <pwd.h> # include <signal.h> # include <stdint.h> # include <stdio.h> # include <string.h> # include <sys/ioctl.h> # include <sys/mman.h> # include <sys/param.h> # include <sys/resource.h> # include <sys/socket.h> # include <sys/stat.h> # include <sys/syscall.h> # include <sys/sysctl.h> # include <sys/time.h> # include <sys/times.h> # include <sys/types.h> # include <time.h> # include <unistd.h>
// available here means free
julong os::Bsd::available_memory() {
uint64_t available = physical_memory() >> 2; #ifdef __APPLE__
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
vm_statistics64_data_t vmstat;
kern_return_t kerr = host_statistics64(mach_host_self(), HOST_VM_INFO64,
(host_info64_t)&vmstat, &count);
assert(kerr == KERN_SUCCESS, "host_statistics64 failed - check mach_host_self() and count"); if (kerr == KERN_SUCCESS) {
available = vmstat.free_count * os::vm_page_size();
} #endif return available;
}
// for more info see : // https://man.openbsd.org/sysctl.2 void os::Bsd::print_uptime_info(outputStream* st) { struct timeval boottime;
size_t len = sizeof(boottime); int mib[2];
mib[0] = CTL_KERN;
mib[1] = KERN_BOOTTIME;
void os::Bsd::initialize_system_info() { int mib[2];
size_t len; int cpu_val;
julong mem_val;
// get processors count via hw.ncpus sysctl
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
len = sizeof(cpu_val); if (sysctl(mib, 2, &cpu_val, &len, NULL, 0) != -1 && cpu_val >= 1) {
assert(len == sizeof(cpu_val), "unexpected data size");
set_processor_count(cpu_val);
} else {
set_processor_count(1); // fallback
}
#ifdefined(__APPLE__) && defined(__x86_64__) // initialize processor id map for (int i = 0; i < processor_id_map_size; i++) {
processor_id_map[i] = processor_id_unassigned;
} #endif
// get physical memory via hw.memsize sysctl (hw.memsize is used // since it returns a 64 bit value)
mib[0] = CTL_HW;
#ifdefined (HW_MEMSIZE) // Apple
mib[1] = HW_MEMSIZE; #elifdefined(HW_PHYSMEM) // Most of BSD
mib[1] = HW_PHYSMEM; #elifdefined(HW_REALMEM) // Old FreeBSD
mib[1] = HW_REALMEM; #else #error No ways to get physmem #endif
void os::init_system_properties_values() { // The next steps are taken in the product version: // // Obtain the JAVA_HOME value from the location of libjvm.so. // This library should be located at: // <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm.so. // // If "/jre/lib/" appears at the right place in the path, then we // assume libjvm.so is installed in a JDK and we use this path. // // Otherwise exit with message: "Could not create the Java virtual machine." // // The following extra steps are taken in the debugging version: // // If "/jre/lib/" does NOT appear at the right place in the path // instead of exit check for $JAVA_HOME environment variable. // // If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>, // then we append a fake suffix "hotspot/libjvm.so" to this path so // it looks like libjvm.so is installed there // <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm.so. // // Otherwise exit. // // Important note: if the location of libjvm.so changes this // code needs to be changed accordingly.
// See ld(1): // The linker uses the following search paths to locate required // shared libraries: // 1: ... // ... // 7: The default directories, normally /lib and /usr/lib. #ifndef DEFAULT_LIBPATH #ifndef OVERRIDE_LIBPATH #define DEFAULT_LIBPATH "/lib:/usr/lib" #else #define DEFAULT_LIBPATH OVERRIDE_LIBPATH #endif #endif
// Base path of extensions installed on the system. #define SYS_EXT_DIR "/usr/java/packages" #define EXTENSIONS_DIR "/lib/ext"
#ifndef __APPLE__
// Buffer that fits several sprintfs. // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator. const size_t bufsize =
MAX2((size_t)MAXPATHLEN, // For dll_dir & friends.
(size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + sizeof(SYS_EXT_DIR) + sizeof(EXTENSIONS_DIR)); // extensions dir char *buf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
// Found the full path to libjvm.so. // Now cut the path to <java_home>/jre if we can.
*(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
pslash = strrchr(buf, '/'); if (pslash != NULL) {
*pslash = '\0'; // Get rid of /{client|server|hotspot}.
}
Arguments::set_dll_dir(buf);
if (pslash != NULL) {
pslash = strrchr(buf, '/'); if (pslash != NULL) {
*pslash = '\0'; // Get rid of /<arch>.
pslash = strrchr(buf, '/'); if (pslash != NULL) {
*pslash = '\0'; // Get rid of /lib.
}
}
}
Arguments::set_java_home(buf); if (!set_boot_path('/', ':')) {
vm_exit_during_initialization("Failed setting boot class path.", NULL);
}
}
// Where to look for native libraries. // // Note: Due to a legacy implementation, most of the library path // is set in the launcher. This was to accommodate linking restrictions // on legacy Bsd implementations (which are no longer supported). // Eventually, all the library path setting will be done here. // // However, to prevent the proliferation of improperly built native // libraries, the new path component /usr/java/packages is added here. // Eventually, all the library path setting will be done here.
{ // Get the user setting of LD_LIBRARY_PATH, and prepended it. It // should always exist (until the legacy problem cited above is // addressed). constchar *v = ::getenv("LD_LIBRARY_PATH"); constchar *v_colon = ":"; if (v == NULL) { v = ""; v_colon = ""; } // That's +1 for the colon and +1 for the trailing '\0'. char *ld_library_path = NEW_C_HEAP_ARRAY(char,
strlen(v) + 1 + sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1,
mtInternal);
sprintf(ld_library_path, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch);
Arguments::set_library_path(ld_library_path);
FREE_C_HEAP_ARRAY(char, ld_library_path);
}
constchar *user_home_dir = get_home(); // The null in SYS_EXTENSIONS_DIRS counts for the size of the colon after user_home_dir.
size_t system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) + sizeof(SYS_EXTENSIONS_DIRS);
// Buffer that fits several sprintfs. // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator. const size_t bufsize =
MAX2((size_t)MAXPATHLEN, // for dll_dir & friends.
(size_t)MAXPATHLEN + sizeof(EXTENSIONS_DIR) + system_ext_size); // extensions dir char *buf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
// Found the full path to libjvm.so. // Now cut the path to <java_home>/jre if we can.
*(strrchr(buf, '/')) = '\0'; // Get rid of /libjvm.so.
pslash = strrchr(buf, '/'); if (pslash != NULL) {
*pslash = '\0'; // Get rid of /{client|server|hotspot}.
} #ifdef STATIC_BUILD
strcat(buf, "/lib"); #endif
Arguments::set_dll_dir(buf);
if (pslash != NULL) {
pslash = strrchr(buf, '/'); if (pslash != NULL) {
*pslash = '\0'; // Get rid of /lib.
}
}
Arguments::set_java_home(buf); if (!set_boot_path('/', ':')) {
vm_exit_during_initialization("Failed setting boot class path.", NULL);
}
}
// Where to look for native libraries. // // Note: Due to a legacy implementation, most of the library path // is set in the launcher. This was to accommodate linking restrictions // on legacy Bsd implementations (which are no longer supported). // Eventually, all the library path setting will be done here. // // However, to prevent the proliferation of improperly built native // libraries, the new path component /usr/java/packages is added here. // Eventually, all the library path setting will be done here.
{ // Get the user setting of LD_LIBRARY_PATH, and prepended it. It // should always exist (until the legacy problem cited above is // addressed). // Prepend the default path with the JAVA_LIBRARY_PATH so that the app launcher code // can specify a directory inside an app wrapper constchar *l = ::getenv("JAVA_LIBRARY_PATH"); constchar *l_colon = ":"; if (l == NULL) { l = ""; l_colon = ""; }
constchar *v = ::getenv("DYLD_LIBRARY_PATH"); constchar *v_colon = ":"; if (v == NULL) { v = ""; v_colon = ""; }
// Apple's Java6 has "." at the beginning of java.library.path. // OpenJDK on Windows has "." at the end of java.library.path. // OpenJDK on Linux and Solaris don't have "." in java.library.path // at all. To ease the transition from Apple's Java6 to OpenJDK7, // "." is appended to the end of java.library.path. Yes, this // could cause a change in behavior, but Apple's Java6 behavior // can be achieved by putting "." at the beginning of the // JAVA_LIBRARY_PATH environment variable. char *ld_library_path = NEW_C_HEAP_ARRAY(char,
strlen(v) + 1 + strlen(l) + 1 +
system_ext_size + 3,
mtInternal);
sprintf(ld_library_path, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.",
v, v_colon, l, l_colon, user_home_dir);
Arguments::set_library_path(ld_library_path);
FREE_C_HEAP_ARRAY(char, ld_library_path);
}
// Extensions directories. // // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator (so actually one byte more // than necessary is allocated).
sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS,
user_home_dir, Arguments::get_java_home());
Arguments::set_ext_dirs(buf);
// calculate stack size if it's not specified by caller
size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size); int status = pthread_attr_setstacksize(&attr, stack_size);
assert_status(status == 0, status, "pthread_attr_setstacksize");
ThreadState state;
{
ResourceMark rm;
pthread_t tid; int ret = 0; int limit = 3; do {
ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);
} while (ret == EAGAIN && limit-- > 0);
char buf[64]; if (ret == 0) {
log_info(os, thread)("Thread \"%s\" started (pthread id: " UINTX_FORMAT ", attributes: %s). ",
thread->name(), (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
} else {
log_warning(os, thread)("Failed to start thread \"%s\" - pthread_create failed (%s) for attributes: %s.",
thread->name(), os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); // Log some OS information which might explain why creating the thread failed.
log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
LogStream st(Log(os, thread)::info());
os::Posix::print_rlimit_info(&st);
os::print_memory_info(&st);
}
pthread_attr_destroy(&attr);
if (ret != 0) { // Need to clean up stuff we've allocated so far
thread->set_osthread(NULL); delete osthread; returnfalse;
}
// Store pthread info into the OSThread
osthread->set_pthread_id(tid);
// Wait until child thread is either initialized or aborted
{
Monitor* sync_with_child = osthread->startThread_lock();
MutexLocker ml(sync_with_child, Mutex::_no_safepoint_check_flag); while ((state = osthread->get_state()) == ALLOCATED) {
sync_with_child->wait_without_safepoint_check();
}
}
}
// The thread is returned suspended (in state INITIALIZED), // and is started higher up in the call chain
assert(state == INITIALIZED, "race condition"); returntrue;
}
// bootstrap the main thread bool os::create_main_thread(JavaThread* thread) {
assert(os::Bsd::_main_thread == pthread_self(), "should be called inside main thread"); return create_attached_thread(thread);
}
// Free Bsd resources related to the OSThread void os::free_thread(OSThread* osthread) {
assert(osthread != NULL, "osthread not set");
// We are told to free resources of the argument thread, // but we can only really operate on the current thread.
assert(Thread::current()->osthread() == osthread, "os::free_thread but not current thread");
//////////////////////////////////////////////////////////////////////////////// // time support double os::elapsedVTime() { // better than nothing, but not much return elapsedTime();
}
#ifdef __APPLE__ void os::Bsd::clock_init() {
mach_timebase_info(&_timebase_info);
} #else void os::Bsd::clock_init() { // Nothing to do
} #endif
#ifdef __APPLE__
jlong os::javaTimeNanos() { const uint64_t tm = mach_absolute_time(); const uint64_t now = (tm * Bsd::_timebase_info.numer) / Bsd::_timebase_info.denom; const uint64_t prev = Bsd::_max_abstime; if (now <= prev) { return prev; // same or retrograde time;
} const uint64_t obsv = Atomic::cmpxchg(&Bsd::_max_abstime, prev, now);
assert(obsv >= prev, "invariant"); // Monotonicity // If the CAS succeeded then we're done and return "now". // If the CAS failed and the observed value "obsv" is >= now then // we should return "obsv". If the CAS failed and now > obsv > prv then // some other thread raced this thread and installed a new value, in which case // we could either (a) retry the entire operation, (b) retry trying to install now // or (c) just return obsv. We use (c). No loop is required although in some cases // we might discard a higher "now" value in deference to a slightly lower but freshly // installed obsv value. That's entirely benign -- it admits no new orderings compared // to (a) or (b) -- and greatly reduces coherence traffic. // We might also condition (c) on the magnitude of the delta between obsv and now. // Avoiding excessive CAS operations to hot RW locations is critical. // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate return (prev == obsv) ? now : obsv;
}
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS;
info_ptr->may_skip_backward = false; // not subject to resetting or drifting
info_ptr->may_skip_forward = false; // not subject to resetting or drifting
info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time
} #endif// __APPLE__
// Information of current thread in variety of formats
pid_t os::Bsd::gettid() { int retval = -1;
int os::current_process_id() { return (int)(getpid());
}
// DLL functions staticint local_dladdr(constvoid* addr, Dl_info* info) { #ifdef __APPLE__ if (addr == (void*)-1) { // dladdr() in macOS12/Monterey returns success for -1, but that addr // value should not be allowed to work to avoid confusion. return 0;
} #endif return dladdr(addr, info);
}
// This must be hard coded because it's the system's temporary // directory not the java application's temp directory, ala java.io.tmpdir. #ifdef __APPLE__ // macosx has a secure per-user temporary directory char temp_path_storage[PATH_MAX]; constchar* os::get_temp_directory() { staticchar *temp_path = NULL; if (temp_path == NULL) { int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, temp_path_storage, PATH_MAX); if (pathSize == 0 || pathSize > PATH_MAX) {
strlcpy(temp_path_storage, "/tmp/", sizeof(temp_path_storage));
}
temp_path = temp_path_storage;
} return temp_path;
} #else// __APPLE__ constchar* os::get_temp_directory() { return"/tmp"; } #endif// __APPLE__
// check if addr is inside libjvm.so bool os::address_is_in_vm(address addr) { static address libjvm_base_addr;
Dl_info dlinfo;
if (libjvm_base_addr == NULL) { if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) {
libjvm_base_addr = (address)dlinfo.dli_fbase;
}
assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm");
}
if (dladdr((void *)addr, &dlinfo) != 0) { if (libjvm_base_addr == (address)dlinfo.dli_fbase) returntrue;
}
returnfalse;
}
bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int *offset, bool demangle) { // buf is not optional, but offset is optional
assert(buf != NULL, "sanity check");
Dl_info dlinfo;
if (local_dladdr((void*)addr, &dlinfo) != 0) { // see if we have a matching symbol if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) { if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
} if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; returntrue;
}
#ifndef __APPLE__ // The 6-parameter Decoder::decode() function is not implemented on macOS. // The Mach-O binary format does not contain a "list of files" with address // ranges like ELF. That makes sense since Mach-O can contain binaries for // than one instruction set so there can be more than one address range for // each "file".
// no matching symbol so try for just file info if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
buf, buflen, offset, dlinfo.dli_fname, demangle)) { returntrue;
}
}
bool os::dll_address_to_library_name(address addr, char* buf, int buflen, int* offset) { // buf is not optional, but offset is optional
assert(buf != NULL, "sanity check");
typedefstruct {
Elf32_Half code; // Actual value as defined in elf.h
Elf32_Half compat_class; // Compatibility of archs at VM's sense char elf_class; // 32 or 64 bit char endianess; // MSB or LSB char* name; // String representation
} arch_t;
// Identify compatibility class for VM's architecture and library's architecture // Obtain string descriptions for architectures
arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL}; int running_arch_index=-1;
for (unsignedint i=0; i < ARRAY_SIZE(arch_array); i++) { if (running_arch_code == arch_array[i].code) {
running_arch_index = i;
} if (lib_arch.code == arch_array[i].code) {
lib_arch.compat_class = arch_array[i].compat_class;
lib_arch.name = arch_array[i].name;
}
}
assert(running_arch_index != -1, "Didn't find running architecture code (running_arch_code) in arch_array"); if (running_arch_index == -1) { // Even though running architecture detection failed // we may still continue with reporting dlerror() message return NULL;
}
while (map != NULL) { // Value for top_address is returned as 0 since we don't have any information about module size if (callback(map->l_name, (address)map->l_addr, (address)0, param)) {
dlclose(handle); return 1;
}
map = map->l_next;
}
dlclose(handle); #elifdefined(__APPLE__) for (uint32_t i = 1; i < _dyld_image_count(); i++) { // Value for top_address is returned as 0 since we don't have any information about module size if (callback(_dyld_get_image_name(i), (address)_dyld_get_image_header(i), (address)0, param)) { return 1;
}
} return 0; #else return 1; #endif
}
void os::get_summary_os_info(char* buf, size_t buflen) { // These buffers are small because we want this to be brief // and not use a lot of stack while generating the hs_err file. char os[100];
size_t size = sizeof(os); int mib_kern[] = { CTL_KERN, KERN_OSTYPE }; if (sysctl(mib_kern, 2, os, &size, NULL, 0) < 0) { #ifdef __APPLE__
strncpy(os, "Darwin", sizeof(os)); #elif __OpenBSD__
strncpy(os, "OpenBSD", sizeof(os)); #else
strncpy(os, "BSD", sizeof(os)); #endif
}
// Find the full path to the current module, libjvm void os::jvm_path(char *buf, jint buflen) { // Error checking. if (buflen < MAXPATHLEN) {
assert(false, "must use a large-enough buffer");
buf[0] = '\0'; return;
} // Lazy resolve the path to current module. if (saved_jvm_path[0] != 0) {
strcpy(buf, saved_jvm_path); return;
}
if (Arguments::sun_java_launcher_is_altjvm()) { // Support for the java launcher's '-XXaltjvm=<path>' option. Typical // value for buf is "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so" // or "<JAVA_HOME>/jre/lib/<vmtype>/libjvm.dylib". If "/jre/lib/" // appears at the right place in the string, then assume we are // installed in a JDK and we're done. Otherwise, check for a // JAVA_HOME environment variable and construct a path to the JVM // being overridden.
constchar *p = buf + strlen(buf) - 1; for (int count = 0; p > buf && count < 5; ++count) { for (--p; p > buf && *p != '/'; --p) /* empty */ ;
}
if (strncmp(p, "/jre/lib/", 9) != 0) { // Look for JAVA_HOME in the environment. char* java_home_var = ::getenv("JAVA_HOME"); if (java_home_var != NULL && java_home_var[0] != 0) { char* jrelib_p; int len;
// Check the current module name "libjvm"
p = strrchr(buf, '/');
assert(strstr(p, "/libjvm") == p, "invalid library name");
rp = os::Posix::realpath(java_home_var, buf, buflen); if (rp == NULL) { return;
}
// determine if this is a legacy image or modules image // modules image doesn't have "jre" subdirectory
len = strlen(buf);
assert(len < buflen, "Ran out of buffer space");
jrelib_p = buf + len;
// Add the appropriate library subdir
snprintf(jrelib_p, buflen-len, "/jre/lib"); if (0 != access(buf, F_OK)) {
snprintf(jrelib_p, buflen-len, "/lib");
}
// Add the appropriate client or server subdir
len = strlen(buf);
jrelib_p = buf + len;
snprintf(jrelib_p, buflen-len, "/%s", COMPILER_VARIANT); if (0 != access(buf, F_OK)) {
snprintf(jrelib_p, buflen-len, "%s", "");
}
// If the path exists within JAVA_HOME, add the JVM library name // to complete the path to JVM being overridden. Otherwise fallback // to the path to the current library. if (0 == access(buf, F_OK)) { // Use current module name "libjvm"
len = strlen(buf);
snprintf(buf + len, buflen-len, "/libjvm%s", JNI_LIB_SUFFIX);
} else { // Fall back to path of current library
rp = os::Posix::realpath(dli_fname, buf, buflen); if (rp == NULL) { return;
}
}
}
}
}
// NOTE: Bsd kernel does not really reserve the pages for us. // All it does is to check if there are enough free pages // left at the time of mmap(). This could be a potential // problem. bool os::pd_commit_memory(char* addr, size_t size, bool exec) { int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; #ifdefined(__OpenBSD__) // XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
Events::log(NULL, "Protecting memory [" INTPTR_FORMAT "," INTPTR_FORMAT "] with protection modes %x", p2i(addr), p2i(addr+size), prot); if (::mprotect(addr, size, prot) == 0) { returntrue;
} #elifdefined(__APPLE__) if (exec) { // Do not replace MAP_JIT mappings, see JDK-8234930 if (::mprotect(addr, size, prot) == 0) { returntrue;
}
} else {
uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); if (res != (uintptr_t) MAP_FAILED) { returntrue;
}
} #else
uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); if (res != (uintptr_t) MAP_FAILED) { returntrue;
} #endif
// Warn about any commit errors we see in non-product builds just // in case mmap() doesn't work as described on the man page.
NOT_PRODUCT(warn_fail_commit_memory(addr, size, exec, errno);)
returnfalse;
}
bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint, bool exec) { // alignment_hint is ignored on this OS return pd_commit_memory(addr, size, exec);
}
void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec, constchar* mesg) {
assert(mesg != NULL, "mesg must be specified"); if (!pd_commit_memory(addr, size, exec)) { // add extra info in product mode for vm_exit_out_of_memory():
PRODUCT_ONLY(warn_fail_commit_memory(addr, size, exec, errno);)
vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "%s", mesg);
}
}
void os::pd_commit_memory_or_exit(char* addr, size_t size,
size_t alignment_hint, bool exec, constchar* mesg) { // alignment_hint is ignored on this OS
pd_commit_memory_or_exit(addr, size, exec, mesg);
}
// If this is a growable mapping, remove the guard pages entirely by // munmap()ping them. If not, just call uncommit_memory(). bool os::remove_stack_guard_pages(char* addr, size_t size) { return os::uncommit_memory(addr, size);
}
// 'requested_addr' is only treated as a hint, the return value may or // may not start from the requested address. Unlike Bsd mmap(), this // function returns NULL to indicate failure. staticchar* anon_mmap(char* requested_addr, size_t bytes, bool exec) { // MAP_FIXED is intentionally left out, to leave existing mappings intact. constint flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS
MACOS_ONLY(| (exec ? MAP_JIT : 0));
// Map reserved/uncommitted pages PROT_NONE so we fail early if we // touch an uncommitted page. Otherwise, the read/write might // succeed if we have enough swap space to back the physical page. char* addr = (char*)::mmap(requested_addr, bytes, PROT_NONE, flags, -1, 0);
staticbool bsd_mprotect(char* addr, size_t size, int prot) { // Bsd wants the mprotect address argument to be page aligned. char* bottom = (char*)align_down((intptr_t)addr, os::vm_page_size());
// According to SUSv3, mprotect() should only be used with mappings // established by mmap(), and mmap() always maps whole pages. Unaligned // 'addr' likely indicates problem in the VM (e.g. trying to change // protection of malloc'ed or statically allocated memory). Check the // caller if you hit this assert.
assert(addr == bottom, "sanity check");
char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* req_addr, bool exec) {
fatal("os::reserve_memory_special should not be called on BSD."); return NULL;
}
bool os::pd_release_memory_special(char* base, size_t bytes) {
fatal("os::release_memory_special should not be called on BSD."); returnfalse;
}
bool os::can_commit_large_page_memory() { // Does not matter, we do not support huge pages. returnfalse;
}
bool os::can_execute_large_page_memory() { // Does not matter, we do not support huge pages. returnfalse;
}
char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {
assert(file_desc >= 0, "file_desc is not valid"); char* result = pd_attempt_reserve_memory_at(requested_addr, bytes, !ExecMem); if (result != NULL) { if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
}
} return result;
}
// Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else).
char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool exec) { // Assert only that the size is a multiple of the page size, since // that's all that mmap requires, and since that's all we really know // about at this low abstraction level. If we need higher alignment, // we can either pass an alignment to this method or verify alignment // in one of the methods further up the call chain. See bug 5044738.
assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
// Repeatedly allocate blocks until the block is allocated at the // right spot.
// Bsd mmap allows caller to pass an address as hint; give it a try first, // if kernel honors the hint then we can return immediately. char * addr = anon_mmap(requested_addr, bytes, exec); if (addr == requested_addr) { return requested_addr;
}
if (addr != NULL) { // mmap() is successful but it fails to reserve at the requested address
anon_munmap(addr, bytes);
}
return NULL;
}
// Used to convert frequent JVM_Yield() to nops bool os::dont_yield() { return DontYieldALot;
}
void os::naked_yield() {
sched_yield();
}
//////////////////////////////////////////////////////////////////////////////// // thread priority support
// Note: Normal Bsd applications are run with SCHED_OTHER policy. SCHED_OTHER // only supports dynamic priority, static priority must be zero. For real-time // applications, Bsd supports SCHED_RR which allows static priority (1-99). // However, for large multi-threaded applications, SCHED_RR is not only slower // than SCHED_OTHER, but also very unstable (my volano tests hang hard 4 out // of 5 runs - Sep 2005). // // The following code actually changes the niceness of kernel-thread/LWP. It // has an assumption that setpriority() only modifies one kernel-thread/LWP, // not the entire user process, and user level threads are 1:1 mapped to kernel // threads. It has always been the case, but could change in the future. For // this reason, the code should not be used as default (ThreadPriorityPolicy=0). // It is only used when ThreadPriorityPolicy=1 and may require system level permission // (e.g., root privilege or CAP_SYS_NICE capability).
#if !defined(__APPLE__) int os::java_to_os_priority[CriticalPriority + 1] = {
19, // 0 Entry should never be used
0, // 1 MinPriority
3, // 2
6, // 3
10, // 4
15, // 5 NormPriority
18, // 6
21, // 7
25, // 8
28, // 9 NearMaxPriority
31, // 10 MaxPriority
31 // 11 CriticalPriority
}; #else // Using Mach high-level priority assignments int os::java_to_os_priority[CriticalPriority + 1] = {
0, // 0 Entry should never be used (MINPRI_USER)
staticint prio_init() { if (ThreadPriorityPolicy == 1) { if (geteuid() != 0) { if (!FLAG_IS_DEFAULT(ThreadPriorityPolicy) && !FLAG_IS_JIMAGE_RESOURCE(ThreadPriorityPolicy)) {
warning("-XX:ThreadPriorityPolicy=1 may require system level permission, " \ "e.g., being the root user. If the necessary permission is not " \ "possessed, changes to priority will be silently ignored.");
}
}
} if (UseCriticalJavaThreadPriority) {
os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority];
} return 0;
}
OSReturn os::set_native_priority(Thread* thread, int newpri) { if (!UseThreadPriorities || ThreadPriorityPolicy == 0) return OS_OK;
externvoid report_error(char* file_name, int line_no, char* title, char* format, ...);
// this is called _before_ the most of global arguments have been parsed void os::init(void) { char dummy; // used to get a guess on initial stack address
int page_size = getpagesize();
OSInfo::set_vm_page_size(page_size);
OSInfo::set_vm_allocation_granularity(page_size); if (os::vm_page_size() <= 0) {
fatal("os_bsd.cpp: os::init: getpagesize() failed (%s)", os::strerror(errno));
}
_page_sizes.add(os::vm_page_size());
Bsd::initialize_system_info();
// _main_thread points to the thread that created/loaded the JVM.
Bsd::_main_thread = pthread_self();
Bsd::clock_init();
os::Posix::init();
}
// To install functions for atexit system call extern"C" { staticvoid perfMemory_exit_helper() {
perfMemory_exit();
}
}
// this is called _after_ the global arguments have been parsed
jint os::init_2(void) {
// This could be set after os::Posix::init() but all platforms // have to set it the same so we have to mirror Solaris.
DEBUG_ONLY(os::set_mutex_init_done();)
os::Posix::init_2();
if (PosixSignals::init() == JNI_ERR) { return JNI_ERR;
}
// Check and sets minimum stack sizes against command line options if (set_minimum_stack_sizes() == JNI_ERR) { return JNI_ERR;
}
// Not supported.
FLAG_SET_ERGO(UseNUMA, false);
FLAG_SET_ERGO(UseNUMAInterleaving, false);
if (MaxFDLimit) { // set the number of file descriptors to max. print out error // if getrlimit/setrlimit fails but continue regardless. struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) {
log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno));
} else {
nbr_files.rlim_cur = nbr_files.rlim_max;
#ifdef __APPLE__ // Darwin returns RLIM_INFINITY for rlim_max, but fails with EINVAL if // you attempt to use RLIM_INFINITY. As per setrlimit(2), OPEN_MAX must // be used instead
nbr_files.rlim_cur = MIN(OPEN_MAX, nbr_files.rlim_cur); #endif
status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) {
log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno));
}
}
}
// at-exit methods are called in the reverse order of their registration. // atexit functions are called on return from main or as a result of a // call to exit(3C). There can be only 32 of these functions registered // and atexit() does not set errno.
if (PerfAllowAtExitRegistration) { // only register atexit functions if PerfAllowAtExitRegistration is set. // atexit functions can be delayed until process exit time, which // can be problematic for embedded VM situations. Embedded VMs should // call DestroyJavaVM() to assure that VM resources are released.
// note: perfMemory_exit_helper atexit function may be removed in // the future if the appropriate cleanup code can be added to the // VM_Exit VMOperation's doit method. if (atexit(perfMemory_exit_helper) != 0) {
warning("os::init_2 atexit(perfMemory_exit_helper) failed");
}
}
// initialize thread priority policy
prio_init();
#ifdef __APPLE__ // dynamically link to objective c gc registration void *handleLibObjc = dlopen(OBJC_LIB, RTLD_LAZY); if (handleLibObjc != NULL) {
objc_registerThreadWithCollectorFunction = (objc_registerThreadWithCollector_t) dlsym(handleLibObjc, OBJC_GCREGISTER);
} #endif
return JNI_OK;
}
int os::active_processor_count() { // User has overridden the number of active processors if (ActiveProcessorCount > 0) {
log_trace(os)("active_processor_count: " "active processor count set by user : %d",
ActiveProcessorCount);
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.62 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.