105 void do_void(){ |
105 void do_void(){ |
106 _cm->cleanup(); |
106 _cm->cleanup(); |
107 } |
107 } |
108 }; |
108 }; |
109 |
109 |
110 double G1ConcurrentMarkThread::mmu_sleep_time(G1Policy* g1_policy, bool remark) { |
110 double G1ConcurrentMarkThread::mmu_delay_end(G1Policy* g1_policy, bool remark) { |
111 // There are 3 reasons to use SuspendibleThreadSetJoiner. |
111 // There are 3 reasons to use SuspendibleThreadSetJoiner. |
112 // 1. To avoid concurrency problem. |
112 // 1. To avoid concurrency problem. |
113 // - G1MMUTracker::add_pause(), when_sec() and its variation(when_ms() etc..) can be called |
113 // - G1MMUTracker::add_pause(), when_sec() and its variation(when_ms() etc..) can be called |
114 // concurrently from ConcurrentMarkThread and VMThread. |
114 // concurrently from ConcurrentMarkThread and VMThread. |
115 // 2. If currently a gc is running, but it has not yet updated the MMU, |
115 // 2. If currently a gc is running, but it has not yet updated the MMU, |
117 // 3. If currently a gc is running, ConcurrentMarkThread will wait it to be finished. |
117 // 3. If currently a gc is running, ConcurrentMarkThread will wait it to be finished. |
118 // And then sleep for predicted amount of time by delay_to_keep_mmu(). |
118 // And then sleep for predicted amount of time by delay_to_keep_mmu(). |
119 SuspendibleThreadSetJoiner sts_join; |
119 SuspendibleThreadSetJoiner sts_join; |
120 |
120 |
121 const G1Analytics* analytics = g1_policy->analytics(); |
121 const G1Analytics* analytics = g1_policy->analytics(); |
122 double now = os::elapsedTime(); |
|
123 double prediction_ms = remark ? analytics->predict_remark_time_ms() |
122 double prediction_ms = remark ? analytics->predict_remark_time_ms() |
124 : analytics->predict_cleanup_time_ms(); |
123 : analytics->predict_cleanup_time_ms(); |
|
124 double prediction = prediction_ms / MILLIUNITS; |
125 G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker(); |
125 G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker(); |
126 return mmu_tracker->when_ms(now, prediction_ms); |
126 double now = os::elapsedTime(); |
|
127 return now + mmu_tracker->when_sec(now, prediction); |
127 } |
128 } |
128 |
129 |
129 void G1ConcurrentMarkThread::delay_to_keep_mmu(G1Policy* g1_policy, bool remark) { |
130 void G1ConcurrentMarkThread::delay_to_keep_mmu(G1Policy* g1_policy, bool remark) { |
130 if (g1_policy->use_adaptive_young_list_length()) { |
131 if (g1_policy->use_adaptive_young_list_length()) { |
131 jlong sleep_time_ms = mmu_sleep_time(g1_policy, remark); |
132 double delay_end_sec = mmu_delay_end(g1_policy, remark); |
132 if (!_cm->has_aborted() && sleep_time_ms > 0) { |
133 // Wait for timeout or thread termination request. |
133 os::sleep(this, sleep_time_ms, false); |
134 MonitorLocker ml(CGC_lock, Monitor::_no_safepoint_check_flag); |
|
135 while (!_cm->has_aborted()) { |
|
136 double sleep_time_sec = (delay_end_sec - os::elapsedTime()); |
|
137 jlong sleep_time_ms = ceil(sleep_time_sec * MILLIUNITS); |
|
138 if (sleep_time_ms <= 0) { |
|
139 break; // Passed end time. |
|
140 } else if (ml.wait(sleep_time_ms, Monitor::_no_safepoint_check_flag)) { |
|
141 break; // Timeout => reached end time. |
|
142 } else if (should_terminate()) { |
|
143 break; // Wakeup for pending termination request. |
|
144 } |
|
145 // Other (possibly spurious) wakeup. Retry with updated sleep time. |
134 } |
146 } |
135 } |
147 } |
136 } |
148 } |
137 |
149 |
138 class G1ConcPhaseTimer : public GCTraceConcTimeImpl<LogLevel::Info, LOG_TAGS(gc, marking)> { |
150 class G1ConcPhaseTimer : public GCTraceConcTimeImpl<LogLevel::Info, LOG_TAGS(gc, marking)> { |