< prev index next >

src/os/linux/vm/os_linux.cpp

Print this page

        

*** 143,153 **** int os::Linux::_page_size = -1; bool os::Linux::_supports_fast_thread_cpu_time = false; uint32_t os::Linux::_os_version = 0; const char * os::Linux::_glibc_version = NULL; const char * os::Linux::_libpthread_version = NULL; - pthread_condattr_t os::Linux::_condattr[1]; static jlong initial_time_count=0; static int clock_tics_per_sec = 100; --- 143,152 ----
*** 159,171 **** // do not use any signal number less than SIGSEGV, see 4355769 static int SR_signum = SIGUSR2; sigset_t SR_sigset; - // Declarations - static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); - // utility functions static int SR_initialize(); julong os::available_memory() { --- 158,167 ----
*** 384,394 **** //////////////////////////////////////////////////////////////////////////////// // signal support debug_only(static bool signal_sets_initialized = false); ! static sigset_t unblocked_sigs, vm_sigs, allowdebug_blocked_sigs; bool os::Linux::is_sig_ignored(int sig) { struct sigaction oact; sigaction(sig, (struct sigaction*)NULL, &oact); void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction) --- 380,390 ---- //////////////////////////////////////////////////////////////////////////////// // signal support debug_only(static bool signal_sets_initialized = false); ! static sigset_t unblocked_sigs, vm_sigs; bool os::Linux::is_sig_ignored(int sig) { struct sigaction oact; sigaction(sig, (struct sigaction*)NULL, &oact); void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction)
*** 415,425 **** // 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. sigemptyset(&unblocked_sigs); - sigemptyset(&allowdebug_blocked_sigs); sigaddset(&unblocked_sigs, SIGILL); sigaddset(&unblocked_sigs, SIGSEGV); sigaddset(&unblocked_sigs, SIGBUS); sigaddset(&unblocked_sigs, SIGFPE); #if defined(PPC64) --- 411,420 ----
*** 428,446 **** sigaddset(&unblocked_sigs, SR_signum); if (!ReduceSignalUsage) { if (!os::Linux::is_sig_ignored(SHUTDOWN1_SIGNAL)) { sigaddset(&unblocked_sigs, SHUTDOWN1_SIGNAL); - sigaddset(&allowdebug_blocked_sigs, SHUTDOWN1_SIGNAL); } if (!os::Linux::is_sig_ignored(SHUTDOWN2_SIGNAL)) { sigaddset(&unblocked_sigs, SHUTDOWN2_SIGNAL); - sigaddset(&allowdebug_blocked_sigs, SHUTDOWN2_SIGNAL); } if (!os::Linux::is_sig_ignored(SHUTDOWN3_SIGNAL)) { sigaddset(&unblocked_sigs, SHUTDOWN3_SIGNAL); - sigaddset(&allowdebug_blocked_sigs, SHUTDOWN3_SIGNAL); } } // Fill in signals that are blocked by all but the VM thread. sigemptyset(&vm_sigs); if (!ReduceSignalUsage) { --- 423,438 ----
*** 462,477 **** sigset_t* os::Linux::vm_signals() { assert(signal_sets_initialized, "Not initialized"); return &vm_sigs; } - // These are signals that are blocked during cond_wait to allow debugger in - sigset_t* os::Linux::allowdebug_blocked_signals() { - assert(signal_sets_initialized, "Not initialized"); - return &allowdebug_blocked_sigs; - } - void os::Linux::hotspot_sigmask(Thread* thread) { //Save caller's signal mask before setting VM signal mask sigset_t caller_sigmask; pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask); --- 454,463 ----
*** 4746,4778 **** Linux::_main_thread = pthread_self(); Linux::clock_init(); initial_time_count = javaTimeNanos(); - // pthread_condattr initialization for monotonic clock - int status; - pthread_condattr_t* _condattr = os::Linux::condAttr(); - if ((status = pthread_condattr_init(_condattr)) != 0) { - fatal("pthread_condattr_init: %s", os::strerror(status)); - } - // Only set the clock if CLOCK_MONOTONIC is available - if (os::supports_monotonic_clock()) { - if ((status = pthread_condattr_setclock(_condattr, CLOCK_MONOTONIC)) != 0) { - if (status == EINVAL) { - warning("Unable to use monotonic clock with relative timed-waits" \ - " - changes to the time-of-day clock may have adverse affects"); - } else { - fatal("pthread_condattr_setclock: %s", os::strerror(status)); - } - } - } - // else it defaults to CLOCK_REALTIME - // retrieve entry point for pthread_setname_np Linux::_pthread_setname_np = (int(*)(pthread_t, const char*))dlsym(RTLD_DEFAULT, "pthread_setname_np"); } // To install functions for atexit system call extern "C" { static void perfMemory_exit_helper() { --- 4732,4746 ---- Linux::_main_thread = pthread_self(); Linux::clock_init(); initial_time_count = javaTimeNanos(); // retrieve entry point for pthread_setname_np Linux::_pthread_setname_np = (int(*)(pthread_t, const char*))dlsym(RTLD_DEFAULT, "pthread_setname_np"); + os::Posix::init(); } // To install functions for atexit system call extern "C" { static void perfMemory_exit_helper() {
*** 4780,4789 **** --- 4748,4760 ---- } } // this is called _after_ the global arguments have been parsed jint os::init_2(void) { + + os::Posix::init_2(); + Linux::fast_thread_clock_init(); // Allocate a single page and mark it as readable for safepoint polling address polling_page = (address) ::mmap(NULL, Linux::page_size(), PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); guarantee(polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page");
*** 5500,5909 **** jio_fprintf(stderr, "Could not open pause file '%s', continuing immediately.\n", filename); } } - - // Refer to the comments in os_solaris.cpp park-unpark. The next two - // comment paragraphs are worth repeating here: - // - // Assumption: - // Only one parker can exist on an event, which is why we allocate - // them per-thread. Multiple unparkers can coexist. - // - // _Event serves as a restricted-range semaphore. - // -1 : thread is blocked, i.e. there is a waiter - // 0 : neutral: thread is running or ready, - // could have been signaled after a wait started - // 1 : signaled - thread is running or ready - // - - // utility to compute the abstime argument to timedwait: - // millis is the relative timeout time - // abstime will be the absolute timeout time - // TODO: replace compute_abstime() with unpackTime() - - static struct timespec* compute_abstime(timespec* abstime, jlong millis) { - if (millis < 0) millis = 0; - - jlong seconds = millis / 1000; - millis %= 1000; - if (seconds > 50000000) { // see man cond_timedwait(3T) - seconds = 50000000; - } - - if (os::supports_monotonic_clock()) { - struct timespec now; - int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now); - assert_status(status == 0, status, "clock_gettime"); - abstime->tv_sec = now.tv_sec + seconds; - long nanos = now.tv_nsec + millis * NANOSECS_PER_MILLISEC; - if (nanos >= NANOSECS_PER_SEC) { - abstime->tv_sec += 1; - nanos -= NANOSECS_PER_SEC; - } - abstime->tv_nsec = nanos; - } else { - struct timeval now; - int status = gettimeofday(&now, NULL); - assert(status == 0, "gettimeofday"); - abstime->tv_sec = now.tv_sec + seconds; - long usec = now.tv_usec + millis * 1000; - if (usec >= 1000000) { - abstime->tv_sec += 1; - usec -= 1000000; - } - abstime->tv_nsec = usec * 1000; - } - return abstime; - } - - void os::PlatformEvent::park() { // AKA "down()" - // Transitions for _Event: - // -1 => -1 : illegal - // 1 => 0 : pass - return immediately - // 0 => -1 : block; then set _Event to 0 before returning - - // Invariant: Only the thread associated with the Event/PlatformEvent - // may call park(). - // TODO: assert that _Assoc != NULL or _Assoc == Self - assert(_nParked == 0, "invariant"); - - int v; - for (;;) { - v = _Event; - if (Atomic::cmpxchg(v-1, &_Event, v) == v) break; - } - guarantee(v >= 0, "invariant"); - if (v == 0) { - // Do this the hard way by blocking ... - int status = pthread_mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - guarantee(_nParked == 0, "invariant"); - ++_nParked; - while (_Event < 0) { - status = pthread_cond_wait(_cond, _mutex); - // for some reason, under 2.7 lwp_cond_wait() may return ETIME ... - // Treat this the same as if the wait was interrupted - if (status == ETIME) { status = EINTR; } - assert_status(status == 0 || status == EINTR, status, "cond_wait"); - } - --_nParked; - - _Event = 0; - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - // Paranoia to ensure our locked and lock-free paths interact - // correctly with each other. - OrderAccess::fence(); - } - guarantee(_Event >= 0, "invariant"); - } - - int os::PlatformEvent::park(jlong millis) { - // Transitions for _Event: - // -1 => -1 : illegal - // 1 => 0 : pass - return immediately - // 0 => -1 : block; then set _Event to 0 before returning - - guarantee(_nParked == 0, "invariant"); - - int v; - for (;;) { - v = _Event; - if (Atomic::cmpxchg(v-1, &_Event, v) == v) break; - } - guarantee(v >= 0, "invariant"); - if (v != 0) return OS_OK; - - // We do this the hard way, by blocking the thread. - // Consider enforcing a minimum timeout value. - struct timespec abst; - compute_abstime(&abst, millis); - - int ret = OS_TIMEOUT; - int status = pthread_mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - guarantee(_nParked == 0, "invariant"); - ++_nParked; - - // Object.wait(timo) will return because of - // (a) notification - // (b) timeout - // (c) thread.interrupt - // - // Thread.interrupt and object.notify{All} both call Event::set. - // That is, we treat thread.interrupt as a special case of notification. - // We ignore spurious OS wakeups unless FilterSpuriousWakeups is false. - // We assume all ETIME returns are valid. - // - // TODO: properly differentiate simultaneous notify+interrupt. - // In that case, we should propagate the notify to another waiter. - - while (_Event < 0) { - status = pthread_cond_timedwait(_cond, _mutex, &abst); - assert_status(status == 0 || status == EINTR || - status == ETIME || status == ETIMEDOUT, - status, "cond_timedwait"); - if (!FilterSpuriousWakeups) break; // previous semantics - if (status == ETIME || status == ETIMEDOUT) break; - // We consume and ignore EINTR and spurious wakeups. - } - --_nParked; - if (_Event >= 0) { - ret = OS_OK; - } - _Event = 0; - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - assert(_nParked == 0, "invariant"); - // Paranoia to ensure our locked and lock-free paths interact - // correctly with each other. - OrderAccess::fence(); - return ret; - } - - void os::PlatformEvent::unpark() { - // Transitions for _Event: - // 0 => 1 : just return - // 1 => 1 : just return - // -1 => either 0 or 1; must signal target thread - // That is, we can safely transition _Event from -1 to either - // 0 or 1. - // 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 (Atomic::xchg(1, &_Event) >= 0) return; - - // Wait for the thread associated with the event to vacate - int status = pthread_mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - int AnyWaiters = _nParked; - assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - if (AnyWaiters != 0) { - // Note that we signal() *after* dropping the lock for "immortal" Events. - // This is safe and avoids a common class of futile wakeups. In rare - // circumstances this can cause a thread to return prematurely from - // cond_{timed}wait() but the spurious wakeup is benign and the victim - // will simply re-test the condition and re-park itself. - // This provides particular benefit if the underlying platform does not - // provide wait morphing. - status = pthread_cond_signal(_cond); - assert_status(status == 0, status, "cond_signal"); - } - } - - - // JSR166 - // ------------------------------------------------------- - - // The solaris and linux implementations of park/unpark are fairly - // conservative for now, but can be improved. They currently use a - // mutex/condvar pair, plus a a count. - // Park decrements count 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". - - static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { - assert(time > 0, "convertTime"); - time_t max_secs = 0; - - if (!os::supports_monotonic_clock() || isAbsolute) { - struct timeval now; - int status = gettimeofday(&now, NULL); - assert(status == 0, "gettimeofday"); - - max_secs = now.tv_sec + MAX_SECS; - - if (isAbsolute) { - jlong secs = time / 1000; - if (secs > max_secs) { - absTime->tv_sec = max_secs; - } else { - absTime->tv_sec = secs; - } - absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; - } else { - jlong secs = time / NANOSECS_PER_SEC; - if (secs >= MAX_SECS) { - absTime->tv_sec = max_secs; - absTime->tv_nsec = 0; - } else { - absTime->tv_sec = now.tv_sec + secs; - absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000; - if (absTime->tv_nsec >= NANOSECS_PER_SEC) { - absTime->tv_nsec -= NANOSECS_PER_SEC; - ++absTime->tv_sec; // note: this must be <= max_secs - } - } - } - } else { - // must be relative using monotonic clock - struct timespec now; - int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now); - assert_status(status == 0, status, "clock_gettime"); - max_secs = now.tv_sec + MAX_SECS; - jlong secs = time / NANOSECS_PER_SEC; - if (secs >= MAX_SECS) { - absTime->tv_sec = max_secs; - absTime->tv_nsec = 0; - } else { - absTime->tv_sec = now.tv_sec + secs; - absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_nsec; - if (absTime->tv_nsec >= NANOSECS_PER_SEC) { - absTime->tv_nsec -= NANOSECS_PER_SEC; - ++absTime->tv_sec; // note: this must be <= max_secs - } - } - } - assert(absTime->tv_sec >= 0, "tv_sec < 0"); - assert(absTime->tv_sec <= max_secs, "tv_sec > max_secs"); - assert(absTime->tv_nsec >= 0, "tv_nsec < 0"); - assert(absTime->tv_nsec < NANOSECS_PER_SEC, "tv_nsec >= nanos_per_sec"); - } - - void Parker::park(bool isAbsolute, jlong time) { - // 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. - if (Atomic::xchg(0, &_counter) > 0) return; - - Thread* thread = Thread::current(); - assert(thread->is_Java_thread(), "Must be JavaThread"); - JavaThread *jt = (JavaThread *)thread; - - // Optional optimization -- avoid state transitions if there's an interrupt pending. - // Check interrupt before trying to wait - if (Thread::is_interrupted(thread, false)) { - return; - } - - // Next, demultiplex/decode time arguments - timespec absTime; - if (time < 0 || (isAbsolute && time == 0)) { // don't wait at all - return; - } - if (time > 0) { - unpackTime(&absTime, isAbsolute, time); - } - - - // 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. - ThreadBlockInVM tbivm(jt); - - // Don't wait if cannot get lock since interference arises from - // unblocking. Also. check interrupt before trying wait - if (Thread::is_interrupted(thread, false) || pthread_mutex_trylock(_mutex) != 0) { - return; - } - - int status; - if (_counter > 0) { // no wait needed - _counter = 0; - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "invariant"); - // 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.) - sigset_t oldsigs; - sigemptyset(&oldsigs); - sigset_t* allowdebug_blocked = os::Linux::allowdebug_blocked_signals(); - pthread_sigmask(SIG_BLOCK, allowdebug_blocked, &oldsigs); - #endif - - OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); - jt->set_suspend_equivalent(); - // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() - - assert(_cur_index == -1, "invariant"); - if (time == 0) { - _cur_index = REL_INDEX; // arbitrary choice when not timed - status = pthread_cond_wait(&_cond[_cur_index], _mutex); - } else { - _cur_index = isAbsolute ? ABS_INDEX : REL_INDEX; - status = pthread_cond_timedwait(&_cond[_cur_index], _mutex, &absTime); - } - _cur_index = -1; - assert_status(status == 0 || status == EINTR || - status == ETIME || status == ETIMEDOUT, - status, "cond_timedwait"); - - #ifdef ASSERT - pthread_sigmask(SIG_SETMASK, &oldsigs, NULL); - #endif - - _counter = 0; - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "invariant"); - // 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 - if (jt->handle_special_suspend_equivalent_condition()) { - jt->java_suspend_self(); - } - } - - void Parker::unpark() { - int status = pthread_mutex_lock(_mutex); - assert_status(status == 0, status, "invariant"); - const int s = _counter; - _counter = 1; - // must capture correct index before unlocking - int index = _cur_index; - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "invariant"); - if (s < 1 && index != -1) { - // thread is definitely parked - status = pthread_cond_signal(&_cond[index]); - assert_status(status == 0, status, "invariant"); - } - } - - 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 --- 5471,5480 ----
< prev index next >