comparison src/os/linux/vm/os_linux.cpp @ 12211:2e6938dd68f2

6900441: PlatformEvent.park(millis) on Linux could still be affected by changes to the time-of-day clock Summary: Associate CLOCK_MONOTONIC with the pthread_cond_t objects used for relative timed waits Reviewed-by: dcubed, shade
author dholmes
date Mon, 16 Sep 2013 07:38:13 -0400
parents bb57d48691f5
children 4472884d8b37
comparison
equal deleted inserted replaced
12210:b135b600a66c 12211:2e6938dd68f2
129 bool os::Linux::_is_floating_stack = false; 129 bool os::Linux::_is_floating_stack = false;
130 bool os::Linux::_is_NPTL = false; 130 bool os::Linux::_is_NPTL = false;
131 bool os::Linux::_supports_fast_thread_cpu_time = false; 131 bool os::Linux::_supports_fast_thread_cpu_time = false;
132 const char * os::Linux::_glibc_version = NULL; 132 const char * os::Linux::_glibc_version = NULL;
133 const char * os::Linux::_libpthread_version = NULL; 133 const char * os::Linux::_libpthread_version = NULL;
134 pthread_condattr_t os::Linux::_condattr[1];
134 135
135 static jlong initial_time_count=0; 136 static jlong initial_time_count=0;
136 137
137 static int clock_tics_per_sec = 100; 138 static int clock_tics_per_sec = 100;
138 139
1397 struct timespec tp; 1398 struct timespec tp;
1398 if (clock_getres_func (CLOCK_MONOTONIC, &res) == 0 && 1399 if (clock_getres_func (CLOCK_MONOTONIC, &res) == 0 &&
1399 clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) { 1400 clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) {
1400 // yes, monotonic clock is supported 1401 // yes, monotonic clock is supported
1401 _clock_gettime = clock_gettime_func; 1402 _clock_gettime = clock_gettime_func;
1403 return;
1402 } else { 1404 } else {
1403 // close librt if there is no monotonic clock 1405 // close librt if there is no monotonic clock
1404 dlclose(handle); 1406 dlclose(handle);
1405 } 1407 }
1406 } 1408 }
1407 } 1409 }
1410 warning("No monotonic clock was available - timed services may " \
1411 "be adversely affected if the time-of-day clock changes");
1408 } 1412 }
1409 1413
1410 #ifndef SYS_clock_getres 1414 #ifndef SYS_clock_getres
1411 1415
1412 #if defined(IA32) || defined(AMD64) 1416 #if defined(IA32) || defined(AMD64)
4707 // main_thread points to the aboriginal thread 4711 // main_thread points to the aboriginal thread
4708 Linux::_main_thread = pthread_self(); 4712 Linux::_main_thread = pthread_self();
4709 4713
4710 Linux::clock_init(); 4714 Linux::clock_init();
4711 initial_time_count = os::elapsed_counter(); 4715 initial_time_count = os::elapsed_counter();
4716
4717 // pthread_condattr initialization for monotonic clock
4718 int status;
4719 pthread_condattr_t* _condattr = os::Linux::condAttr();
4720 if ((status = pthread_condattr_init(_condattr)) != 0) {
4721 fatal(err_msg("pthread_condattr_init: %s", strerror(status)));
4722 }
4723 // Only set the clock if CLOCK_MONOTONIC is available
4724 if (Linux::supports_monotonic_clock()) {
4725 if ((status = pthread_condattr_setclock(_condattr, CLOCK_MONOTONIC)) != 0) {
4726 if (status == EINVAL) {
4727 warning("Unable to use monotonic clock with relative timed-waits" \
4728 " - changes to the time-of-day clock may have adverse affects");
4729 } else {
4730 fatal(err_msg("pthread_condattr_setclock: %s", strerror(status)));
4731 }
4732 }
4733 }
4734 // else it defaults to CLOCK_REALTIME
4735
4712 pthread_mutex_init(&dl_mutex, NULL); 4736 pthread_mutex_init(&dl_mutex, NULL);
4713 4737
4714 // If the pagesize of the VM is greater than 8K determine the appropriate 4738 // If the pagesize of the VM is greater than 8K determine the appropriate
4715 // number of initial guard pages. The user can change this with the 4739 // number of initial guard pages. The user can change this with the
4716 // command line arguments, if needed. 4740 // command line arguments, if needed.
5517 // abstime will be the absolute timeout time 5541 // abstime will be the absolute timeout time
5518 // TODO: replace compute_abstime() with unpackTime() 5542 // TODO: replace compute_abstime() with unpackTime()
5519 5543
5520 static struct timespec* compute_abstime(timespec* abstime, jlong millis) { 5544 static struct timespec* compute_abstime(timespec* abstime, jlong millis) {
5521 if (millis < 0) millis = 0; 5545 if (millis < 0) millis = 0;
5522 struct timeval now; 5546
5523 int status = gettimeofday(&now, NULL);
5524 assert(status == 0, "gettimeofday");
5525 jlong seconds = millis / 1000; 5547 jlong seconds = millis / 1000;
5526 millis %= 1000; 5548 millis %= 1000;
5527 if (seconds > 50000000) { // see man cond_timedwait(3T) 5549 if (seconds > 50000000) { // see man cond_timedwait(3T)
5528 seconds = 50000000; 5550 seconds = 50000000;
5529 } 5551 }
5530 abstime->tv_sec = now.tv_sec + seconds; 5552
5531 long usec = now.tv_usec + millis * 1000; 5553 if (os::Linux::supports_monotonic_clock()) {
5532 if (usec >= 1000000) { 5554 struct timespec now;
5533 abstime->tv_sec += 1; 5555 int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now);
5534 usec -= 1000000; 5556 assert_status(status == 0, status, "clock_gettime");
5535 } 5557 abstime->tv_sec = now.tv_sec + seconds;
5536 abstime->tv_nsec = usec * 1000; 5558 long nanos = now.tv_nsec + millis * NANOSECS_PER_MILLISEC;
5559 if (nanos >= NANOSECS_PER_SEC) {
5560 abstime->tv_sec += 1;
5561 nanos -= NANOSECS_PER_SEC;
5562 }
5563 abstime->tv_nsec = nanos;
5564 } else {
5565 struct timeval now;
5566 int status = gettimeofday(&now, NULL);
5567 assert(status == 0, "gettimeofday");
5568 abstime->tv_sec = now.tv_sec + seconds;
5569 long usec = now.tv_usec + millis * 1000;
5570 if (usec >= 1000000) {
5571 abstime->tv_sec += 1;
5572 usec -= 1000000;
5573 }
5574 abstime->tv_nsec = usec * 1000;
5575 }
5537 return abstime; 5576 return abstime;
5538 } 5577 }
5539 5578
5540 5579
5541 // Test-and-clear _Event, always leaves _Event set to 0, returns immediately. 5580 // Test-and-clear _Event, always leaves _Event set to 0, returns immediately.
5623 5662
5624 while (_Event < 0) { 5663 while (_Event < 0) {
5625 status = os::Linux::safe_cond_timedwait(_cond, _mutex, &abst); 5664 status = os::Linux::safe_cond_timedwait(_cond, _mutex, &abst);
5626 if (status != 0 && WorkAroundNPTLTimedWaitHang) { 5665 if (status != 0 && WorkAroundNPTLTimedWaitHang) {
5627 pthread_cond_destroy (_cond); 5666 pthread_cond_destroy (_cond);
5628 pthread_cond_init (_cond, NULL) ; 5667 pthread_cond_init (_cond, os::Linux::condAttr()) ;
5629 } 5668 }
5630 assert_status(status == 0 || status == EINTR || 5669 assert_status(status == 0 || status == EINTR ||
5631 status == ETIME || status == ETIMEDOUT, 5670 status == ETIME || status == ETIMEDOUT,
5632 status, "cond_timedwait"); 5671 status, "cond_timedwait");
5633 if (!FilterSpuriousWakeups) break ; // previous semantics 5672 if (!FilterSpuriousWakeups) break ; // previous semantics
5724 * years from "now". 5763 * years from "now".
5725 */ 5764 */
5726 5765
5727 static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { 5766 static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
5728 assert (time > 0, "convertTime"); 5767 assert (time > 0, "convertTime");
5729 5768 time_t max_secs = 0;
5730 struct timeval now; 5769
5731 int status = gettimeofday(&now, NULL); 5770 if (!os::Linux::supports_monotonic_clock() || isAbsolute) {
5732 assert(status == 0, "gettimeofday"); 5771 struct timeval now;
5733 5772 int status = gettimeofday(&now, NULL);
5734 time_t max_secs = now.tv_sec + MAX_SECS; 5773 assert(status == 0, "gettimeofday");
5735 5774
5736 if (isAbsolute) { 5775 max_secs = now.tv_sec + MAX_SECS;
5737 jlong secs = time / 1000; 5776
5738 if (secs > max_secs) { 5777 if (isAbsolute) {
5739 absTime->tv_sec = max_secs; 5778 jlong secs = time / 1000;
5740 } 5779 if (secs > max_secs) {
5741 else { 5780 absTime->tv_sec = max_secs;
5742 absTime->tv_sec = secs; 5781 } else {
5743 } 5782 absTime->tv_sec = secs;
5744 absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; 5783 }
5745 } 5784 absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC;
5746 else { 5785 } else {
5786 jlong secs = time / NANOSECS_PER_SEC;
5787 if (secs >= MAX_SECS) {
5788 absTime->tv_sec = max_secs;
5789 absTime->tv_nsec = 0;
5790 } else {
5791 absTime->tv_sec = now.tv_sec + secs;
5792 absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000;
5793 if (absTime->tv_nsec >= NANOSECS_PER_SEC) {
5794 absTime->tv_nsec -= NANOSECS_PER_SEC;
5795 ++absTime->tv_sec; // note: this must be <= max_secs
5796 }
5797 }
5798 }
5799 } else {
5800 // must be relative using monotonic clock
5801 struct timespec now;
5802 int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now);
5803 assert_status(status == 0, status, "clock_gettime");
5804 max_secs = now.tv_sec + MAX_SECS;
5747 jlong secs = time / NANOSECS_PER_SEC; 5805 jlong secs = time / NANOSECS_PER_SEC;
5748 if (secs >= MAX_SECS) { 5806 if (secs >= MAX_SECS) {
5749 absTime->tv_sec = max_secs; 5807 absTime->tv_sec = max_secs;
5750 absTime->tv_nsec = 0; 5808 absTime->tv_nsec = 0;
5751 } 5809 } else {
5752 else {
5753 absTime->tv_sec = now.tv_sec + secs; 5810 absTime->tv_sec = now.tv_sec + secs;
5754 absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000; 5811 absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_nsec;
5755 if (absTime->tv_nsec >= NANOSECS_PER_SEC) { 5812 if (absTime->tv_nsec >= NANOSECS_PER_SEC) {
5756 absTime->tv_nsec -= NANOSECS_PER_SEC; 5813 absTime->tv_nsec -= NANOSECS_PER_SEC;
5757 ++absTime->tv_sec; // note: this must be <= max_secs 5814 ++absTime->tv_sec; // note: this must be <= max_secs
5758 } 5815 }
5759 } 5816 }
5829 5886
5830 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */); 5887 OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
5831 jt->set_suspend_equivalent(); 5888 jt->set_suspend_equivalent();
5832 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() 5889 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
5833 5890
5891 assert(_cur_index == -1, "invariant");
5834 if (time == 0) { 5892 if (time == 0) {
5835 status = pthread_cond_wait (_cond, _mutex) ; 5893 _cur_index = REL_INDEX; // arbitrary choice when not timed
5894 status = pthread_cond_wait (&_cond[_cur_index], _mutex) ;
5836 } else { 5895 } else {
5837 status = os::Linux::safe_cond_timedwait (_cond, _mutex, &absTime) ; 5896 _cur_index = isAbsolute ? ABS_INDEX : REL_INDEX;
5897 status = os::Linux::safe_cond_timedwait (&_cond[_cur_index], _mutex, &absTime) ;
5838 if (status != 0 && WorkAroundNPTLTimedWaitHang) { 5898 if (status != 0 && WorkAroundNPTLTimedWaitHang) {
5839 pthread_cond_destroy (_cond) ; 5899 pthread_cond_destroy (&_cond[_cur_index]) ;
5840 pthread_cond_init (_cond, NULL); 5900 pthread_cond_init (&_cond[_cur_index], isAbsolute ? NULL : os::Linux::condAttr());
5841 } 5901 }
5842 } 5902 }
5903 _cur_index = -1;
5843 assert_status(status == 0 || status == EINTR || 5904 assert_status(status == 0 || status == EINTR ||
5844 status == ETIME || status == ETIMEDOUT, 5905 status == ETIME || status == ETIMEDOUT,
5845 status, "cond_timedwait"); 5906 status, "cond_timedwait");
5846 5907
5847 #ifdef ASSERT 5908 #ifdef ASSERT
5866 status = pthread_mutex_lock(_mutex); 5927 status = pthread_mutex_lock(_mutex);
5867 assert (status == 0, "invariant") ; 5928 assert (status == 0, "invariant") ;
5868 s = _counter; 5929 s = _counter;
5869 _counter = 1; 5930 _counter = 1;
5870 if (s < 1) { 5931 if (s < 1) {
5871 if (WorkAroundNPTLTimedWaitHang) { 5932 // thread might be parked
5872 status = pthread_cond_signal (_cond) ; 5933 if (_cur_index != -1) {
5873 assert (status == 0, "invariant") ; 5934 // thread is definitely parked
5935 if (WorkAroundNPTLTimedWaitHang) {
5936 status = pthread_cond_signal (&_cond[_cur_index]);
5937 assert (status == 0, "invariant");
5874 status = pthread_mutex_unlock(_mutex); 5938 status = pthread_mutex_unlock(_mutex);
5875 assert (status == 0, "invariant") ; 5939 assert (status == 0, "invariant");
5876 } else { 5940 } else {
5877 status = pthread_mutex_unlock(_mutex); 5941 status = pthread_mutex_unlock(_mutex);
5878 assert (status == 0, "invariant") ; 5942 assert (status == 0, "invariant");
5879 status = pthread_cond_signal (_cond) ; 5943 status = pthread_cond_signal (&_cond[_cur_index]);
5880 assert (status == 0, "invariant") ; 5944 assert (status == 0, "invariant");
5881 } 5945 }
5946 } else {
5947 pthread_mutex_unlock(_mutex);
5948 assert (status == 0, "invariant") ;
5949 }
5882 } else { 5950 } else {
5883 pthread_mutex_unlock(_mutex); 5951 pthread_mutex_unlock(_mutex);
5884 assert (status == 0, "invariant") ; 5952 assert (status == 0, "invariant") ;
5885 } 5953 }
5886 } 5954 }