1067 // this unconditionally, so we do it.
1068 //
1069 // See: https://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.basetrf2/read_real_time.htm
1070 //
1071 // On PASE: mread_real_time will always return RTC_POWER_PC data, so no
1072 // conversion is necessary. However, mread_real_time will not return
1073 // monotonic results but merely matches read_real_time. So we need a tweak
1074 // to ensure monotonic results.
1075 //
1076 // For PASE no public documentation exists, just word by IBM
1077 jlong os::javaTimeNanos() {
1078 timebasestruct_t time;
1079 int rc = mread_real_time(&time, TIMEBASE_SZ);
1080 if (os::Aix::on_pase()) {
1081 assert(rc == RTC_POWER, "expected time format RTC_POWER from mread_real_time in PASE");
1082 jlong now = jlong(time.tb_high) * NANOSECS_PER_SEC + jlong(time.tb_low);
1083 jlong prev = max_real_time;
1084 if (now <= prev) {
1085 return prev; // same or retrograde time;
1086 }
1087 jlong obsv = Atomic::cmpxchg(now, &max_real_time, prev);
1088 assert(obsv >= prev, "invariant"); // Monotonicity
1089 // If the CAS succeeded then we're done and return "now".
1090 // If the CAS failed and the observed value "obsv" is >= now then
1091 // we should return "obsv". If the CAS failed and now > obsv > prv then
1092 // some other thread raced this thread and installed a new value, in which case
1093 // we could either (a) retry the entire operation, (b) retry trying to install now
1094 // or (c) just return obsv. We use (c). No loop is required although in some cases
1095 // we might discard a higher "now" value in deference to a slightly lower but freshly
1096 // installed obsv value. That's entirely benign -- it admits no new orderings compared
1097 // to (a) or (b) -- and greatly reduces coherence traffic.
1098 // We might also condition (c) on the magnitude of the delta between obsv and now.
1099 // Avoiding excessive CAS operations to hot RW locations is critical.
1100 // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate
1101 return (prev == obsv) ? now : obsv;
1102 } else {
1103 if (rc != RTC_POWER) {
1104 rc = time_base_to_time(&time, TIMEBASE_SZ);
1105 assert(rc != -1, "error calling time_base_to_time()");
1106 }
1107 return jlong(time.tb_high) * NANOSECS_PER_SEC + jlong(time.tb_low);
1777 }
1778 }
1779
1780 static void jdk_misc_signal_init() {
1781 // Initialize signal structures
1782 ::memset((void*)pending_signals, 0, sizeof(pending_signals));
1783
1784 // Initialize signal semaphore
1785 local_sem_init();
1786 }
1787
1788 void os::signal_notify(int sig) {
1789 Atomic::inc(&pending_signals[sig]);
1790 local_sem_post();
1791 }
1792
1793 static int check_pending_signals() {
1794 for (;;) {
1795 for (int i = 0; i < NSIG + 1; i++) {
1796 jint n = pending_signals[i];
1797 if (n > 0 && n == Atomic::cmpxchg(n - 1, &pending_signals[i], n)) {
1798 return i;
1799 }
1800 }
1801 JavaThread *thread = JavaThread::current();
1802 ThreadBlockInVM tbivm(thread);
1803
1804 bool threadIsSuspended;
1805 do {
1806 thread->set_suspend_equivalent();
1807 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
1808
1809 local_sem_wait();
1810
1811 // were we externally suspended while we were waiting?
1812 threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
1813 if (threadIsSuspended) {
1814 //
1815 // The semaphore has been incremented, but while we were waiting
1816 // another thread suspended us. We don't want to continue running
1817 // while suspended because that would surprise the thread that
|
1067 // this unconditionally, so we do it.
1068 //
1069 // See: https://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.basetrf2/read_real_time.htm
1070 //
1071 // On PASE: mread_real_time will always return RTC_POWER_PC data, so no
1072 // conversion is necessary. However, mread_real_time will not return
1073 // monotonic results but merely matches read_real_time. So we need a tweak
1074 // to ensure monotonic results.
1075 //
1076 // For PASE no public documentation exists, just word by IBM
1077 jlong os::javaTimeNanos() {
1078 timebasestruct_t time;
1079 int rc = mread_real_time(&time, TIMEBASE_SZ);
1080 if (os::Aix::on_pase()) {
1081 assert(rc == RTC_POWER, "expected time format RTC_POWER from mread_real_time in PASE");
1082 jlong now = jlong(time.tb_high) * NANOSECS_PER_SEC + jlong(time.tb_low);
1083 jlong prev = max_real_time;
1084 if (now <= prev) {
1085 return prev; // same or retrograde time;
1086 }
1087 jlong obsv = Atomic::cmpxchg(&max_real_time, prev, now);
1088 assert(obsv >= prev, "invariant"); // Monotonicity
1089 // If the CAS succeeded then we're done and return "now".
1090 // If the CAS failed and the observed value "obsv" is >= now then
1091 // we should return "obsv". If the CAS failed and now > obsv > prv then
1092 // some other thread raced this thread and installed a new value, in which case
1093 // we could either (a) retry the entire operation, (b) retry trying to install now
1094 // or (c) just return obsv. We use (c). No loop is required although in some cases
1095 // we might discard a higher "now" value in deference to a slightly lower but freshly
1096 // installed obsv value. That's entirely benign -- it admits no new orderings compared
1097 // to (a) or (b) -- and greatly reduces coherence traffic.
1098 // We might also condition (c) on the magnitude of the delta between obsv and now.
1099 // Avoiding excessive CAS operations to hot RW locations is critical.
1100 // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate
1101 return (prev == obsv) ? now : obsv;
1102 } else {
1103 if (rc != RTC_POWER) {
1104 rc = time_base_to_time(&time, TIMEBASE_SZ);
1105 assert(rc != -1, "error calling time_base_to_time()");
1106 }
1107 return jlong(time.tb_high) * NANOSECS_PER_SEC + jlong(time.tb_low);
1777 }
1778 }
1779
1780 static void jdk_misc_signal_init() {
1781 // Initialize signal structures
1782 ::memset((void*)pending_signals, 0, sizeof(pending_signals));
1783
1784 // Initialize signal semaphore
1785 local_sem_init();
1786 }
1787
1788 void os::signal_notify(int sig) {
1789 Atomic::inc(&pending_signals[sig]);
1790 local_sem_post();
1791 }
1792
1793 static int check_pending_signals() {
1794 for (;;) {
1795 for (int i = 0; i < NSIG + 1; i++) {
1796 jint n = pending_signals[i];
1797 if (n > 0 && n == Atomic::cmpxchg(&pending_signals[i], n, n - 1)) {
1798 return i;
1799 }
1800 }
1801 JavaThread *thread = JavaThread::current();
1802 ThreadBlockInVM tbivm(thread);
1803
1804 bool threadIsSuspended;
1805 do {
1806 thread->set_suspend_equivalent();
1807 // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
1808
1809 local_sem_wait();
1810
1811 // were we externally suspended while we were waiting?
1812 threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
1813 if (threadIsSuspended) {
1814 //
1815 // The semaphore has been incremented, but while we were waiting
1816 // another thread suspended us. We don't want to continue running
1817 // while suspended because that would surprise the thread that
|