/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*
*/
// no precompiled headers
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm_solaris.h"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "mutex_solaris.inline.hpp"
#include "oops/oop.inline.hpp"
#include "os_share_solaris.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
#include "runtime/globals.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/osThread.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/statSampler.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/threadCritical.hpp"
#include "services/attachListener.hpp"
#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
#include "thread_solaris.inline.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/vmError.hpp"
#ifdef TARGET_ARCH_x86
# include "assembler_x86.inline.hpp"
# include "nativeInst_x86.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "assembler_sparc.inline.hpp"
# include "nativeInst_sparc.hpp"
#endif
// put OS-includes here
# include <dlfcn.h>
# include <errno.h>
# include <exception>
# include <link.h>
# include <poll.h>
# include <pthread.h>
# include <pwd.h>
# include <schedctl.h>
# include <setjmp.h>
# include <signal.h>
# include <stdio.h>
# include <alloca.h>
# include <sys/processor.h>
# include <sys/resource.h>
# include <sys/systeminfo.h>
# include <thread.h>
# include <unistd.h>
# include <sys/priocntl.h>
# include <sys/rtpriocntl.h>
# include <sys/tspriocntl.h>
# include <sys/iapriocntl.h>
# include <sys/fxpriocntl.h>
# include <string.h>
# include <stdio.h>
// for timer info max values which include all bits
#ifdef _GNU_SOURCE
// See bug #6514594
#endif //_GNU_SOURCE
/*
MPSS Changes Start.
The JVM binary needs to be built and run on pre-Solaris 9
systems, but the constants needed by MPSS are only in Solaris 9
header files. They are textually replicated here to allow
building on earlier systems. Once building on Solaris 8 is
no longer a requirement, these #defines can be replaced by ordinary
system .h inclusion.
In earlier versions of the JDK and Solaris, we used ISM for large pages.
But ISM requires shared memory to achieve this and thus has many caveats.
MPSS is a fully transparent and is a cleaner way to get large pages.
Although we still require keeping ISM for backward compatiblitiy as well as
giving the opportunity to use large pages on older systems it is
recommended that MPSS be used for Solaris 9 and above.
*/
#ifndef MC_HAT_ADVISE
struct memcntl_mha {
};
#endif
// MPSS Changes End.
// Here are some liblgrp types from sys/lgrp_user.h to be able to
// compile on older systems without this header file.
#ifndef MADV_ACCESS_LWP
#endif
#ifndef MADV_ACCESS_MANY
#endif
#ifndef LGRP_RSRC_CPU
#endif
#ifndef LGRP_RSRC_MEM
#endif
#ifndef MAX_MEMINFO_CNT
/*
* info_req request type definitions for meminfo
* request types starting with MEMINFO_V are used for Virtual addresses
* and should not be mixed with MEMINFO_PLGRP which is targeted for Physical
* addresses
*/
/* maximum number of addresses meminfo() can process at a time */
/* maximum number of request types */
#endif
// see thr_setprio(3T) for the basis of these numbers
#define MinimumPriority 0
// Values for ThreadPriorityPolicy == 1
-99999, 0, 16, 32, 48, 64,
80, 96, 112, 124, 127, 127 };
// System parameters used internally
// Track if we have called enable_extended_FILE_stdio (on Solaris 10u4+)
static bool enabled_extended_FILE_stdio = false;
// For diagnostics to print a message once. see run_periodic_checks
static bool check_addr0_done = false;
static bool check_signals = true;
// "default" initializers for missing libc APIs
extern "C" {
static int lwp_mutex_init(mutex_t *mx, int scope, void *arg) { memset(mx, 0, sizeof(mutex_t)); return 0; }
static int lwp_cond_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; }
}
// "default" initializers for pthread-based synchronization
extern "C" {
static int pthread_mutex_default_init(mutex_t *mx, int scope, void *arg) { memset(mx, 0, sizeof(mutex_t)); return 0; }
static int pthread_cond_default_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; }
}
// Thread Local Storage
// This is common to all Solaris platforms so it is defined here,
// in this common file.
// The declarations are in the os_cpu threadLS*.hpp files.
//
// Static member initialization for TLS
#ifndef PRODUCT
}
#endif // PRODUCT
int index) {
"sp must be inside of selected thread stack");
}
return thread;
}
// Store the new value before updating the cache to prevent a race
// between get_thread_via_cache_slowly() and this store operation.
// Update thread cache with new thread if setting on thread create,
// or NO_CACHED_THREAD (zeroed) thread if resetting thread on exit.
}
for (int i = 0; i < _pd_cache_size; i++) {
}
}
// Invalidate all the caches (happens to be the same as pd_init).
// END Thread Local Storage
// 4759953: Compensate for ridiculous stack size.
}
// 4812466: Make sure size doesn't allow the stack to wrap the address space.
}
return size;
}
return st;
}
int r = thr_main() ;
bool is_primordial_thread = r;
// Workaround 4352906, avoid calls to thr_stksegment by
// thr_main after the first one (it looks like we trash
// some data, causing the value for ss_sp to be incorrect).
if (is_primordial_thread) {
// cache initial value of stack base
}
} else {
}
}
int r = thr_main() ;
if(!r) {
} else {
}
// base may not be page aligned
}
}
// 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
// its former state whether or not an interrupt is received.
// Used by classloader os::read
// os::restartable_read calls skip this layer and stay in _thread_in_native
}
// Version of setup_interruptible() for threads that are already in
// _thread_blocked. Used by os_sleep().
}
return thread;
}
typedef int (*enable_extended_FILE_stdio_t)(int, int);
if (!UseExtendedFileIO) {
return;
}
"enable_extended_FILE_stdio");
if (enabler) {
}
}
#ifdef ASSERT
return thread;
}
}
#endif
// cleanup_interruptible reverses the effects of setup_interruptible
// setup_interruptible_already_blocked() does not need any cleanup.
ThreadStateTransition::transition(thread, _thread_blocked, osthread->saved_interrupt_thread_state());
}
// I/O interruption related counters called in _INTERRUPTIBLE
}
}
static int _processors_online = 0;
return Solaris::available_memory();
}
}
return Solaris::physical_memory();
}
#ifdef _LP64
return size;
#else
if (!is_allocatable(result)) {
// Memory allocations will be aligned but the alignment
// is not known at this point. Alignments will
// be at most to LargePageSizeInBytes. Protect
// allocations from alignments up to illegal
// values. If at this point 2G is illegal.
}
return result;
#endif
}
const int LOCK_FREE = 0;
}
// Are we running in a processor set or is there any processor set around?
// Query the number of cpus available to us.
return pset_cpus;
}
}
// Otherwise return number of online cpus
return online_cpus;
}
bool result = false;
// Find the number of processors in the processor set.
// Make up an array to hold their ids.
// Fill in the array with their processor ids.
result = true;
}
}
return result;
}
// Callers of find_processors_online() must tolerate imprecise results --
// the system configuration can change asynchronously because of DR
// or explicit psradm operations.
//
// We also need to take care that the loop (below) terminates as the
// number of processors online can change between the _SC_NPROCESSORS_ONLN
// request and the loop that builds the list of processor ids. Unfortunately
// there's no reliable way to determine the maximum valid processor id,
// so we use a manifest constant, MAX_PROCESSOR_ID, instead. See p_online
// man pages, which claim the processor id set is "sparse, but
// not too sparse". MAX_PROCESSOR_ID is used to ensure that we eventually
// exit the loop.
//
// In the future we'll be able to use sysconf(_SC_CPUID_MAX), but that's
// not available on S8.0.
// Find the number of processors online.
// Make up an array to hold their ids.
// Processors need not be numbered consecutively.
long found = 0;
// NB, PI_NOINTR processors are effectively online ...
found += 1;
}
}
next += 1;
}
// The loop above didn't identify the expected number of processors.
// We could always retry the operation, calling sysconf(_SC_NPROCESSORS_ONLN)
// and re-running the loop, above, but there's no guarantee of progress
// if the system configuration is in flux. Instead, we just return what
// we've got. Note that in the worst case find_processors_online() could
// return an empty set. (As a fall-back in the case of the empty set we
// could just return the ID of the current processor).
}
return true;
}
// We assume we can assign processorid_t's to uint's.
"can't convert processorid_t to uint");
// Quick check to see if we won't succeed.
if (id_length < distribution_length) {
return false;
}
// Assign processor ids to the distribution.
// Try to shuffle processors to distribute work across boards,
// assuming 4 processors per board.
// Find the maximum processor id.
}
// The next id, to limit loops.
// Make up markers for available processors.
available_id[c] = false;
}
available_id[id_array[a]] = true;
}
// Step by "boards", then by "slot", copying to "assigned".
// NEEDS_CLEANUP: The assignment of processors should be stateful,
// remembering which processors have been assigned by
// previous calls, etc., so as to distribute several
// independent calls of this method. What we'd like is
// It would be nice to have an API that let us ask
// how many processes are bound to a processor,
// but we don't have that, either.
// In the short term, "board" is static so that
// subsequent distributions don't all start at board 0.
// Until we've found enough processors ....
while (assigned < distribution_length) {
// ... find the next available processor in the board.
available_id[try_id] = false;
assigned += 1;
break;
}
}
board += 1;
board = 0;
}
}
if (available_id != NULL) {
}
return true;
}
// Not yet implemented.
return;
}
bool result = false;
// Find the processor id's of all the available CPUs.
// There are some races between querying information and using it,
// since processor sets can change dynamically.
// Are we running in a processor set?
} else {
}
if (result == true) {
} else {
result = false;
}
}
}
return result;
}
// We assume that a processorid_t can be stored in a uint.
"can't convert uint to processorid_t");
int bind_result =
P_MYID, // bind current LWP.
NULL); // don't return old binding.
return (bind_result == 0);
}
return false;
}
return true;
}
// Return true if user is running as root.
static bool init = false;
static bool privileges = false;
if (!init) {
init = true;
}
return privileges;
}
// The next steps are taken in the product version:
//
// Obtain the JAVA_HOME value from the location of libjvm[_g].so.
// This library should be located at:
//
// assume libjvm[_g].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:
//
// instead of exit check for $JAVA_HOME environment variable.
//
// it looks like libjvm[_g].so is installed there
//
// Otherwise exit.
//
// Important note: if the location of libjvm.so changes this
// code needs to be changed accordingly.
// The next few definitions allow the code to be verbatim:
{
/* sysclasspath, java_home, dll_dir */
{
char *home_path;
char *dll_path;
char *pslash;
// Found the full path to libjvm.so.
// Now cut the path to <java_home>/jre if we can.
return;
}
}
return;
return;
}
/*
* Where to look for native libraries
*/
{
// Use dlinfo() to determine the correct java.library.path.
//
// If we're launched by the Java launcher, and the user
// does not set java.library.path explicitly on the commandline,
// the Java launcher sets LD_LIBRARY_PATH for us and unsets
// LD_LIBRARY_PATH_32 and LD_LIBRARY_PATH_64. In this case
// dlinfo returns LD_LIBRARY_PATH + crle settings (including
//
// If the user does set java.library.path, it completely
// overwrites this setting, and always has.
//
// If we're not launched by the Java launcher, we may
// settings. Again, dlinfo does exactly what we want.
char* library_path;
char *common_path;
int i;
// determine search path count and required buffer size
}
// allocate new buffer and initialize
"init_system_properties_values info");
}
// obtain search path information
}
// Note: Due to a legacy implementation, most of the library path
// is set in the launcher. This was to accomodate linking restrictions
// on legacy Solaris 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
// Determine the actual CPU architecture.
#ifdef _LP64
// If we are a 64-bit vm, perform the following translations:
// sparc -> sparcv9
// i386 -> amd64
#endif
// Construct the invariant part of ld_library_path. Note that the
// space for the colon and the trailing null are provided by the
// nulls included by the sizeof operator.
if (common_path == NULL) {
"init_system_properties_values common_path");
}
// struct size is more than sufficient for the path components obtained
// through the dlinfo() call, so only add additional space for the path
// components explicitly added here.
if (library_path == NULL) {
"init_system_properties_values library_path");
}
library_path[0] = '\0';
// Construct the desired Java library path from the linker's library
// search path.
//
// For compatibility, it is optimal that we insert the additional path
// components specific to the Java VM after those components specified
// in LD_LIBRARY_PATH (if any) but before those added by the ld.so
// infrastructure.
} else {
int inserted = 0;
inserted = 1;
}
}
// eliminate trailing path separator
}
// happens before argument parsing - can't use a trace flag
// tty->print_raw("init_system_properties_values: native lib path: ");
// tty->print_raw_cr(library_path);
// callee copies into its own buffer
}
/*
* 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).
*/
{
sizeof(EXTENSIONS_DIR) + sizeof(COMMON_DIR) +
sizeof(EXTENSIONS_DIR));
Arguments::get_java_home());
}
/* Endorsed standards default directory. */
{
}
}
}
}
{
return true;
return true;
return true;
return true;
}
return false;
}
return false;
}
// use debugger to set breakpoint here
}
// Thread start routine for all new Java threads
// Try to randomize the cache line index of hot stack frames.
// This helps when threads of the same stack traces evict each other's
// cache lines. The threads can be either from the same JVM instance, or
// from different JVM instances. The benefit is especially true for
// processors with hyperthreading technology.
static int counter = 0;
int prio;
if (UseNUMA) {
if (lgrp_id != -1) {
}
}
// If the creator called set priority before we started,
// we need to call set_native_priority now that we have an lwp.
// We used to get the priority from thr_getprio (we called
// thr_setprio way back in create_thread) and pass it to
// set_native_priority, but Solaris scales the priority
// in java_to_os_priority, so when we read it back here,
// we pass trash to set_native_priority instead of what's
// in java_to_os_priority. So we save the native priority
// in the osThread and recall it here.
if ( UseThreadPriorities ) {
if (ThreadPriorityVerbose) {
INTPTR_FORMAT ", setting priority: %d\n",
}
}
} else if (ThreadPriorityVerbose) {
warning("Can't set priority in _start routine, thread id hasn't been set\n");
}
// initialize signal mask for this thread
// One less thread is executing
// When the VMThread gets here, the main thread may have already exited
// which frees the CodeHeap containing the Atomic::dec code
}
if (UseDetachedThreads) {
}
return NULL;
}
// Allocate the OSThread object
// Store info on the Solaris thread into the OSThread
if (UseNUMA) {
if (lgrp_id != -1) {
}
}
if ( ThreadPriorityVerbose ) {
}
// Initial thread state is INITIALIZED, not SUSPENDED
return osthread;
}
//Save caller's signal mask
if (!ReduceSignalUsage) {
if (thread->is_VM_thread()) {
// Only the VM thread handles BREAK_SIGNAL ...
} else {
// ... all other threads block BREAK_SIGNAL
}
}
}
#ifdef ASSERT
#endif
return false;
}
// Initial thread state is RUNNABLE
// initialize signal mask for this thread
// and save the caller's signal mask
return true;
}
#ifdef ASSERT
#endif
if (_starting_thread == NULL) {
if (_starting_thread == NULL) {
return false;
}
}
// The primodial thread is runnable from the start
// initialize signal mask for this thread
// and save the caller's signal mask
return true;
}
// _T2_libthread is true if we believe we are running with the newer
// SunSoft lwp/libthread.so (2.8 patch, 2.9 default)
// Allocate the OSThread object
return false;
}
if ( ThreadPriorityVerbose ) {
char *thrtyp;
switch ( thr_type ) {
case vm_thread:
thrtyp = (char *)"vm";
break;
case cgc_thread:
thrtyp = (char *)"cgc";
break;
case pgc_thread:
thrtyp = (char *)"pgc";
break;
case java_thread:
thrtyp = (char *)"java";
break;
case compiler_thread:
thrtyp = (char *)"compiler";
break;
case watcher_thread:
thrtyp = (char *)"watcher";
break;
default:
thrtyp = (char *)"unknown";
break;
}
}
// Calculate stack size if it's not specified by caller.
if (stack_size == 0) {
// The default stack size 1M (2M for LP64).
switch (thr_type) {
case os::java_thread:
// Java threads use ThreadStackSize which default value can be changed with the flag -Xss
break;
case os::compiler_thread:
if (CompilerThreadStackSize > 0) {
break;
} // else fall through:
// use VMThreadStackSize if CompilerThreadStackSize is not defined
case os::pgc_thread:
case os::cgc_thread:
case os::watcher_thread:
break;
}
}
// Initial state is ALLOCATED but not INITIALIZED
// We got lots of threads. Check if we still have some address space left.
// Need to be at least 5Mb of unreserved address space. We do check by
// trying to reserve some.
delete osthread;
return false;
} else {
// Release the memory again
}
}
// Setup osthread because the child thread may need it.
// Create the Solaris thread
// explicit THR_BOUND for T2_libthread case in case
// that assumption is not accurate, but our alternate signal stack
// handling is based on it which must have bound threads
(thr_type == cgc_thread) ||
(thr_type == pgc_thread) ||
THR_BOUND : 0);
int status;
//
// On multiprocessors systems, libthread sometimes under-provisions our
// process with LWPs. On a 30-way systems, for instance, we could have
// 50 user-level threads in ready state and only 2 or 3 LWPs assigned
// to our process. This can result in under utilization of PEs.
// I suspect the problem is related to libthread's LWP
// pool management and to the kernel's SIGBLOCKING "last LWP parked"
// upcall policy.
//
// The following code is palliative -- it attempts to ensure that our
// process has sufficient LWPs to take advantage of multiple PEs.
// Proper long-term cures include using user-level threads bound to LWPs
// (THR_BOUND) or using LWP-based synchronization. Note that there is a
// slight timing window with respect to sampling _os_thread_count, but
// the race is benign. Also, we should periodically recompute
// _processors_online as the min of SC_NPROCESSORS_ONLN and the
// the number of PEs in our partition. You might be tempted to use
// THR_NEW_LWP here, but I'd recommend against it as that could
// result in undesirable growth of the libthread's LWP pool.
// The fix below isn't sufficient; for instance, it doesn't take into count
// LWPs parked on IO. It does, however, help certain CPU-bound benchmarks.
//
// Some pathologies this scheme doesn't handle:
// * Threads can block, releasing the LWPs. The LWPs can age out.
// When a large number of threads become ready again there aren't
// enough LWPs available to service them. This can occur when the
// number of ready threads oscillates.
//
// Finally, we should call thr_setconcurrency() periodically to refresh
// the LWP pool and thwart the LWP age-out mechanism.
// The "+3" term provides a little slop -- we want to slightly overprovision.
}
}
// Although this doesn't hurt, we should warn of undefined behavior
// when using unbound T1 threads with schedctl(). This should never
// happen, as the compiler and VM threads are always created bound
if ((VMThreadHintNoPreempt || CompilerThreadHintNoPreempt) &&
}
);
// Mark that we don't have an lwp or thread id yet.
// In case we attempt to set the priority before the thread starts.
if (status != 0) {
perror("os::create_thread");
}
// Need to clean up stuff we've allocated so far
delete osthread;
return false;
}
// Store info on the Solaris thread into the OSThread
// Remember that we created this thread so we can set priority on it
// Set the default thread priority. If using bound threads, setting
// lwp priority will be delayed until thread start.
DefaultThreadPriority == -1 ?
// Initial thread state is INITIALIZED, not SUSPENDED
// The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain
return true;
}
/* defined for >= Solaris 10. This allows builds on earlier versions
* of Solaris to take advantage of the newly reserved Solaris JVM signals
* With SIGJVM1, SIGJVM2, INTERRUPT_SIGNAL is SIGJVM1, ASYNC_SIGNAL is SIGJVM2
* and -XX:+UseAltSigs does nothing since these should have no conflict
*/
#if !defined(SIGJVM1)
#endif
debug_only(static bool signal_sets_initialized = false);
return true;
else
return false;
}
// Note: SIGRTMIN is a macro that calls sysconf() so it will
// dynamically detect SIGRTMIN value for the system at runtime, not buildtime
static bool isJVM1available() {
}
// Should also have an assertion stating we are still single-threaded.
// Fill in signals that are necessarily unblocked for all threads in
// the VM. Currently, we unblock the following signals:
// SHUTDOWN{1,2,3}_SIGNAL: for shutdown hooks support (unless over-ridden
// by -Xrs (=ReduceSignalUsage));
// BREAK_SIGNAL which is unblocked only by the VM thread and blocked by all
// other threads. The "ReduceSignalUsage" boolean tells us not to alter
// the dispositions or masks wrt these signals.
// Programs embedding the VM that want to use the above signals for their
// own purposes must, at this time, use the "-Xrs" option to prevent
// interference with shutdown hooks and BREAK_SIGNAL thread dumping.
// (See bug 4345157, and other related bugs).
// In reality, though, unblocking these signals is really a nop, since
// these signals are not blocked by default.
if (isJVM1available) {
} else if (UseAltSigs) {
} else {
}
if (!ReduceSignalUsage) {
}
}
}
}
// Fill in signals that are blocked by all but the VM thread.
if (!ReduceSignalUsage)
debug_only(signal_sets_initialized = true);
// For diagnostics only used in run_periodic_checks
}
// These are signals that are unblocked while a thread is running Java.
// (For some reason, they get blocked by default.)
return &unblocked_sigs;
}
// These are the signals that are blocked while a (non-VM) thread is
// running Java. Only the VM thread handles these signals.
return &vm_sigs;
}
// These are signals that are blocked during cond_wait to allow debugger in
return &allowdebug_blocked_sigs;
}
void _handle_uncaught_cxx_exception() {
}
// First crack at OS-specific initialization, from inside the new thread.
int r = thr_main() ;
if (r) {
if (Arguments::created_by_java_launcher()) {
// Use 2MB to allow for Solaris 7 64 bit mode.
// There are rare cases when we may have already used more than
// the basic stack size allotment before this method is invoked.
// Attempt to allow for a normally sized java_stack.
} else {
// 6269555: If we were not created by a Java launcher, i.e. if we are
// running embedded in a native application, treat the primordial thread
// as much like a native attached thread as possible. This means using
// the current stack size from thr_stksegment(), unless it is too large
// to reliably setup guard pages. A reasonable max size is 8MB.
// This should never happen, but just in case....
}
)
"Stack size of %d Kb exceeds current limit of %d Kb.\n"
"(Stack sizes are rounded up to a multiple of the system page size.)\n"
"See limit(1) to increase the stack size limit.",
vm_exit(1);
}
"Attempt to map more stack than was allocated");
}
// 5/22/01: Right now alternate signal stacks do not handle
// throwing stack overflow exceptions, see bug 4463178
// Until a fix is found for this, T2 will NOT imply alternate signal
// stacks.
// If using T2 libthread threads, install an alternate signal stack.
// Because alternate stacks associate with LWPs on Solaris,
// see sigaltstack(2), if using UNBOUND threads, or if UseBoundThreads
// we prefer to explicitly stack bang.
// If not using T2 libthread, but using UseBoundThreads any threads
// (primordial thread, jni_attachCurrentThread) we do not create,
// probably are not bound, therefore they can not have an alternate
// signal stack. Since our stack banging code is generated and
// is shared across threads, all threads must be bound to allow
// using alternate signal stacks. The alternative is to interpose
// on _lwp_create to associate an alt sig stack with each LWP,
// and this could be a problem when the JVM is embedded.
// We would prefer to use alternate signal stacks with T2
// Since there is currently no accurate way to detect T2
// we do not. Assuming T2 when running T1 causes sig 11s or assertions
// on installing alternate signal stacks
// 05/09/03: removed alternate signal stack support for Solaris
// The alternate signal stack mechanism is no longer needed to
// handle stack overflow. This is now handled by allocating
// guard pages (red zone) and stackbanging.
// Initially the alternate signal stack mechanism was removed because
// it did not work with T1 llibthread. Alternate
// signal stacks MUST have all threads bound to lwps. Applications
// can create their own threads and attach them without their being
// bound under T1. This is frequently the case for the primordial thread.
// If we were ever to reenable this mechanism we would need to
// use the dynamic check for T2 libthread.
}
// Free Solaris resources related to the OSThread
// We are told to free resources of the argument thread,
// but we can only really operate on the current thread.
// The main thread must take the VMThread down synchronously
// before the main thread exits and frees up CodeHeap
// Restore caller's signal mask
}
delete osthread;
}
}
}
}
// %%% in Win32 this allocates a memory segment pointed to by a
// register. Dan Stein can implement a similar feature in
// Solaris. Alternatively, the VM can do the same thing
// explicitly: malloc some storage and keep the pointer in a
// register (which is part of the thread's context) (or keep it
// in TLS).
// %%% In current versions of Solaris, thr_self and TSD can
// be accessed via short sequences of displaced indirections.
// The value of thr_self is available as %g7(36).
// The value of thr_getspecific(k) is stored in %g7(12)(4)(k*4-4),
// assuming that the current thread already has a value bound to k.
// It may be worth experimenting with such access patterns,
// and later having the parameters formally exported from a Solaris
// interface. I think, however, that it will be faster to
// maintain the invariant that %g2 always contains the
// JavaThread in Java code, and have stubs simply
// treat %g2 as a caller-save register, preserving it in a %lN.
return int(tk);
}
// %%% don't think we need anything here
// if ( pthread_key_delete((pthread_key_t) tk) )
// fatal("os::free_thread_local_storage: pthread_key_delete failed");
}
// small number - point is NO swap space available
// %%% this is used only in threadLocalStorage.cpp
} else {
}
} else {
}
}
// This function could be called before TLS is initialized, for example, when
// VM receives an async signal or when VM causes a fatal error during
// initialization. Return NULL if thr_getspecific() fails.
// %%% this is used only in threadLocalStorage.cpp
void* r = NULL;
}
// gethrtime can move backwards if read from one cpu and then a different cpu
// getTimeNanos is guaranteed to not move backward on Solaris
// local spinloop created as faster for a CAS on an int than
// a CAS on a 64bit jlong. Also Atomic::cmpxchg for jlong is not
// supported on sparc v8 or pre supports_cx8 intel boxes.
// oldgetTimeNanos for systems which do not support CAS on 64bit jlong
// i.e. sparc v8 and pre supports_cx8 (i486) intel boxes
for (;;) {
// grab lock for max_hrtime
if (newtime > max_hrtime) {
} else {
}
// release lock
return newtime;
}
}
// gethrtime can move backwards if read from one cpu and then a different cpu
// getTimeNanos is guaranteed to not move backward on Solaris
if (VM_Version::supports_cx8()) {
// Use atomic long load since 32-bit x86 uses 2 registers to keep long.
// 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.
} else {
return oldgetTimeNanos();
}
}
// Time since start-up in seconds to a fine granularity.
// Used by VMSelfDestructTimer and the MemProfiler.
}
}
return hrtime_hz;
}
// Return the real, user, and system times in seconds from an
// arbitrary fixed point in the past.
double* process_user_time,
double* process_system_time) {
return false;
} else {
// For consistency return the real time from getTimeNanos()
// converted to seconds.
return true;
}
}
if (fd == -1)
return false;
if (res != sizeof(long) * 2)
return false;
return true;
}
if (fd == -1)
return false;
return false;
}
return (double)gethrvtime() / (double)hrtime_hz;
}
// Used internally for comparisons only
// getTimeMillis guaranteed to not move backwards on Solaris
}
// Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis
timeval t;
}
return (jlong)getTimeNanos();
}
}
struct tm t;
localtime_r(&long_time, &t);
return buf;
}
// Note: os::shutdown() might be called very early during initialization, or
// called from signal handler. Before adding something to os::shutdown(), make
// sure it is async-safe and can handle partially initialized VM.
// allow PerfMemory to attempt cleanup of any persistent resources
// needs to remove object in file system
AttachListener::abort();
// flush buffered output, finish log files
// Check for abort hook
if (abort_hook != NULL) {
abort_hook();
}
}
// Note: os::abort() might be called very early during initialization, or
// called from signal handler. Before adding something to os::abort(), make
// sure it is async-safe and can handle partially initialized VM.
if (dump_core) {
#ifndef PRODUCT
#endif
::abort(); // dump core (for debugging)
}
::exit(1);
}
// Die immediately, no exit hook, no abort hook, no cleanup.
::abort(); // dump core (for debugging)
}
// unused
// DLL functions
// This must be hard coded because it's the system's temporary
// directory not the java application's temp directory, ala java.io.tmpdir.
return false;
}
}
// Quietly truncate on buffer overflow. Should be an error.
*buffer = '\0';
return;
}
if (pnamelen == 0) {
int n;
for (int i = 0 ; i < n ; i++) {
// really shouldn't be NULL but what the heck, check can't hurt
continue; // skip the empty path values
}
if (file_exists(buffer)) {
break;
}
}
// release the storage
for (int i = 0 ; i < n ; i++) {
}
}
}
} else {
}
}
}
// check if addr is inside libjvm[_g].so
if (libjvm_base_addr == NULL) {
}
}
return false;
}
// dladdr1_func was initialized in os::init()
if (dladdr1_func){
// yes, we have dladdr1
// Support for dladdr1 is checked at runtime; it may be
// available even if the vm is built on a machine that does
// not have dladdr1 support. Make sure there is a value for
// RTLD_DL_SYMENT.
#ifndef RTLD_DL_SYMENT
#endif
#ifdef _LP64
#else
#endif
RTLD_DL_SYMENT)) {
}
return true;
}
}
return true;
}
}
return false;
} else {
// no, only dladdr is available
}
return true;
return true;
}
}
return false;
}
}
return true;
} else {
return false;
}
}
// Prints the names and full paths of all opened dynamic libraries
// for current process
void *handle;
Link_map *p;
return;
}
return;
}
return;
}
}
}
// Loads .dll/.so and
// in case of error it checks if .dll/.so was built for the
// same architecture as Hotspot is running on
{
// Successful loading
return result;
}
// Read system error message into ebuf
// It may or may not be overwritten below
if (diag_msg_max_length==0) {
// No more space in ebuf for additional diagnostics message
return NULL;
}
if (file_descriptor < 0) {
// Can't open library, report dlerror() message
return NULL;
}
bool failed_to_read_elf_head=
(sizeof(elf_head)!=
::close(file_descriptor);
if (failed_to_read_elf_head) {
// file i/o error - report dlerror() msg
return NULL;
}
typedef struct {
} arch_t;
};
#if (defined IA32)
#elif (defined __powerpc64__)
#elif (defined __powerpc__)
#else
#endif
// Identify compatability class for VM's architecture and library's architecture
// Obtain string descriptions for architectures
for (unsigned int i=0 ; i < ARRAY_SIZE(arch_array) ; i++ ) {
running_arch_index = i;
}
}
}
"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;
}
return NULL;
}
::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: architecture word width mismatch)");
return NULL;
}
" (Possible cause: can't load %s-bit .so on a %s-bit platform)",
} else {
" (Possible cause: can't load this .so (machine code=0x%x) on a %s-bit platform)",
}
}
return NULL;
}
}
return -1;
}
}
if (fd == -1) {
return false;
}
int bytes;
}
return true;
}
}
}
}
}
}
else {
}
}
if (fd >= 0) {
prmap_t p;
if (p.pr_vaddr == 0x0) {
status = true;
}
}
}
return status;
}
// Nothing to do for now.
}
(void) check_addr0(st);
}
// but they're the same for all the solaris architectures that we support.
"ILL_ILLTRP", "ILL_PRVOPC", "ILL_PRVREG",
"ILL_COPROC", "ILL_BADSTK" };
"FPE_FLTOVF", "FPE_FLTUND", "FPE_FLTRES",
"FPE_FLTINV", "FPE_FLTSUB" };
} else {
}
assert(c > 0, "unexpected si_code");
case SIGILL:
break;
case SIGFPE:
break;
case SIGSEGV:
break;
case SIGBUS:
break;
default:
// no si_addr
}
" Mapped file inaccessible during execution, " \
}
}
}
// Moved from whole group, because we need them here for diagnostic
// prints.
static int Maxsignum = 0;
return ourSigFlags[sig];
}
}
int offset;
if (found) {
// skip directory names
} else {
}
return buf;
}
} else {
}
// May be, handler was resetted by VMError?
}
// Check: is it our handler?
// It is our signal handler
// check for flags
}
}
}
}
// Find the full path to the current module, libjvm.so or libjvm_g.so
// 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) {
return;
}
if (Arguments::created_by_gamma_launcher()) {
// Support for the gamma launcher. Typical value for buf is
// 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 fix
// up the path so it looks like libjvm.so is installed there (append a
for (--p; p > buf && *p != '/'; --p)
/* empty */ ;
}
// Look for JAVA_HOME in the environment.
char* jrelib_p;
int len;
#ifdef _LP64
}
#endif
// Check the current module name "libjvm.so" or "libjvm_g.so".
// determine if this is a legacy image or modules image
// modules image doesn't have "jre" subdirectory
}
// Use current module name "libjvm[_g].so" instead of
// "libjvm"debug_only("_g")".so" since for fastdebug version
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
} else {
// Go back to path of .so
}
}
}
}
}
// no prefix required, not even "_"
}
// no suffix required
}
// This method is a copy of JDK's sysGetLastErrorString
// from src/solaris/hpi/src/system_md.c
if (errno == 0) return 0;
if (n >= len) {
n = len - 1;
}
buf[n] = '\0';
return n;
}
// sun.misc.Signal
extern "C" {
// Ctrl-C is pressed during error reporting, likely because the error
// handler fails to abort. Let VM die immediately.
}
// We do not need to reinstate the signal handler each time...
}
}
return CAST_FROM_FN_PTR(void*, UserHandler);
}
public:
Semaphore();
~Semaphore();
void signal();
void wait();
bool trywait();
private:
};
}
}
}
}
return sema_trywait(&_semaphore) == 0;
}
while (1) {
if (result == 0) {
return true;
continue;
return false;
} else {
return false;
}
}
}
extern "C" {
typedef void (*sa_handler_t)(int);
}
// -1 means registration failed
return (void *)-1;
}
}
/*
* The following code is moved from os.cpp for making this
* code platform specific, which it is by its very nature.
*/
// a counter for each possible signal value
static int Sigexit = 0;
static int Maxlibjsigsigs;
typedef int (*version_getting_t)();
return Sigexit;
}
// Initialize signal structures
// pending_signals has one int per signal
// The additional signal is for SIGEXIT - exit signal to signal_thread
if (UseSignalChaining) {
}
}
int ret;
}
int ret;
}
int ret;
while (true) {
for (int i = 0; i < Sigexit + 1; i++) {
jint n = pending_signals[i];
return i;
}
}
if (!wait_for_signal) {
return -1;
}
bool threadIsSuspended;
do {
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
;
// were we externally suspended while we were waiting?
if (threadIsSuspended) {
//
// The semaphore has been incremented, but while we were waiting
// another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that
// suspended us.
//
}
} while (threadIsSuspended);
}
}
return check_pending_signals(false);
}
return check_pending_signals(true);
}
////////////////////////////////////////////////////////////////////////////////
// Virtual Memory
// The mmap MAP_ALIGN flag is supported on Solaris 9 and later. init_2() will
// clear this var if support is not available.
static bool has_map_align = true;
return page_size;
}
// Solaris allocates memory by pages.
return page_size;
}
// See if the error is one we can let the caller handle. This
// list of errno values comes from the Solaris mmap(2) man page.
switch (err) {
case EBADF:
case EINVAL:
case ENOTSUP:
// let the caller deal with these errors
return true;
default:
// Any remaining errors on this OS can cause our reserved mapping
// to be lost. That can cause confusion where different data
// structures think they have the same memory mapped. The worst
// scenario is if both the VM and a library think they have the
// same memory mapped.
return false;
}
}
int err) {
}
int err) {
}
if (UseNUMAInterleaving) {
}
return 0;
}
if (!recoverable_mmap_error(err)) {
}
return err;
}
}
const char* mesg) {
if (err != 0) {
// the caller wants all commit errors to exit with the specified mesg:
}
}
if (err == 0) {
// If the large page size has been set and the VM
// is using large pages, use the large page size
// if it is smaller than the alignment hint. This is
// a case where the VM wants to use a larger alignment size
// for its own reasons but still want to use large pages
// (which is what matters to setting the mpss range.
if (large_page_size() < alignment_hint) {
page_size = large_page_size();
} else {
// If the alignment hint is less than the large page
// size, the VM wants a particular alignment (thus the hint)
// for internal reasons. Try to set the mpss range using
// the alignment_hint.
}
// Since this is a hint, ignore any failures.
}
}
return err;
}
bool exec) {
}
const char* mesg) {
if (err != 0) {
// the caller wants all commit errors to exit with the specified mesg:
}
}
// Uncommit the pages in a specified region.
return;
}
}
}
}
// Change the page size in a given range.
if (UseLargePages && UseMPSS) {
}
}
// Tell the OS to make the range local to the first-touching LWP
}
}
// Tell the OS that this range would be accessed from different LWPs.
}
}
// Get the number of the locality groups.
return n != -1 ? n : 1;
}
// Get a list of leaf locality groups. A leaf lgroup is group that
// board. An LWP is assigned to one of these groups upon creation.
ids[0] = 0;
return 1;
}
for (int k = 0; k < size; k++) {
if (r == -1) {
ids[0] = 0;
return 1;
}
if (!r) {
// That's a leaf node.
// Check if the node has memory
NULL, 0, LGRP_RSRC_MEM) > 0) {
}
}
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.
assert(c != 0, "Failure to initialize LGRP API");
Solaris::set_lgrp_cookie(c);
return true;
}
return false;
}
// Get the group id of the current LWP.
if (lgrp_id == -1) {
return 0;
}
// Get the ids of all lgroups with memory; r is the count.
if (r <= 0) {
return 0;
}
}
// Request information about the page.
return false;
}
if ((validity & 1) != 0) {
if ((validity & 2) != 0) {
}
if ((validity & 4) != 0) {
}
return true;
}
return false;
}
// Scan the pages from start to end until a page different than
// the one described in the info parameter is encountered.
addrs[0] = p;
addrs_count++;
}
return NULL;
}
size_t i = 0;
for (; i < addrs_count; i++) {
if ((validity[i] & 1) != 0) {
if ((validity[i] & 4) != 0) {
break;
}
} else
if (page_expected->size != 0) {
break;
}
break;
}
}
} else {
return NULL;
}
}
if (i != addrs_count) {
if ((validity[i] & 2) != 0) {
} else {
}
if ((validity[i] & 4) != 0) {
} else {
page_found->size = 0;
}
return (char*)addrs[i];
}
}
return end;
}
// Map uncommitted pages PROT_NONE so we fail early if we touch an
// have enough swap space to back the physical page.
return
}
if (b == MAP_FAILED) {
return NULL;
}
return b;
}
char* os::Solaris::anon_mmap(char* requested_addr, size_t bytes, size_t alignment_hint, bool fixed) {
if (fixed) {
addr = (char*) alignment_hint;
}
// Map uncommitted pages PROT_NONE so we fail early if we touch an
// have enough swap space to back the physical page.
}
"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).
// Solaris adds a gap between mmap'ed regions. The size of the gap
// is dependent on the requested size and the MMU. Our initial gap
// value here is just a guess and will be corrected later.
bool had_top_overlap = false;
bool have_adjusted_gap = false;
// 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.
// 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.
if (addr == requested_addr) {
return addr;
}
if (PrintMiscellaneous && Verbose) {
buf[0] = '\0';
}
}
// 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) {
// Is this the block we wanted?
if (base[i] == requested_addr) {
break;
}
// check that the gap value is right
if (had_top_overlap && !have_adjusted_gap) {
if (gap != actual_gap) {
// adjust the gap value and retry the last 2 allocations
assert(i > 0, "gap adjustment code problem");
have_adjusted_gap = true; // adjust the gap only once, just in case
gap = actual_gap;
if (PrintMiscellaneous && Verbose) {
}
i-=2;
continue;
}
}
// Does this overlap the block we wanted? Give back the overlapped
// parts and try again.
//
// There is still a bug in this code: if top_overlap == bytes,
// the overlap is offset from requested region by the value of gap.
// In this case giving back the overlapped part will not work,
// because we'll give back the entire block at base[i] and
// therefore the subsequent allocation will not generate a new gap.
// This could be fixed with a new algorithm that used larger
// or variable size chunks to find the requested region -
// but such a change would introduce additional complications.
// It's rare enough that the planets align for this bug,
// so we'll just wait for a fix for 6204603/5003415 which
// will provide a mmap flag to allow us to avoid this business.
had_top_overlap = true;
base[i] += top_overlap;
} else {
warning("attempt_reserve_memory_at: possible alignment bug");
}
} else {
}
}
}
}
// Give back the unused reserved pieces.
for (int j = 0; j < i; ++j) {
}
}
}
}
"addr must be page aligned");
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 is_committed) {
unsigned int p = 0;
switch (prot) {
case MEM_PROT_NONE: p = PROT_NONE; break;
case MEM_PROT_READ: p = PROT_READ; break;
default:
}
// is_committed is unused.
}
// 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.
}
}
// Large page support
// UseMPSS and UseISM are supported for compatibility reasons. Their combined
// effects can be described in the following table:
//
// UseLargePages UseMPSS UseISM
// false * * => UseLargePages is the master switch, turning
// it off will turn off both UseMPSS and
// UseISM. VM will not use large page memory
// true false false => Unless future Solaris provides other
// mechanism to use large page memory, this
// combination is equivalent to -UseLargePages,
// VM will not use large page memory
// true true false => JVM will use MPSS for large page memory.
// This is the default behavior.
// true false true => JVM will use ISM for large page memory.
// true true true => JVM will use ISM if it is available.
// Otherwise, JVM will fall back to MPSS.
// Becaues ISM is now available on all
// supported Solaris versions, this combination
// is equivalent to +UseISM -UseMPSS.
// x86 uses either 2M or 4M page, depending on whether PAE (Physical Address
// can support multiple page sizes.
// Don't bother to probe page size because getpagesizes() comes with MPSS.
// ISM is only recommended on old Solaris where there is no MPSS support.
// Simply choose a conservative value as default.
ARM_ONLY(2 * M);
// ISM is available on all supported Solaris versions
return true;
}
// Insertion sort for small arrays (descending order).
for (int i = 0; i < len; i++) {
}
}
}
if (usable_count == 1) {
return false;
}
// Find the right getpagesizes interface. When solaris 11 is the minimum
// build platform, getpagesizes() (without the '2') can be called directly.
if (warn) {
warning("MPSS is not supported by the operating system.");
}
return false;
}
}
// Fill the array of page sizes.
assert(n > 0, "Solaris bug?");
if (n == page_sizes_max) {
// Add a sentinel value (necessary only if the array was completely filled
// since it is static (zeroed at initialization)).
_page_sizes[--n] = 0;
}
if (n == 1) return false; // Only one page size available.
// Skip sizes larger than 4M (or LargePageSizeInBytes if it was set) and
// select up to usable_count elements. First sort the array, find the first
// acceptable value, then copy the usable sizes to the top of the array and
// trim the rest. Make sure to include the default page size :-).
//
// A better policy could get rid of the 4M limit by taking the sizes of the
// important VM memory regions (java heap and possibly the code cache) into
// account.
int beg;
}
// Default page size is not the smallest; sort again.
}
*page_size = _page_sizes[0];
return true;
}
if (!UseLargePages) {
UseISM = false;
UseMPSS = false;
return;
}
// print a warning if any large page related flag is specified on command line
!FLAG_IS_DEFAULT(UseISM) ||
!FLAG_IS_DEFAULT(UseMPSS) ||
if (UseISM) {
// ISM disables MPSS to be compatible with old JDK behavior
UseMPSS = false;
_page_sizes[0] = _large_page_size;
}
}
// Signal to OS that we want large pages for addresses
// from addr, addr + bytes
mpss_struct.mha_flags = 0;
(caddr_t) &mpss_struct, 0, 0) < 0) {
return false;
}
return true;
}
// "exec" is passed in but not used. Creating the shared image for
// the code cache doesn't have an SHM_X executable permission to check.
int shmid;
(!FLAG_IS_DEFAULT(UseLargePages) ||
!FLAG_IS_DEFAULT(UseISM) ||
);
// Create a large shared memory region to attach to based on size.
// Currently, size is the total size of the heap
if (shmid == -1){
if (warn_on_failure) {
}
return NULL;
}
// Attach to the region
// Remove shmid. If shmat() is successful, the actual shared memory segment
// will be deleted when it's detached by shmdt() or when the process
// terminates. If shmat() is not successful this will remove the shared
// segment immediately.
if (retAddr == (char *) -1) {
if (warn_on_failure) {
}
return NULL;
}
}
// The memory is committed
return retAddr;
}
// detaching the SHM segment will also delete it, see reserve_memory_special()
if (rslt == 0) {
return true;
} else {
return false;
}
}
return _large_page_size;
}
// MPSS allows application to commit large page memory on demand; with ISM
// the entire memory region must be allocated as shared memory.
return UseISM ? false : true;
}
return UseISM ? false : true;
}
int res;
return res;
}
// Restart interrupted polls with new parameters until the proper delay
// has been completed.
prevtime = getTimeMillis();
while (millis > 0) {
if (!interruptible) {
// Following assert fails for os::yield_all:
// assert(!thread->is_Java_thread(), "must not be java thread");
} else {
}
// INTERRUPTIBLE_NORESTART_VM_ALWAYS returns res == OS_INTRPT for
// thread.Interrupt.
// See c/r 6751923. Poll can return 0 before time
// has elapsed if time is set via clock_settime (as NTP does).
// res == 0 if poll timed out (see man poll RETURN VALUES)
// using the logic below checks that we really did
// sleep at least "millis" if not we'll sleep again.
newtime = getTimeMillis();
/* Doing prevtime and newtime in microseconds doesn't help precision,
and trying to round up to avoid lost milliseconds can result in a
too-short delay. */
if(millis <= 0)
return OS_OK;
} else
return res;
}
return OS_OK;
}
// Read calls from inside the vm need to perform state transitions
}
}
// TODO-FIXME: this should be removed.
// On Solaris machines (especially 2.5.1) we found that sometimes the VM gets into a live lock
// situation with a JavaThread being starved out of a lwp. The kernel doesn't seem to generate
// a SIGWAITING signal which would enable the threads library to create a new lwp for the starving
// thread. We suspect that because the Watcher thread keeps waking up at periodic intervals the kernel
// is fooled into believing that the system is making progress. In the code below we block the
// the watcher thread while safepoint is in progress so that it would not appear as though the
// system is making progress.
if (!Solaris::T2_libthread() &&
thread->is_Watcher_thread() && SafepointSynchronize::is_synchronizing() && !Arguments::has_profile()) {
// We now try to acquire the threads lock. Since this lock is held by the VM thread during
// the entire safepoint, the watcher thread will line up here during the safepoint.
Threads_lock->unlock();
}
if (thread->is_Java_thread()) {
// This is a JavaThread so we honor the _thread_blocked protocol
// even for sleeps of 0 milliseconds. This was originally done
// as a workaround for bug 4338139. However, now we also do it
// to honor the suspend-equivalent protocol.
// cleared by handle_special_suspend_equivalent_condition() or
// java_suspend_self() via check_and_wait_while_suspended()
int ret_code;
if (millis <= 0) {
thr_yield();
ret_code = 0;
} else {
// The original sleep() implementation did not create an
// OSThreadWaitState helper for sleeps of 0 milliseconds.
// I'm preserving that decision for now.
}
// were we externally suspended while we were waiting?
return ret_code;
}
// non-JavaThread from this point on:
if (millis <= 0) {
thr_yield();
return 0;
}
}
// %% make the sleep time an integer flag. for now use 1 millisec.
return os_sleep(1, false);
}
// Sleep forever; naked call to OS-specific sleep; use with CAUTION
while (true) { // sleep forever ...
}
}
// Used to convert frequent JVM_Yield() to nops
if (DontYieldALot) {
return true;
return false;
}
else {
return false;
}
}
// Caveat: Solaris os::yield() causes a thread-state transition whereas
// the linux and win32 implementations do not. This should be checked.
// Yields to all threads with same or greater priority
}
// Note that yield semantics are defined by the scheduling class to which
// the thread currently belongs. Typically, yield will _not yield to
// other equal or higher priority threads that reside on the dispatch queues
// of other CPUs.
// On Solaris we found that yield_all doesn't always yield to all other threads.
// There have been cases where there is a thread ready to execute but it doesn't
// get an lwp as the VM thread continues to spin with sleeps of 1 millisecond.
// The 1 millisecond wait doesn't seem long enough for the kernel to issue a
// SIGWAITING signal which will cause a new lwp to be created. So we count the
// number of times yield_all is called in the one loop and increase the sleep
// time after 8 attempts. If this fails too we increase the concurrency level
// so that the starving thread would get an lwp
// Yields to all threads, including threads with lower priorities
if (attempts == 0) {
} else {
// thr_setconcurrency and _getconcurrency make sense only under T1.
}
} else if (iterations < 25) {
} else {
}
}
}
// Called from the tight loops to possibly influence time-sharing heuristics
}
// Interface for setting lwp priorities. If we are using T2 libthread,
// which forces the use of BoundThreads or we manually set UseBoundThreads,
// all of our threads will be assigned to real lwp's. Using the thr_setprio
// function is meaningless in this mode so we must adjust the real lwp's priority
// The routines below implement the getting and setting of lwp priorities.
//
// Note: There are three priority scales used on Solaris. Java priotities
// which range from 1 to 10, libthread "thr_setprio" scale which range
// from 0 to 127, and the current scheduling class of the process we
// are running in. This is typically from -60 to +60.
// The setting of the lwp priorities in done after a call to thr_setprio
// so Java priorities are mapped to libthread priorities and we map from
// the latter to lwp priorities. We don't keep priorities stored in
// Java priorities since some of our worker threads want to set priorities
// higher than all Java threads.
//
// For related information:
// (1) man -s 2 priocntl
// (2) man -s 4 priocntl
// (3) man dispadmin
// = librt.so
// = ps -cL <pid> ... to validate priority.
// = sched_get_priority_min and _max
// pthread_create
// sched_setparam
// pthread_setschedparam
//
// Assumptions:
// + We assume that all threads in the process belong to the same
// scheduling class. IE. an homogenous process.
// + Must be root or in IA group to change change "interactive" attribute.
// Priocntl() will fail silently. The only indication of failure is when
// we read-back the value and notice that it hasn't changed.
// + Interactive threads enter the runq at the head, non-interactive at the tail.
// + For RT, change timeslice as well. Invariant:
// constant "priority integral"
// Konst == TimeSlice * (60-Priority)
// Given a priority, compute appropriate timeslice.
// + Higher numerical values have higher priority.
// sched class attributes
typedef struct {
int maxPrio;
int minPrio;
} SchedInfo;
#ifdef ASSERT
#endif
static int myClass = 0;
static int myMin = 0;
static int myMax = 0;
static int myCur = 0;
static bool priocntl_enable = false;
// Call the version of priocntl suitable for all supported versions
// of Solaris. We need to call through this wrapper so that we can
// build on Solaris 9 and run on Solaris 8, 9 and 10.
//
// This code should be removed if we ever stop supporting Solaris 8
// and earlier releases.
// Stub to set the value of the real pointer, and then call the real
// function.
// Try Solaris 8- name only.
priocntl_ptr = tmp;
}
// lwp_priocntl_init
//
// Try to determine the priority scale for our process.
//
// Return errno or 0 if OK.
//
static
int lwp_priocntl_init ()
{
int rslt;
int i;
if (!UseThreadPriorities) return 0;
// We are using Bound threads, we need to determine our priority ranges
// If ThreadPriorityPolicy is 1, switch tables
if (ThreadPriorityPolicy == 1) {
for (i = 0 ; i < CriticalPriority+1; i++)
}
// MaxPriority always maps to the FX scheduling class and criticalPrio.
// See set_native_priority() and set_lwp_class_and_priority().
// Save original MaxPriority mapping in case attempt to
// use critical priority fails.
// Set negative to distinguish from other priorities
}
}
// Not using Bound Threads, set to ThreadPolicy 1
else {
for ( i = 0 ; i < CriticalPriority+1; i++ ) {
}
return 0;
}
// Get IDs for a set of well-known scheduling classes.
// TODO-FIXME: GETCLINFO returns the current # of classes in the
// the system. We should have a loop that iterates over the
// classID values, which are known to be "small" integers.
// Query our "current" scheduling class.
// This will normally be IA, TS or, rarely, FX or RT.
// We now know our scheduling classId, get specific information
// about the class.
if (ThreadPriorityVerbose) {
}
} else {
// No clue - punt
return EINVAL; // no clue, punt
}
if (ThreadPriorityVerbose) {
}
priocntl_enable = true; // Enable changing priorities
return 0;
}
// scale_to_lwp_priority
//
// Convert from the libthread "thr_setprio" scale to our current
// lwp scheduling class scale.
//
static
{
int v;
return v;
}
// set_lwp_class_and_priority
//
// Set the class and priority of the lwp. This call should only
// be made when using bound threads (T2 threads are bound by default).
//
int rslt;
#ifdef ASSERT
#endif
// Set priority via PC_GETPARMS, update, PC_SETPARMS
// Query current values.
// TODO: accelerate this by eliminating the PC_GETPARMS call.
// Cache "pcparms_t" in global ParmCache.
// TODO: elide set-to-same-value
// If something went wrong on init, don't change priorities.
if ( !priocntl_enable ) {
return EINVAL;
}
// If lwp hasn't started yet, just return
// the _start routine will call us again.
if ( lwpid <= 0 ) {
if (ThreadPriorityVerbose) {
INTPTR_FORMAT " to %d, lwpid not set",
}
return 0;
}
if (ThreadPriorityVerbose) {
}
: newPrio;
if (ThreadPriorityVerbose) {
}
: newPrio;
if (ThreadPriorityVerbose) {
}
: newPrio;
if (ThreadPriorityVerbose) {
}
: newPrio;
if (ThreadPriorityVerbose) {
}
} else {
if (ThreadPriorityVerbose) {
}
return EINVAL; // no clue, punt
}
if (ThreadPriorityVerbose && rslt) {
}
#ifdef ASSERT
// Sanity check: read back what we just attempted to set.
// In theory it could have changed in the interim ...
//
// The priocntl system call is tricky.
// Sometimes it'll validate the priority value argument and
// return EINVAL if unhappy. At other times it fails silently.
// Readbacks are prudent.
if (!ReadBackValidate) return 0;
} else {
if (ThreadPriorityVerbose) {
}
}
if (ThreadPriorityVerbose) {
}
}
#endif
return 0;
}
// Solaris only gives access to 128 real priorities at a time,
// so we expand Java's ten to fill this range. This would be better
// if we dynamically adjusted relative priorities.
//
// The ThreadPriorityPolicy option allows us to select 2 different
// priority scales.
//
// ThreadPriorityPolicy=0
// Since the Solaris' default priority is MaximumPriority, we do not
// set a priority lower than Max unless a priority lower than
// NormPriority is requested.
//
// ThreadPriorityPolicy=1
// This mode causes the priority table to get filled with
// linear values. NormPriority get's mapped to 50% of the
// Maximum priority an so on. This will cause VM threads
// to get unfair treatment against other Solaris processes
// which do not explicitly alter their thread priorities.
//
-99999, // 0 Entry should never be used
0, // 1 MinPriority
32, // 2
64, // 3
96, // 4
127, // 5 NormPriority
127, // 6
127, // 7
127, // 8
127, // 9 NearMaxPriority
127, // 10 MaxPriority
-criticalPrio // 11 CriticalPriority
};
// Save requested priority in case the thread hasn't been started
// Check for critical priority request
bool fxcritical = false;
if (newpri == -criticalPrio) {
fxcritical = true;
}
if (!UseThreadPriorities) return OS_OK;
int status = 0;
if (!fxcritical) {
// Use thr_setprio only if we have a priority that thr_setprio understands
}
int lwp_status =
!fxcritical);
if (lwp_status != 0 && fxcritical) {
// Try again, this time without changing the scheduling class
}
status |= lwp_status;
}
}
int p;
if ( !UseThreadPriorities ) {
return OS_OK;
}
if (status != 0) {
return OS_ERR;
}
*priority_ptr = p;
return OS_OK;
}
// Hint to the underlying OS that a task switch would not be good.
// Void return because it's a hint and can fail.
}
}
}
// Save and restore errno to avoid confusing native code with EINTR
// after sigsuspend.
// attempt to switch the state, we assume we had a SUSPEND_REQUEST
// get current set of blocked signals and unblock resume signal
// wait here until we are resumed
while (1) {
break;
}
}
// request was cancelled, continue
} else {
}
// request was cancelled, continue
// ignore
} else {
// ignore
}
}
assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer");
if (!isInterrupted) {
osthread->set_interrupted(true);
OrderAccess::fence();
// os::sleep() is implemented with either poll (NULL,0,timeout) or
// by parking on _SleepEvent. If the former, thr_kill will unwedge
// the sleeper by SIGINTR, otherwise the unpark() will wake the sleeper.
}
// For JSR166: unpark after setting status but before thr_kill -dl
if (thread->is_Java_thread()) {
}
// Handle interruptible wait() ...
// When events are used everywhere for os::sleep, then this thr_kill
// will only be needed if UseVMInterruptibleIO is true.
if (!isInterrupted) {
// Bump thread interruption counter
}
}
assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer");
// NOTE that since there is no "lock" around these two operations,
// there is the possibility that the interrupted flag will be
// "false" but that the interrupt event will be set. This is
// intentional. The effect of this is that Object.wait() will appear
// to have a spurious wakeup, which is not harmful, and the
// possibility is so rare that it is not worth the added complexity
// to add yet another lock. It has also been recommended not to put
// the interrupted flag into the os::Solaris::Event structure,
// because it hides the issue.
if (res && clear_interrupted) {
osthread->set_interrupted(false);
}
return res;
}
}
int i;
// Prevent process from exiting upon "read error" without consuming all CPU
}
return status;
}
// "Randomly" selected value for how long we want to spin
// before bailing out on suspending a thread, also how often
// we send a signal to a thread we want to resume
// mark as suspended and send signal
// failed to switch, state wasn't running?
return false;
}
}
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
while (true) {
break;
} else {
// timeout
return false;
// make sure that we consume the signal on the semaphore as well
sr_semaphore.wait();
break;
} else {
return false;
}
}
}
return true;
}
// failed to switch to WAKEUP_REQUEST
return;
}
while (true) {
return;
}
}
} else {
}
}
}
}
}
public:
ExtendedPC result();
protected:
private:
};
return _epc;
}
} else {
// NULL context is unexpected, double-check this is the VMThread
}
}
// A lightweight implementation that does not suspend the target thread and
// thus returns only a hint. Used for profiling only!
// Make sure that it is called by the watcher and the Threads lock is owned.
// For now, is only used to profile the VM Thread
}
// This does not do anything on Solaris. This is basically a hook for being
// able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
}
// This routine may be used by user applications as a "hook" to catch signals.
// The user-defined signal handler must pass unrecognized signals to this
// routine, and if it returns true (non-zero), then the signal handler must
// return immediately. If the flag "abort_if_unrecognized" is true, then this
// routine will never retun false (zero), but instead will execute a VM panic
// routine kill the process.
//
// If this routine returns false, it is OK to call it again. This allows
// the user-defined signal handler to perform checks either before or after
// the VM performs its own checks. Naturally, the user code would be making
// a serious error if it tried to handle an exception (such as a null check
// or breakpoint) that the VM was generating for its own correct operation.
//
// This routine may recognize any of the following kinds of signals:
// SIGBUS, SIGSEGV, SIGILL, SIGFPE, BREAK_SIGNAL, SIGPIPE, SIGXFSZ,
// os::Solaris::SIGasync
// It should be consulted by handlers for any of those signals.
// It explicitly does not recognize os::Solaris::SIGinterrupt
//
// The caller of this routine must pass in the three arguments supplied
// to the function referred to in the "sa_sigaction" (not the "sa_handler")
// field of the structure passed to sigaction(). This routine assumes that
// the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART.
//
// Note that the VM will print warnings if it detects conflicting signal
// handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers".
//
extern "C" JNIEXPORT int
int abort_if_unrecognized);
}
/* Do not delete - if guarantee is ever removed, a signal handler (even empty)
is needed to provoke threads blocked on IO to return an EINTR
Note: this explicitly does NOT call JVM_handle_solaris_signal and
does NOT participate in signal chaining due to requirement for
NOT setting SA_RESTART to make EINTR work. */
if (UseSignalChaining) {
vm_exit_during_initialization("Signal chaining detected for VM interrupt signal, try -XX:+UseAltSigs");
}
}
}
// This boolean allows users to forward their own non-matching signals
// to JVM_handle_solaris_signal, harmlessly.
// For signal-chaining
// Retrieve the old signal handler from libjsig
}
// Retrieve the preinstalled signal handler from jvm
}
return actp;
}
// Call the old signal handler
// It's more reasonable to let jvm treat it as an unexpected exception
// instead of taking the default action.
return false;
// automaticlly block the signal
}
// retrieve the chained handler
if (siginfo_flag_set) {
} else {
}
}
// try to honor the signal mask
// call into the chained handler
if (siginfo_flag_set) {
} else {
}
// restore the signal mask
}
// Tell jvm's signal handler the signal is taken care of.
return true;
}
bool chained = false;
// signal-chaining
if (UseSignalChaining) {
}
}
return chained;
}
assert((chainedsigactions != (struct sigaction *)NULL) && (preinstalled_sigs != (int *)NULL) , "signals not yet initialized");
if (preinstalled_sigs[sig] != 0) {
return &chainedsigactions[sig];
}
return NULL;
}
assert((chainedsigactions != (struct sigaction *)NULL) && (preinstalled_sigs != (int *)NULL) , "signals not yet initialized");
}
// Check for overwrite.
if (AllowUserSignalHandlers || !set_installed) {
// Do not overwrite; user takes responsibility to forward to us.
return;
} else if (UseSignalChaining) {
if (oktochain) {
// save the old handler in jvm
} else {
vm_exit_during_initialization("Signal chaining not allowed for VM interrupt signal, try -XX:+UseAltSigs.");
}
// libjsig also interposes the sigaction() call below and saves the
// old sigaction on it own.
} else {
}
}
// Handle SIGSEGV on alternate signal stack if
// not using stack banging
// Interruptible i/o requires SA_RESTART cleared so EINTR
// is returned instead of restarting system calls
} else {
}
}
// This method is a periodic task to check for misbehaving JNI applications
// under CheckJNI, we can add any periodic checks here
// A big source of grief is hijacking virt. addr 0x0 on Solaris,
// thereby preventing a NULL checks.
if (check_signals == false) return;
// SEGV and BUS if overridden could potentially prevent
// generation of hs*.log in the event of a crash, debugging
// such a case can be very challenging, so we absolutely
// check for the following for a good measure:
// ReduceSignalUsage allows the user to override these handlers
// see comments at the very top and jvm_solaris.h
if (!ReduceSignalUsage) {
}
}
if (os_sigaction == NULL) {
// only trust the default sigaction, in case it has been interposed
if (os_sigaction == NULL) return;
}
switch(sig) {
case SIGSEGV:
case SIGBUS:
case SIGFPE:
case SIGPIPE:
case SIGXFSZ:
case SIGILL:
break;
case SHUTDOWN1_SIGNAL:
case SHUTDOWN2_SIGNAL:
case SHUTDOWN3_SIGNAL:
case BREAK_SIGNAL:
break;
default:
} else {
return;
}
break;
}
if (thisHandler != jvmHandler) {
// No need to check this sig any longer
} else if(os::Solaris::get_our_sigflags(sig) != 0 && act.sa_flags != os::Solaris::get_our_sigflags(sig)) {
// No need to check this sig any longer
}
// Print all the signal handler state
}
}
bool libjsigdone = false;
signal_handlers_are_installed = true;
// signal-chaining
typedef void (*signal_setting_t)();
if (begin_signal_setting != NULL) {
libjsig_is_loaded = true;
}
}
if (libjsig_is_loaded) {
// Tell libjsig jvm is setting signal handlers
(*begin_signal_setting)();
}
set_signal_handler(SIGSEGV, true, true);
set_signal_handler(SIGPIPE, true, true);
set_signal_handler(SIGXFSZ, true, true);
set_signal_handler(SIGBUS, true, true);
set_signal_handler(SIGILL, true, true);
set_signal_handler(SIGFPE, true, true);
// Pre-1.4.1 Libjsig limited to signal chaining signals <= 32 so
// can not register overridable signals which might be > 32
// Tell libjsig jvm has finished setting signal handlers
(*end_signal_setting)();
libjsigdone = true;
}
}
// Never ok to chain our SIGinterrupt
if (libjsig_is_loaded && !libjsigdone) {
// Tell libjsig jvm finishes setting signal handlers
(*end_signal_setting)();
}
// We don't activate signal checker if libjsig is in place, we trust ourselves
// and if UserSignalHandler is installed all bets are off.
// Log that signal checking is off only if -verbose:jni is specified.
if (CheckJNICalls) {
if (libjsig_is_loaded) {
if (PrintJNIResolving) {
}
check_signals = false;
}
if (AllowUserSignalHandlers) {
if (PrintJNIResolving) {
tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled");
}
check_signals = false;
}
}
}
const char * signames[] = {
"SIG0",
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP",
"SIGABRT", "SIGEMT", "SIGFPE", "SIGKILL", "SIGBUS",
"SIGSEGV", "SIGSYS", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGCLD", "SIGPWR", "SIGWINCH",
"SIGURG", "SIGPOLL", "SIGSTOP", "SIGTSTP", "SIGCONT",
"SIGTTIN", "SIGTTOU", "SIGVTALRM", "SIGPROF", "SIGXCPU",
"SIGXFSZ", "SIGWAITING", "SIGLWP", "SIGFREEZE", "SIGTHAW",
"SIGCANCEL", "SIGLOST"
};
// signal
if (exception_code < sizeof(signames)/sizeof(const char*)) {
} else {
}
return buf;
} else {
return NULL;
}
}
// (Static) wrappers for the new libthread API
// (Static) wrapper for getisax(2) call.
// (Static) wrappers for the liblgrp API
// (Static) wrapper for meminfo() call.
// RTLD_DEFAULT was not defined on some early versions of 2.5.1
}
return addr;
}
}
return addr;
}
// isT2_libthread()
//
// Routine to determine if we are currently using the new T2 libthread.
//
// looking for a thread with the ASLWP bit set. If we find this status
// bit set, we must assume that we are NOT using T2. The T2 team
// has approved this algorithm.
//
// We need to determine if we are running with the new T2 libthread
// 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 int lwpSize = 0;
bool isT2 = false;
if (lwpFile < 0) {
return false;
}
for (;;) {
break;
}
// We got a good snapshot - now iterate over the list.
int aslwpcount = 0;
aslwpcount++;
}
}
if (aslwpcount == 0) isT2 = true;
break;
}
}
if (ThreadPriorityVerbose) {
}
return isT2;
}
// Determine if we are running with the new T2 libthread
// RTLD_DEFAULT was not defined on some early versions of 5.5.1
// Guarantee that this VM is running on an new enough OS (5.6 or
// later) that it will have a new enough libthread.so.
}
// Initialize the new libthread getstate API wrappers
int size;
void (*handler_info_func)(address *, int *);
}
if(UseLWPSynchronization) {
os::Solaris::set_mutex_trylock(CAST_TO_FN_PTR(int_fnP_mutex_tP, resolve_symbol("_lwp_mutex_trylock")));
os::Solaris::set_mutex_unlock(CAST_TO_FN_PTR(int_fnP_mutex_tP, resolve_symbol("_lwp_mutex_unlock")));
os::Solaris::set_cond_timedwait(CAST_TO_FN_PTR(int_fnP_cond_tP_mutex_tP_timestruc_tP, resolve_symbol("_lwp_cond_timedwait")));
os::Solaris::set_cond_wait(CAST_TO_FN_PTR(int_fnP_cond_tP_mutex_tP, resolve_symbol("_lwp_cond_wait")));
os::Solaris::set_cond_broadcast(CAST_TO_FN_PTR(int_fnP_cond_tP, resolve_symbol("_lwp_cond_broadcast")));
}
else {
if(UsePthreads) {
os::Solaris::set_mutex_lock(CAST_TO_FN_PTR(int_fnP_mutex_tP, resolve_symbol("pthread_mutex_lock")));
os::Solaris::set_mutex_trylock(CAST_TO_FN_PTR(int_fnP_mutex_tP, resolve_symbol("pthread_mutex_trylock")));
os::Solaris::set_mutex_unlock(CAST_TO_FN_PTR(int_fnP_mutex_tP, resolve_symbol("pthread_mutex_unlock")));
os::Solaris::set_mutex_destroy(CAST_TO_FN_PTR(int_fnP_mutex_tP, resolve_symbol("pthread_mutex_destroy")));
os::Solaris::set_cond_timedwait(CAST_TO_FN_PTR(int_fnP_cond_tP_mutex_tP_timestruc_tP, resolve_symbol("pthread_cond_timedwait")));
os::Solaris::set_cond_wait(CAST_TO_FN_PTR(int_fnP_cond_tP_mutex_tP, resolve_symbol("pthread_cond_wait")));
os::Solaris::set_cond_signal(CAST_TO_FN_PTR(int_fnP_cond_tP, resolve_symbol("pthread_cond_signal")));
os::Solaris::set_cond_broadcast(CAST_TO_FN_PTR(int_fnP_cond_tP, resolve_symbol("pthread_cond_broadcast")));
os::Solaris::set_cond_destroy(CAST_TO_FN_PTR(int_fnP_cond_tP, resolve_symbol("pthread_cond_destroy")));
}
else {
os::Solaris::set_cond_timedwait(CAST_TO_FN_PTR(int_fnP_cond_tP_mutex_tP_timestruc_tP, resolve_symbol("cond_timedwait")));
}
}
}
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")));
set_lgrp_cookie(c);
return true;
}
return false;
}
// getisax
}
// meminfo
}
}
}
// Symbol doesn't exist in Solaris 8 pset.h
#ifndef PS_MYID
#endif
// int pset_getloadavg(psetid_t pset, double loadavg[], int nelem);
void init_pset_getloadavg_ptr(void) {
warning("pset_getloadavg function not found");
}
}
// this is called _before_ the global arguments have been parsed
_initial_pid = getpid();
init_random(1234567);
if (page_size == -1)
// Initialize misc. symbols as soon as possible, so we can use them
// if we need them.
Solaris::misc_sym_init();
if (fd < 0) {
} else {
// Close on exec, child won't inherit.
}
// check if dladdr1() exists; dladdr1 can provide more information than
// dladdr for os::dll_address_to_function_name. It comes with SunOS 5.9
// and is available on linker patches for 5.7 and 5.8.
// libdl.so must have been loaded, this call is just an entry lookup
if (hdl)
// (Solaris only) this switches to calls that actually do locking.
main_thread = thr_self();
// Constant minimum stack size allowed. It must be at least
// the minimum of what the OS supports (thr_min_stack()), and
// enough to allow the thread to get to user bytecode execution.
// If the pagesize of the VM is greater than 8K determine the appropriate
// number of initial guard pages. The user can change this with the
// command line arguments, if needed.
if (vm_page_size() > 8*K) {
StackYellowPages = 1;
StackRedPages = 1;
}
}
// To install functions for atexit system call
extern "C" {
static void perfMemory_exit_helper() {
}
}
// this is called _after_ the global arguments have been parsed
// try to enable extended file IO ASAP, see 6431278
// Allocate a single page and mark it as readable for safepoint polling. Also
// use this first mmap call to check support for MAP_ALIGN.
if (polling_page == NULL) {
has_map_align = false;
}
#ifndef PRODUCT
if( Verbose && PrintMiscellaneous )
#endif
if (!UseMembar) {
address mem_serialize_page = (address)Solaris::mmap_chunk( NULL, page_size, MAP_PRIVATE, PROT_READ | PROT_WRITE );
#ifndef PRODUCT
if(Verbose && PrintMiscellaneous)
#endif
}
os::large_page_init();
// Check minimum allowable stack size for thread creation and to initialize
// the java system classes, including StackOverflowError - depends on page
// size. Add a page for compiler2 recursion in main thread.
// Add in 2*BytesPerWord times page size to account for VM stack during
// class initialization depending on 32 or 64 bit VM.
if (threadStackSizeInBytes != 0 &&
return JNI_ERR;
}
// For 64kbps there will be a 64kb page size, which makes
// the usable default stack size quite a bit less. Increase the
// stack for 64kb (or any > than 8kb) pages, this increases
// virtual memory fragmentation (since we're not creating the
// stack on a power of 2 boundary. The real fix for this
// should be to fix the guard page mechanism.
if (vm_page_size() > 8*K) {
: 0;
}
// Make the stack size a multiple of the page size so that
vm_page_size()));
if (UseNUMA) {
if (!Solaris::liblgrp_init()) {
UseNUMA = false;
} else {
if (lgrp_num < 2) {
// There's only one locality group, disable NUMA.
UseNUMA = false;
}
}
// ISM is not compatible with the NUMA allocator - it always allocates
// pages round-robin across the lgroups.
if (!FLAG_IS_DEFAULT(UseNUMA)) {
UseLargePages = false;
} else {
warning("UseNUMA is not compatible with ISM large pages, disabling NUMA allocator");
UseNUMA = false;
}
} else {
UseNUMA = false;
}
}
UseNUMA = true;
}
}
if (libjsigversion < JSIG_VERSION_1_4_1) {
}
// initialize synchronization primitives to use either thread or
// lwp synchronization (controlled by UseLWPSynchronization)
if (MaxFDLimit) {
// set the number of file descriptors to max. print out error
if (status != 0) {
perror("os::init_2 getrlimit failed");
} else {
if (status != 0) {
perror("os::init_2 setrlimit failed");
}
}
}
// Calculate theoretical max. size of Threads to guard gainst
// artifical out-of-memory situations, where all available address-
// space has been reserved by thread stacks. Default stack size is 1Mb.
// Solaris has a maximum of 4Gb of user programs. Calculate the thread limit when
// we should start doing Virtual Memory banging. Currently when the threads will
// have used all but 200Mb of space.
// at-exit methods are called in the reverse order of their registration.
// In Solaris 7 and earlier, 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. In Solaris
// 8 and later, there is no limit to the number of functions registered
// and atexit() sets errno. In addition, in Solaris 8 and later, atexit
// functions are called upon dlclose(3DL) in addition to return from main
// and exit(3C).
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::init2 atexit(perfMemory_exit_helper) failed");
}
}
// Init pset_loadavg function pointer
return JNI_OK;
}
return;
}
// Mark the polling page as unreadable
fatal("Could not disable polling page");
};
// Mark the polling page as readable
fatal("Could not enable polling page");
};
// OS interface.
if (!sol_vsnprintf) {
//search for the named symbol in the objects that were loaded after libjvm
if (!sol_vsnprintf){
//search for the named symbol in the objects that were loaded before libjvm
}
}
}
// Is a (classpath) directory empty?
/* Scan the directory */
bool result = true;
result = false;
}
}
return result;
}
// This code originates from JDK's sysOpen and open64_w
// from src/solaris/hpi/src/system_md.c
#ifndef O_DELETE
#endif
// Open a file. Unlink the file immediately after open returns
// if the specified oflag has the O_DELETE flag set.
return -1;
}
int fd;
//If the open succeeded, the file might still be a directory
{
if (ret != -1) {
return -1;
}
} else {
return -1;
}
}
/*
* 32-bit Solaris systems suffer from:
*
* - an historical default soft limit of 256 per-process file
* descriptors that is too low for many Java programs.
*
* - a design flaw where file descriptors created using stdio
* fopen must be less than 256, _even_ when the first limit above
* has been raised. This can cause calls to fopen (but not calls to
* open, for example) to fail mysteriously, perhaps in 3rd party
* native code (although the JDK itself uses fopen). One can hardly
* criticize them for using this most standard of all functions.
*
* We attempt to make everything work anyways by:
*
* - raising the soft limit on per-process file descriptors beyond
* 256
*
* - As of Solaris 10u4, we can request that Solaris raise the 256
* stdio fopen limit by calling function enable_extended_FILE_stdio.
* This is done in init_2 and recorded in enabled_extended_FILE_stdio
*
* - If we are stuck on an old (pre 10u4) Solaris system, we can
* workaround the bug by remapping non-stdio file descriptors below
* 256 to ones beyond 256, which is done below.
*
* See:
* 1085341: 32-bit stdio routines should support file descriptors >255
* 6533291: Work around 32-bit Solaris stdio limit of 256 open files
* 6431278: Netbeans crash on 32 bit Solaris: need to call
* enable_extended_FILE_stdio() in VM initialisation
* Giri Mandalika's blog
*/
#ifndef _LP64
if (newfd != -1) {
}
}
#endif // 32-bit Solaris
/*
* All file descriptors that are opened in the JVM and not
* specifically destined for a subprocess should have the
* close-on-exec flag set. If we don't set it, then careless 3rd
* party native code might fork and exec without closing all
* appropriate file descriptors (e.g. as we do in closeDescriptors in
* UNIXProcess.c), and this in turn might:
*
* - cause end-of-file to fail to be detected on some file
* descriptors, resulting in mysterious hangs, or
*
* - might cause an fopen in the subprocess to fail on a system
* suffering from bug 1085341.
*
* (Yes, the default setting of the close-on-exec flag is a Unix
* design flaw)
*
* See:
* 1085341: 32-bit stdio routines should support file descriptors >255
* 4843136: (process) pipe file descriptor from Runtime.exec not being closed
* 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
*/
#ifdef FD_CLOEXEC
{
if (flags != -1)
}
#endif
if (o_delete != 0) {
}
return fd;
}
// create binary file, rewriting existing file if required
if (!rewrite_existing) {
}
}
// return current position of file pointer
}
// move file pointer to the specified offset
}
}
return path;
}
}
}
int mode;
/*
* XXX: is the following call interruptible? If so, this might
* need to go through the INTERRUPT_IO() wrapper as for other
* blocking, interruptible calls in this file.
*/
int n,ioctl_return;
if (ioctl_return>= 0) {
*bytes = n;
return 1;
}
}
}
return 0;
return 0;
return 0;
}
return 1;
}
// Map a block of memory.
bool allow_exec) {
int prot;
int flags;
if (read_only) {
flags = MAP_SHARED;
} else {
flags = MAP_PRIVATE;
}
if (allow_exec) {
}
}
fd, file_offset);
if (mapped_address == MAP_FAILED) {
return NULL;
}
return mapped_address;
}
// Remap a block of memory.
bool allow_exec) {
// same as map_memory() on this OS
}
// Unmap a block of memory.
}
if (PauseAtStartupFile && PauseAtStartupFile[0]) {
} else {
}
if (fd != -1) {
}
} else {
"Could not open pause file '%s', continuing immediately.\n", filename);
}
}
#ifndef PRODUCT
// Turn this on if you need to trace synch operations.
// Set RECORD_SYNCH_LIMIT to a large-enough value,
// and call record_synch_enable and record_synch_disable
// around the computation of interest.
class RecordSynch {
char* _name;
public:
{ record_synch(_name, false); }
};
static int callcount = 0; \
} \
++callcount; \
inner; \
}
// in dbx, examine callcounts this way:
// for n in $(eval whereis callcount | awk '{print $2}'); do print $n; done
#define CHECK_POINTER_OK(p) \
#define CHECK_MU \
#define CHECK_CV \
#define CHECK_P(p) \
CHECK_SYNCH_OP(int, cond_op, (cond_t *cv, mutex_t *mu, timestruc_t* ts), (cv, mu, ts), CHECK_MU;CHECK_CV);
// do the _lwp_* versions too
// recording machinery:
int record_synch_count = 0;
bool record_synch_enabled = false;
// in dbx, examine recorded data this way:
// for n in name arg0ptr returning thread; do print record_synch_$n[0..record_synch_count-1]; done
if (record_synch_enabled) {
if (record_synch_count < RECORD_SYNCH_LIMIT) {
}
// put more checking code here:
// ...
}
}
void record_synch_enable() {
// start collecting trace data, if not already doing so
if (!record_synch_enabled) record_synch_count = 0;
record_synch_enabled = true;
}
void record_synch_disable() {
// stop collecting trace data
record_synch_enabled = false;
}
#endif // INTERPOSE_ON_SYSTEM_SYNCH_FUNCTIONS
#endif // PRODUCT
// JVMTI & JVM monitoring and management support
// The thread_cpu_time() and current_thread_cpu_time() are only
// supported if is_thread_cpu_time_supported() returns true.
// They are not supported on Solaris T1.
// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
// are used by JVM M&M and JVMTI to get user+sys or user CPU time
// of a thread.
//
// current_thread_cpu_time() and thread_cpu_time(Thread *)
// returns the fast estimate available on the platform.
// hrtime_t gethrvtime() return value includes
// user time but does not include system time
return (jlong) gethrvtime();
}
// return user level CPU time only to be consistent with
// what current_thread_cpu_time returns.
// thread_cpu_time_info() must be changed if this changes
}
if (user_sys_cpu_time) {
} else {
return os::current_thread_cpu_time();
}
}
int count;
int fd;
getpid(),
do {
if ( count < 0 ) return -1;
if (user_sys_cpu_time) {
// user + system CPU time
} else {
// user level CPU time only
}
return(lwp_time);
}
}
}
return true;
} else {
return false;
}
}
// System loadavg support. Returns -1 if load average cannot be obtained.
// Return the load average for our processor set if the primitive exists
// (Solaris 9 and later). Otherwise just return system wide loadavg.
if (pset_getloadavg_ptr != NULL) {
} else {
}
}
//---------------------------------------------------------------------------------
return x;
else if (x > y)
else
}
#ifdef _LP64
#else
#endif
else
#ifdef _LP64
#else
#endif
if (Verbose) {
// decode some bytes around the PC
}
return true;
}
return false;
}
// Following function has been added to support HotSparc's libjvm.so running
// under Solaris production JDK 1.2.2 / 1.3.0. These came from
// src/solaris/hpi/native_threads in the EVM codebase.
//
// NOTE: This is no longer needed in the 1.3.1 and 1.4 production release
// libraries and should thus be removed. We will leave it behind for a while
// until we no longer want to able to run on top of 1.3.0 Solaris production
// JDK. See 4341971.
extern "C" {
}
}
extern "C" {
class ASGCT_CallTrace;
}
// ObjectMonitor park-unpark infrastructure ...
//
// We implement Solaris and Linux PlatformEvents with the
// obvious condvar-mutex-flag triple.
// Another alternative that works quite well is pipes:
// Each PlatformEvent consists of a pipe-pair.
// The thread associated with the PlatformEvent
// calls park(), which reads from the input end of the pipe.
// Unpark() writes into the other end of the pipe.
// The write-side of the pipe must be set NDELAY.
// Unfortunately pipes consume a large # of handles.
// Native solaris lwp_park() and lwp_unpark() work nicely, too.
// Using pipes for the 1st few threads might be workable, however.
//
// park() is permitted to return spuriously.
// Callers of park() should wrap the call to park() in
// an appropriate loop. A litmus test for the correct
// usage of park is the following: if park() were modified
// to immediately return 0 your code should still work,
// albeit degenerating to a spin loop.
//
// An interesting optimization for park() is to use a trylock()
// to attempt to acquire the mutex. If the trylock() fails
// then we know that a concurrent unpark() operation is in-progress.
// in that case the park() code could simply set _count to 0
// and return immediately. The subsequent park() operation *might*
// return immediately. That's harmless as the caller of park() is
// expected to loop. By using trylock() we will have avoided a
// avoided a context switch caused by contention on the per-thread mutex.
//
// TODO-FIXME:
// 1. Reconcile Doug's JSR166 j.u.c park-unpark with the
// objectmonitor implementation.
// 2. Collapse the JSR166 parker event, and the
// objectmonitor ParkEvent into a single "Event" construct.
// 3. In park() and unpark() add:
// assert (Thread::current() == AssociatedWith).
// 4. add spurious wakeup injection on a -XX:EarlyParkReturn=N switch.
// 1-out-of-N park() operations will return immediately.
//
// _Event transitions in park()
// -1 => -1 : illegal
// 1 => 0 : pass - return immediately
// 0 => -1 : block
//
// _Event serves as a restricted-range semaphore.
//
// Another possible encoding of _Event would be with
// explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
//
// TODO-FIXME: add DTRACE probes for:
// 1. Tx parks
// 2. Ty unparks Tx
// 3. Tx resumes from park
// value determined through experimentation
// utility to compute the abstime argument to timedwait.
// TODO-FIXME: switch from compute_abstime() to unpackTime().
// millis is the relative timeout time
// abstime will be the absolute timeout time
if (UseLWPSynchronization) {
// forward port of fix for 4275818 (not sleeping long enough)
// There was a bug in Solaris 6, 7 and pre-patch 5 of 8 where
// _lwp_cond_timedwait() used a round_down algorithm rather
// than a round_up. For millis less than our roundfactor
// it rounded down to 0 which doesn't meet the spec.
// For millis > roundfactor we may return a bit sooner, but
// since we can not accurately identify the patch level and
// this has already been fixed in Solaris 9 and 8 we will
// leave it alone rather than always rounding down.
// It appears that when we go directly through Solaris _lwp_cond_timedwait()
// the acceptable max time threshold is smaller than for libthread on 2.5.1 and 2.6
max_wait_period = 21000000;
} else {
max_wait_period = 50000000;
}
millis %= 1000;
}
if (usec >= 1000000) {
usec -= 1000000;
}
return abstime;
}
// Test-and-clear _Event, always leaves _Event set to 0, returns immediately.
// Conceptually TryPark() should be equivalent to park(0).
for (;;) {
const int v = _Event ;
}
}
// Invariant: Only the thread associated with the Event/PlatformEvent
// may call park().
int v ;
for (;;) {
v = _Event ;
}
guarantee (v >= 0, "invariant") ;
if (v == 0) {
// Do this the hard way by blocking ...
// TODO-FIXME: for Solaris SPARC set fprs.FEF=0 prior to parking.
// Only for SPARC >= V8PlusA
if (ClearFPUAtPark) { _mark_fpu_nosave() ; }
#endif
++ _nParked ;
while (_Event < 0) {
// for some reason, under 2.7 lwp_cond_wait() may return ETIME ...
// Treat this the same as if the wait was interrupted
}
-- _nParked ;
_Event = 0 ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other.
OrderAccess::fence();
}
}
int v ;
for (;;) {
v = _Event ;
}
guarantee (v >= 0, "invariant") ;
if (v != 0) return OS_OK ;
// For Solaris SPARC set fprs.FEF=0 prior to parking.
// Only for SPARC >= V8PlusA
if (ClearFPUAtPark) { _mark_fpu_nosave() ; }
#endif
++ _nParked ;
while (_Event < 0) {
status, "cond_timedwait");
if (!FilterSpuriousWakeups) break ; // previous semantics
// We consume and ignore EINTR and spurious wakeups.
}
-- _nParked ;
_Event = 0 ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other.
OrderAccess::fence();
return ret;
}
// Transitions for _Event:
// 0 :=> 1
// 1 :=> 1
// -1 :=> either 0 or 1; must signal target thread
// That is, we can safely transition _Event from -1 to either
// 0 or 1. Forcing 1 is slightly more efficient for back-to-back
// unpark() calls.
// See also: "Semaphores in Plan 9" by Mullender & Cox
//
// Note: Forcing a transition from "-1" to "1" on an unpark() means
// that it will take two back-to-back park() calls for the owning
// thread to block. This has the benefit of forcing a spurious return
// from the first park() call after an unpark() call which will help
// shake out uses of park() and unpark() without condition variables.
// If the thread associated with the event was parked, wake it.
// Wait for the thread assoc with the PlatformEvent to vacate.
if (AnyWaiters != 0) {
// We intentional signal *after* dropping the lock
// to avoid a common class of futile wakeups.
}
}
// JSR166
// -------------------------------------------------------
/*
* conservative for now, but can be improved. They currently use a
* Park decrements _counter if > 0, else does a condvar wait. Unpark
* sets count to 1 and signals condvar. Only one thread ever waits
* on the condvar. Contention seen when trying to park implies that someone
* is unparking you, so don't wait. And spurious returns are fine, so there
* is no need to track notifications.
*/
/*
* This code is common to linux and solaris and will be moved to a
* common place in dolphin.
*
* The passed in time value is either a relative time in nanoseconds
* or an absolute time in milliseconds. Either way it has to be unpacked
* into suitable seconds and nanoseconds components and stored in the
* given timespec structure.
* Given time is a 64-bit value and the time_t used in the timespec is only
* a signed-32-bit value (except on 64-bit Linux) we have to watch for
* overflow if times way in the future are given. Further on Solaris versions
* prior to 10 there is a restriction (see cond_timedwait) that the specified
* number of seconds, in abstime, is less than current_time + 100,000,000.
* As it will be 28 years before "now + 100000000" will overflow we can
* ignore overflow and just impose a hard-limit on seconds using the value
* of "now + 100,000,000". This places a limit on the timeout of about 3.17
* years from "now".
*/
if (isAbsolute) {
}
else {
}
}
else {
}
else {
}
}
}
}
// Ideally we'd do something useful while spinning, such
// as calling unpackTime().
// Optional fast-path check:
// Return immediately if a permit is available.
// We depend on Atomic::xchg() having full barrier semantics
// since we are doing a lock-free update to _counter.
// Optional fast-exit: Check interrupt before trying to wait
return;
}
// First, demultiplex/decode time arguments
return;
}
if (time > 0) {
// Warning: this code might be exposed to the old Solaris time
// round-down bugs. Grep "roundingFix" for details.
}
// Enter safepoint region
// Beware of deadlocks such as 6317397.
// The per-thread Parker:: _mutex is a classic leaf-lock.
// In particular a thread must never block on the Threads_lock while
// holding the Parker:: mutex. If safepoints are pending both the
// the ThreadBlockInVM() CTOR and DTOR may grab Threads_lock.
// Don't wait if cannot get lock since interference arises from
// unblocking. Also. check interrupt before trying wait
return;
}
int status ;
if (_counter > 0) { // no wait needed
_counter = 0;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
return;
}
#ifdef ASSERT
// Don't catch signals while blocked; let the running threads have the signals.
// (This allows a debugger to break into the running thread.)
#endif
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
// Do this the hard way by blocking ...
// TODO-FIXME: for Solaris SPARC set fprs.FEF=0 prior to parking.
// Only for SPARC >= V8PlusA
if (ClearFPUAtPark) { _mark_fpu_nosave() ; }
#endif
if (time == 0) {
} else {
}
// Note that an untimed cond_wait() can sometimes return ETIME on older
// versions of the Solaris.
status, "cond_timedwait");
#ifdef ASSERT
#endif
_counter = 0 ;
// Paranoia to ensure our locked and lock-free paths interact
// correctly with each other and Java-level accesses.
OrderAccess::fence();
// If externally suspended while waiting, re-suspend
jt->java_suspend_self();
}
}
int s, status ;
s = _counter;
_counter = 1;
if (s < 1) {
}
}
extern char** environ;
// Run the specified command in a separate process. Return its exit value,
// or -1 on failure (e.g. can't fork a new process).
// Unlike system(), this function can be called from signal handler. It
// doesn't block SIGINT et al.
argv[0] = (char *)"sh";
// fork is async-safe, fork1 is not so can't use in signal handler
if (t != NULL && t->is_inside_signal_handler()) {
} else {
}
if (pid < 0) {
// fork failed
return -1;
} else if (pid == 0) {
// child process
// execve failed
_exit(-1);
} else {
// copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't
// care about the actual exit code, for now.
int status;
// Wait for the child process to exit. This returns immediately if
// the child has already exited. */
switch (errno) {
case ECHILD: return 0;
case EINTR: break;
default: return -1;
}
}
// The child exited normally; get its exit code.
return WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
// The child exited because of a signal
// The best value to return is 0x80 + signal number,
// because that is what all Unix shells do, and because
// it allows callers to distinguish between process exit and
// process death by signal.
} else {
// Unknown exit code; pass it through
return status;
}
}
}
// is_headless_jre()
//
// Test for the existence of xawt/libmawt.so or libawt_xawt.so
// in order to report if we are running in a headless jre
//
// Since JDK8 xawt/libmawt.so was moved into the same directory
// as libawt.so, and renamed libawt_xawt.so
//
char *p;
// Get path to libjvm.so
// Get rid of libjvm.so
if (p == NULL) return false;
else *p = '\0';
// Get rid of client or server
if (p == NULL) return false;
else *p = '\0';
// check xawt/libmawt.so
// check libawt_xawt.so
return true;
}
}
}
}
}
}
}
// As both poll and select can be interrupted by signals, we have to be
// prepared to restart the system call after updating the timeout, unless
// a poll() is done with timeout == -1, in which case we repeat with this
// "wait forever" value.
int res;
struct timeval t;
static const char* aNull = 0;
gettimeofday(&t, &aNull);
for(;;) {
if(timeout != -1) {
gettimeofday(&t, &aNull);
if(timeout <= 0)
return OS_OK;
}
} else return res;
}
}
int _result;
// Depending on when thread interruption is reset, _result could be
// one of two values when errno == EINTR
/* restarting a connect() changes its errno semantics */
/* undo these changes */
errno = 0;
return OS_OK;
}
}
}
return _result;
}
if (fd < 0) {
return OS_ERR;
}
}
}
}
if (fd < 0) {
return OS_OK;
}
int ret;
// note: ioctl can return 0 when successful, JVM_SocketAvailable
// is expected to return 0 on failure and 1 on success to the jdk.
}
}
// Get the default path to the core file
// Returns the length of the string
if (p == NULL) {
return 0;
}
}