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();