hotspot/src/os/solaris/vm/os_solaris.cpp

Print this page
rev 611 : Merge

*** 1,10 **** #ifdef USE_PRAGMA_IDENT_SRC #pragma ident "@(#)os_solaris.cpp 1.402 07/10/04 10:49:26 JVM" #endif /* ! * Copyright 1997-2007 Sun Microsystems, Inc. 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. --- 1,10 ---- #ifdef USE_PRAGMA_IDENT_SRC #pragma ident "@(#)os_solaris.cpp 1.402 07/10/04 10:49:26 JVM" #endif /* ! * Copyright 1997-2009 Sun Microsystems, Inc. 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.
*** 123,132 **** --- 123,139 ---- #endif #ifndef MADV_ACCESS_MANY # define MADV_ACCESS_MANY 8 /* many processes to access heavily */ #endif + #ifndef LGRP_RSRC_CPU + # define LGRP_RSRC_CPU 0 /* CPU resources */ + #endif + #ifndef LGRP_RSRC_MEM + # define LGRP_RSRC_MEM 1 /* memory resources */ + #endif + // Some more macros from sys/mman.h that are not present in Solaris 8. #ifndef MAX_MEMINFO_CNT /* * info_req request type definitions for meminfo
*** 317,326 **** --- 324,337 ---- address base = current_stack_base(); address bottom = (address)align_size_up((intptr_t)(base - size), os::vm_page_size());; return (size_t)(base - bottom); } + struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { + return localtime_r(clock, res); + } + // interruptible infrastructure // setup_interruptible saves the thread state before going into an // interruptible system call. // The saved state is used to restore the thread to
*** 456,477 **** int os::active_processor_count() { int online_cpus = sysconf(_SC_NPROCESSORS_ONLN); pid_t pid = getpid(); psetid_t pset = PS_NONE; ! // Are we running in a processor set? if (pset_bind(PS_QUERY, P_PID, pid, &pset) == 0) { - if (pset != PS_NONE) { uint_t pset_cpus; ! // Query number of cpus in processor set if (pset_info(pset, NULL, &pset_cpus, NULL) == 0) { assert(pset_cpus > 0 && pset_cpus <= online_cpus, "sanity check"); _processors_online = pset_cpus; return pset_cpus; } } - } // Otherwise return number of online cpus return online_cpus; } static bool find_processors_in_pset(psetid_t pset, --- 467,486 ---- int os::active_processor_count() { int online_cpus = sysconf(_SC_NPROCESSORS_ONLN); pid_t pid = getpid(); psetid_t pset = PS_NONE; ! // Are we running in a processor set or is there any processor set around? if (pset_bind(PS_QUERY, P_PID, pid, &pset) == 0) { uint_t pset_cpus; ! // Query the number of cpus available to us. if (pset_info(pset, NULL, &pset_cpus, NULL) == 0) { assert(pset_cpus > 0 && pset_cpus <= online_cpus, "sanity check"); _processors_online = pset_cpus; return pset_cpus; } } // Otherwise return number of online cpus return online_cpus; } static bool find_processors_in_pset(psetid_t pset,
*** 1634,1653 **** } // gethrtime can move backwards if read from one cpu and then a different cpu // getTimeNanos is guaranteed to not move backward on Solaris inline hrtime_t getTimeNanos() { if (VM_Version::supports_cx8()) { ! bool retry = false; ! hrtime_t newtime = gethrtime(); ! hrtime_t oldmaxtime = max_hrtime; ! hrtime_t retmaxtime = oldmaxtime; ! while ((newtime > retmaxtime) && (retry == false || retmaxtime != oldmaxtime)) { ! oldmaxtime = retmaxtime; ! retmaxtime = Atomic::cmpxchg(newtime, (volatile jlong *)&max_hrtime, oldmaxtime); ! retry = true; ! } ! return (newtime > retmaxtime) ? newtime : retmaxtime; } else { return oldgetTimeNanos(); } } --- 1643,1670 ---- } // gethrtime can move backwards if read from one cpu and then a different cpu // getTimeNanos is guaranteed to not move backward on Solaris inline hrtime_t getTimeNanos() { if (VM_Version::supports_cx8()) { ! const hrtime_t now = gethrtime(); ! const hrtime_t prev = max_hrtime; ! if (now <= prev) return prev; // same or retrograde time; ! const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev); ! assert(obsv >= prev, "invariant"); // Monotonicity ! // If the CAS succeeded then we're done and return "now". ! // If the CAS failed and the observed value "obs" is >= now then ! // we should return "obs". If the CAS failed and now > obs > 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 obs. 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 obs 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 obs and now. ! // Avoiding excessive CAS operations to hot RW locations is critical. ! // See http://blogs.sun.com/dave/entry/cas_and_cache_trivia_invalidate ! return (prev == obsv) ? now : obsv ; } else { return oldgetTimeNanos(); } }
*** 1685,1714 **** return true; } } // Used internally for comparisons only // getTimeMillis guaranteed to not move backwards on Solaris jlong getTimeMillis() { jlong nanotime = getTimeNanos(); return (jlong)(nanotime / NANOSECS_PER_MILLISECS); } ! jlong os::timeofday() { timeval t; if (gettimeofday( &t, NULL) == -1) ! fatal1("timeofday: gettimeofday (%s)", strerror(errno)); return jlong(t.tv_sec) * 1000 + jlong(t.tv_usec) / 1000; } - // Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis - // _use_global_time is only set if CacheTimeMillis is true - jlong os::javaTimeMillis() { - return (_use_global_time ? read_global_time() : timeofday()); - } - jlong os::javaTimeNanos() { return (jlong)getTimeNanos(); } void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { --- 1702,1760 ---- return true; } } + bool os::supports_vtime() { return true; } + + bool os::enable_vtime() { + int fd = open("/proc/self/ctl", O_WRONLY); + if (fd == -1) + return false; + + long cmd[] = { PCSET, PR_MSACCT }; + int res = write(fd, cmd, sizeof(long) * 2); + close(fd); + if (res != sizeof(long) * 2) + return false; + + return true; + } + + bool os::vtime_enabled() { + int fd = open("/proc/self/status", O_RDONLY); + if (fd == -1) + return false; + + pstatus_t status; + int res = read(fd, (void*) &status, sizeof(pstatus_t)); + close(fd); + if (res != sizeof(pstatus_t)) + return false; + + return status.pr_flags & PR_MSACCT; + } + + double os::elapsedVTime() { + return (double)gethrvtime() / (double)hrtime_hz; + } + // Used internally for comparisons only // getTimeMillis guaranteed to not move backwards on Solaris jlong getTimeMillis() { jlong nanotime = getTimeNanos(); return (jlong)(nanotime / NANOSECS_PER_MILLISECS); } ! // Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis ! jlong os::javaTimeMillis() { timeval t; if (gettimeofday( &t, NULL) == -1) ! fatal1("os::javaTimeMillis: gettimeofday (%s)", strerror(errno)); return jlong(t.tv_sec) * 1000 + jlong(t.tv_usec) / 1000; } jlong os::javaTimeNanos() { return (jlong)getTimeNanos(); } void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
*** 1782,1791 **** --- 1828,1885 ---- const char* os::dll_file_extension() { return ".so"; } const char* os::get_temp_directory() { return "/tmp/"; } + static bool file_exists(const char* filename) { + struct stat statbuf; + if (filename == NULL || strlen(filename) == 0) { + return false; + } + return os::stat(filename, &statbuf) == 0; + } + + void os::dll_build_name(char* buffer, size_t buflen, + const char* pname, const char* fname) { + // Copied from libhpi + const size_t pnamelen = pname ? strlen(pname) : 0; + + // Quietly truncate on buffer overflow. Should be an error. + if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { + *buffer = '\0'; + return; + } + + if (pnamelen == 0) { + snprintf(buffer, buflen, "lib%s.so", fname); + } else if (strchr(pname, *os::path_separator()) != NULL) { + int n; + char** pelements = split_path(pname, &n); + for (int i = 0 ; i < n ; i++) { + // really shouldn't be NULL but what the heck, check can't hurt + if (pelements[i] == NULL || strlen(pelements[i]) == 0) { + continue; // skip the empty path values + } + snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname); + if (file_exists(buffer)) { + break; + } + } + // release the storage + for (int i = 0 ; i < n ; i++) { + if (pelements[i] != NULL) { + FREE_C_HEAP_ARRAY(char, pelements[i]); + } + } + if (pelements != NULL) { + FREE_C_HEAP_ARRAY(char*, pelements); + } + } else { + snprintf(buffer, buflen, "%s/lib%s.so", pname, fname); + } + } + const char* os::get_current_directory(char *buf, int buflen) { return getcwd(buf, buflen); } // check if addr is inside libjvm[_g].so
*** 2033,2042 **** --- 2127,2139 ---- } return NULL; } + void* os::dll_lookup(void* handle, const char* name) { + return dlsym(handle, name); + } bool _print_ascii_file(const char* filename, outputStream* st) { int fd = open(filename, O_RDONLY); if (fd == -1) {
*** 2608,2618 **** assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned."); Solaris::set_mpss_range(addr, bytes, alignment_hint); } // Tell the OS to make the range local to the first-touching LWP ! void os::numa_make_local(char *addr, size_t bytes) { assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned."); if (madvise(addr, bytes, MADV_ACCESS_LWP) < 0) { debug_only(warning("MADV_ACCESS_LWP failed.")); } } --- 2705,2715 ---- assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned."); Solaris::set_mpss_range(addr, bytes, alignment_hint); } // Tell the OS to make the range local to the first-touching LWP ! void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned."); if (madvise(addr, bytes, MADV_ACCESS_LWP) < 0) { debug_only(warning("MADV_ACCESS_LWP failed.")); } }
*** 2646,2665 **** if (r == -1) { ids[0] = 0; return 1; } if (!r) { assert (bottom <= cur, "Sanity check"); ids[bottom++] = ids[cur]; } top += r; cur++; } return bottom; } ! // Detect the topology change. Typically happens during CPU pluggin-unplugging. bool os::numa_topology_changed() { int is_stale = Solaris::lgrp_cookie_stale(Solaris::lgrp_cookie()); if (is_stale != -1 && is_stale) { Solaris::lgrp_fini(Solaris::lgrp_cookie()); Solaris::lgrp_cookie_t c = Solaris::lgrp_init(Solaris::LGRP_VIEW_CALLER); --- 2743,2773 ---- if (r == -1) { ids[0] = 0; return 1; } if (!r) { + // That's a leaf node. assert (bottom <= cur, "Sanity check"); + // Check if the node has memory + if (Solaris::lgrp_resources(Solaris::lgrp_cookie(), ids[cur], + NULL, 0, LGRP_RSRC_MEM) > 0) { ids[bottom++] = ids[cur]; } + } top += r; cur++; } + if (bottom == 0) { + // Handle a situation, when the OS reports no memory available. + // Assume UMA architecture. + ids[0] = 0; + return 1; + } return bottom; } ! // Detect the topology change. Typically happens during CPU plugging-unplugging. bool os::numa_topology_changed() { int is_stale = Solaris::lgrp_cookie_stale(Solaris::lgrp_cookie()); if (is_stale != -1 && is_stale) { Solaris::lgrp_fini(Solaris::lgrp_cookie()); Solaris::lgrp_cookie_t c = Solaris::lgrp_init(Solaris::LGRP_VIEW_CALLER);
*** 2670,2684 **** return false; } // Get the group id of the current LWP. int os::numa_get_group_id() { ! int lgrp_id = os::Solaris::lgrp_home(P_LWPID, P_MYID); if (lgrp_id == -1) { return 0; } ! return lgrp_id; } // Request information about the page. bool os::get_page_info(char *start, page_info* info) { const uint_t info_types[] = { MEMINFO_VLGRP, MEMINFO_VPAGESIZE }; --- 2778,2801 ---- return false; } // Get the group id of the current LWP. int os::numa_get_group_id() { ! int lgrp_id = Solaris::lgrp_home(P_LWPID, P_MYID); if (lgrp_id == -1) { return 0; } ! const int size = os::numa_get_groups_num(); ! int *ids = (int*)alloca(size * sizeof(int)); ! ! // Get the ids of all lgroups with memory; r is the count. ! int r = Solaris::lgrp_resources(Solaris::lgrp_cookie(), lgrp_id, ! (Solaris::lgrp_id_t*)ids, size, LGRP_RSRC_MEM); ! if (r <= 0) { ! return 0; ! } ! return ids[os::random() % r]; } // Request information about the page. bool os::get_page_info(char *start, page_info* info) { const uint_t info_types[] = { MEMINFO_VLGRP, MEMINFO_VPAGESIZE };
*** 2786,2817 **** return NULL; } return b; } ! char* ! os::reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) { ! char* addr = NULL; ! int flags; ! flags = MAP_PRIVATE | MAP_NORESERVE; ! if (requested_addr != NULL) { flags |= MAP_FIXED; ! addr = requested_addr; ! } else if (has_map_align && alignment_hint > (size_t) vm_page_size()) { flags |= MAP_ALIGN; addr = (char*) alignment_hint; } // Map 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. ! addr = Solaris::mmap_chunk(addr, bytes, flags, PROT_NONE); guarantee(requested_addr == NULL || requested_addr == addr, "OS failed to return requested mmap address."); - return addr; } // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else). --- 2903,2936 ---- return NULL; } return b; } ! char* os::Solaris::anon_mmap(char* requested_addr, size_t bytes, size_t alignment_hint, bool fixed) { ! char* addr = requested_addr; ! int flags = MAP_PRIVATE | MAP_NORESERVE; ! ! assert(!(fixed && (alignment_hint > 0)), "alignment hint meaningless with fixed mmap"); ! if (fixed) { flags |= MAP_FIXED; ! } else if (has_map_align && (alignment_hint > (size_t) vm_page_size())) { flags |= MAP_ALIGN; addr = (char*) alignment_hint; } // Map 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. ! return mmap_chunk(addr, bytes, flags, PROT_NONE); ! } ! ! char* os::reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) { ! char* addr = Solaris::anon_mmap(requested_addr, bytes, alignment_hint, (requested_addr != NULL)); guarantee(requested_addr == NULL || requested_addr == addr, "OS failed to return requested mmap address."); return addr; } // Reserve memory at an arbitrary address, only if that area is // available (and not reserved for something else).
*** 2833,2842 **** --- 2952,2986 ---- // 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"); + // Since snv_84, Solaris attempts to honor the address hint - see 5003415. + // Give it a try, if the kernel honors the hint we can return immediately. + char* addr = Solaris::anon_mmap(requested_addr, bytes, 0, false); + volatile int err = errno; + if (addr == requested_addr) { + return addr; + } else if (addr != NULL) { + unmap_memory(addr, bytes); + } + + if (PrintMiscellaneous && Verbose) { + char buf[256]; + buf[0] = '\0'; + if (addr == NULL) { + jio_snprintf(buf, sizeof(buf), ": %s", strerror(err)); + } + warning("attempt_reserve_memory_at: couldn't reserve %d bytes at " + PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT + "%s", bytes, requested_addr, addr, buf); + } + + // Address hint method didn't work. Fall back to the old method. + // In theory, once SNV becomes our oldest supported platform, this + // code will no longer be needed. + // // Repeatedly allocate blocks until the block is allocated at the // right spot. Give up after max_tries. int i; for (i = 0; i < max_tries; ++i) { base[i] = reserve_memory(bytes);
*** 2923,2947 **** "addr must be page aligned"); int retVal = mprotect(addr, bytes, prot); return retVal == 0; } ! // Protect memory (make it read-only. (Used to pass readonly pages through // JNI GetArray<type>Elements with empty arrays.) ! bool os::protect_memory(char* addr, size_t bytes) { ! return solaris_mprotect(addr, bytes, PROT_READ); } // guard_memory and unguard_memory only happens within stack guard pages. // Since ISM pertains only to the heap, guard and unguard memory should not /// happen with an ISM region. bool os::guard_memory(char* addr, size_t bytes) { return solaris_mprotect(addr, bytes, PROT_NONE); } bool os::unguard_memory(char* addr, size_t bytes) { ! return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE|PROT_EXEC); } // Large page support // UseLargePages is the master flag to enable/disable large page memory. --- 3067,3104 ---- "addr must be page aligned"); int retVal = mprotect(addr, bytes, prot); return retVal == 0; } ! // Protect memory (Used to pass readonly pages through // JNI GetArray<type>Elements with empty arrays.) ! // Also, used for serialization page and for compressed oops null pointer ! // checking. ! bool os::protect_memory(char* addr, size_t bytes, ProtType prot, ! bool is_committed) { ! unsigned int p = 0; ! switch (prot) { ! case MEM_PROT_NONE: p = PROT_NONE; break; ! case MEM_PROT_READ: p = PROT_READ; break; ! case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break; ! case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break; ! default: ! ShouldNotReachHere(); ! } ! // is_committed is unused. ! return solaris_mprotect(addr, bytes, p); } // guard_memory and unguard_memory only happens within stack guard pages. // Since ISM pertains only to the heap, guard and unguard memory should not /// happen with an ISM region. bool os::guard_memory(char* addr, size_t bytes) { return solaris_mprotect(addr, bytes, PROT_NONE); } bool os::unguard_memory(char* addr, size_t bytes) { ! return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE); } // Large page support // UseLargePages is the master flag to enable/disable large page memory.
*** 3068,3077 **** --- 3225,3236 ---- UseISM = UseISM && Solaris::ism_sanity_check(warn_on_failure, &_large_page_size); if (UseISM) { // ISM disables MPSS to be compatible with old JDK behavior UseMPSS = false; + _page_sizes[0] = _large_page_size; + _page_sizes[1] = vm_page_size(); } UseMPSS = UseMPSS && Solaris::mpss_sanity_check(warn_on_failure, &_large_page_size);
*** 3157,3166 **** --- 3316,3329 ---- // the entire memory region must be allocated as shared memory. bool os::can_commit_large_page_memory() { return UseISM ? false : true; } + bool os::can_execute_large_page_memory() { + return UseISM ? false : true; + } + static int os_sleep(jlong millis, bool interruptible) { const jlong limit = INT_MAX; jlong prevtime; int res;
*** 3638,3648 **** } else if (ParmInfo.pc_cid == iaLimits.schedPolicy) { iaparms_t *iaInfo = (iaparms_t*)ParmInfo.pc_clparms; int maxClamped = MIN2(iaLimits.maxPrio, (int)iaInfo->ia_uprilim); iaInfo->ia_upri = scale_to_lwp_priority(iaLimits.minPrio, maxClamped, newPrio); iaInfo->ia_uprilim = IA_NOCHANGE; - iaInfo->ia_nice = IA_NOCHANGE; iaInfo->ia_mode = IA_NOCHANGE; if (ThreadPriorityVerbose) { tty->print_cr ("IA: [%d...%d] %d->%d\n", iaLimits.minPrio, maxClamped, newPrio, iaInfo->ia_upri); } --- 3801,3810 ----
*** 4326,4335 **** --- 4488,4498 ---- os::Solaris::lgrp_home_func_t os::Solaris::_lgrp_home; os::Solaris::lgrp_init_func_t os::Solaris::_lgrp_init; os::Solaris::lgrp_fini_func_t os::Solaris::_lgrp_fini; os::Solaris::lgrp_root_func_t os::Solaris::_lgrp_root; os::Solaris::lgrp_children_func_t os::Solaris::_lgrp_children; + os::Solaris::lgrp_resources_func_t os::Solaris::_lgrp_resources; os::Solaris::lgrp_nlgrps_func_t os::Solaris::_lgrp_nlgrps; os::Solaris::lgrp_cookie_stale_func_t os::Solaris::_lgrp_cookie_stale; os::Solaris::lgrp_cookie_t os::Solaris::_lgrp_cookie = 0; // (Static) wrapper for meminfo() call.
*** 4364,4428 **** // since setting native thread priorities is handled differently // when using this library. All threads created using T2 are bound // threads. Calling thr_setprio is meaningless in this case. // bool isT2_libthread() { - int i, rslt; static prheader_t * lwpArray = NULL; static int lwpSize = 0; static int lwpFile = -1; lwpstatus_t * that; - int aslwpcount; char lwpName [128]; bool isT2 = false; #define ADR(x) ((uintptr_t)(x)) #define LWPINDEX(ary,ix) ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1)))) ! aslwpcount = 0; ! lwpSize = 16*1024; ! lwpArray = ( prheader_t *)NEW_C_HEAP_ARRAY (char, lwpSize); ! lwpFile = open ("/proc/self/lstatus", O_RDONLY, 0); ! if (lwpArray == NULL) { ! if ( ThreadPriorityVerbose ) warning ("Couldn't allocate T2 Check array\n"); ! return(isT2); ! } if (lwpFile < 0) { ! if ( ThreadPriorityVerbose ) warning ("Couldn't open /proc/self/lstatus\n"); ! return(isT2); } for (;;) { lseek (lwpFile, 0, SEEK_SET); ! rslt = read (lwpFile, lwpArray, lwpSize); ! if ((lwpArray->pr_nent * lwpArray->pr_entsize) <= lwpSize) { break; } ! FREE_C_HEAP_ARRAY(char, lwpArray); ! lwpSize = lwpArray->pr_nent * lwpArray->pr_entsize; ! lwpArray = ( prheader_t *)NEW_C_HEAP_ARRAY (char, lwpSize); ! if (lwpArray == NULL) { ! if ( ThreadPriorityVerbose ) warning ("Couldn't allocate T2 Check array\n"); ! return(isT2); ! } ! } ! // We got a good snapshot - now iterate over the list. ! for (i = 0; i < lwpArray->pr_nent; i++ ) { that = LWPINDEX(lwpArray,i); if (that->pr_flags & PR_ASLWP) { aslwpcount++; } } ! if ( aslwpcount == 0 ) isT2 = true; FREE_C_HEAP_ARRAY(char, lwpArray); close (lwpFile); ! if ( ThreadPriorityVerbose ) { ! if ( isT2 ) tty->print_cr("We are running with a T2 libthread\n"); else tty->print_cr("We are not running with a T2 libthread\n"); } ! return (isT2); } void os::Solaris::libthread_init() { address func = (address)dlsym(RTLD_DEFAULT, "_thr_suspend_allmutators"); --- 4527,4582 ---- // since setting native thread priorities is handled differently // when using this library. All threads created using T2 are bound // threads. Calling thr_setprio is meaningless in this case. // bool isT2_libthread() { static prheader_t * lwpArray = NULL; static int lwpSize = 0; static int lwpFile = -1; lwpstatus_t * that; char lwpName [128]; bool isT2 = false; #define ADR(x) ((uintptr_t)(x)) #define LWPINDEX(ary,ix) ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1)))) ! lwpFile = open("/proc/self/lstatus", O_RDONLY, 0); if (lwpFile < 0) { ! if (ThreadPriorityVerbose) warning ("Couldn't open /proc/self/lstatus\n"); ! return false; } + lwpSize = 16*1024; for (;;) { lseek (lwpFile, 0, SEEK_SET); ! lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize); ! if (read(lwpFile, lwpArray, lwpSize) < 0) { ! if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n"); break; } ! if ((lwpArray->pr_nent * lwpArray->pr_entsize) <= lwpSize) { // We got a good snapshot - now iterate over the list. ! int aslwpcount = 0; ! for (int i = 0; i < lwpArray->pr_nent; i++ ) { that = LWPINDEX(lwpArray,i); if (that->pr_flags & PR_ASLWP) { aslwpcount++; } } ! if (aslwpcount == 0) isT2 = true; ! break; ! } ! lwpSize = lwpArray->pr_nent * lwpArray->pr_entsize; ! FREE_C_HEAP_ARRAY(char, lwpArray); // retry. ! } FREE_C_HEAP_ARRAY(char, lwpArray); close (lwpFile); ! if (ThreadPriorityVerbose) { ! if (isT2) tty->print_cr("We are running with a T2 libthread\n"); else tty->print_cr("We are not running with a T2 libthread\n"); } ! return isT2; } void os::Solaris::libthread_init() { address func = (address)dlsym(RTLD_DEFAULT, "_thr_suspend_allmutators");
*** 4529,4555 **** os::Solaris::set_cond_destroy(::cond_destroy); } } } ! void os::Solaris::liblgrp_init() { ! void *handle = dlopen("liblgrp.so", RTLD_LAZY); if (handle != NULL) { os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home"))); os::Solaris::set_lgrp_init(CAST_TO_FN_PTR(lgrp_init_func_t, dlsym(handle, "lgrp_init"))); os::Solaris::set_lgrp_fini(CAST_TO_FN_PTR(lgrp_fini_func_t, dlsym(handle, "lgrp_fini"))); os::Solaris::set_lgrp_root(CAST_TO_FN_PTR(lgrp_root_func_t, dlsym(handle, "lgrp_root"))); os::Solaris::set_lgrp_children(CAST_TO_FN_PTR(lgrp_children_func_t, dlsym(handle, "lgrp_children"))); os::Solaris::set_lgrp_nlgrps(CAST_TO_FN_PTR(lgrp_nlgrps_func_t, dlsym(handle, "lgrp_nlgrps"))); os::Solaris::set_lgrp_cookie_stale(CAST_TO_FN_PTR(lgrp_cookie_stale_func_t, dlsym(handle, "lgrp_cookie_stale"))); lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER); set_lgrp_cookie(c); ! } else { ! warning("your OS does not support NUMA"); } } void os::Solaris::misc_sym_init() { address func = (address)dlsym(RTLD_DEFAULT, "meminfo"); if(func == NULL) { --- 4683,4710 ---- os::Solaris::set_cond_destroy(::cond_destroy); } } } ! bool os::Solaris::liblgrp_init() { ! void *handle = dlopen("liblgrp.so.1", RTLD_LAZY); if (handle != NULL) { os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home"))); os::Solaris::set_lgrp_init(CAST_TO_FN_PTR(lgrp_init_func_t, dlsym(handle, "lgrp_init"))); os::Solaris::set_lgrp_fini(CAST_TO_FN_PTR(lgrp_fini_func_t, dlsym(handle, "lgrp_fini"))); os::Solaris::set_lgrp_root(CAST_TO_FN_PTR(lgrp_root_func_t, dlsym(handle, "lgrp_root"))); os::Solaris::set_lgrp_children(CAST_TO_FN_PTR(lgrp_children_func_t, dlsym(handle, "lgrp_children"))); + os::Solaris::set_lgrp_resources(CAST_TO_FN_PTR(lgrp_resources_func_t, dlsym(handle, "lgrp_resources"))); os::Solaris::set_lgrp_nlgrps(CAST_TO_FN_PTR(lgrp_nlgrps_func_t, dlsym(handle, "lgrp_nlgrps"))); os::Solaris::set_lgrp_cookie_stale(CAST_TO_FN_PTR(lgrp_cookie_stale_func_t, dlsym(handle, "lgrp_cookie_stale"))); lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER); set_lgrp_cookie(c); ! return true; } + return false; } void os::Solaris::misc_sym_init() { address func = (address)dlsym(RTLD_DEFAULT, "meminfo"); if(func == NULL) {
*** 4714,4726 **** // the yellow/red zones can be guarded. JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, vm_page_size())); Solaris::libthread_init(); if (UseNUMA) { ! Solaris::liblgrp_init(); } Solaris::misc_sym_init(); Solaris::signal_sets_init(); Solaris::init_signal_mem(); Solaris::install_signal_handlers(); --- 4869,4897 ---- // the yellow/red zones can be guarded. JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, vm_page_size())); Solaris::libthread_init(); + if (UseNUMA) { ! if (!Solaris::liblgrp_init()) { ! UseNUMA = false; ! } else { ! size_t lgrp_limit = os::numa_get_groups_num(); ! int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit); ! size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit); ! FREE_C_HEAP_ARRAY(int, lgrp_ids); ! if (lgrp_num < 2) { ! // There's only one locality group, disable NUMA. ! UseNUMA = false; ! } } + if (!UseNUMA && ForceNUMA) { + UseNUMA = true; + } + } + Solaris::misc_sym_init(); Solaris::signal_sets_init(); Solaris::init_signal_mem(); Solaris::install_signal_handlers();