Mercurial > hg > graal-jvmci-8
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 } |