127 }
128 }
129 }
130
131 void G1ConcurrentRefineThreadControl::stop() {
132 for (uint i = 0; i < _num_max_threads; i++) {
133 if (_threads[i] != NULL) {
134 _threads[i]->stop();
135 }
136 }
137 }
138
139 // Arbitrary but large limits, to simplify some of the zone calculations.
140 // The general idea is to allow expressions like
141 // MIN2(x OP y, max_XXX_zone)
142 // without needing to check for overflow in "x OP y", because the
143 // ranges for x and y have been restricted.
144 STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2));
145 const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort);
146 const size_t max_green_zone = max_yellow_zone / 2;
147 const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_queue.
148 STATIC_ASSERT(max_yellow_zone <= max_red_zone);
149
150 // Range check assertions for green zone values.
151 #define assert_zone_constraints_g(green) \
152 do { \
153 size_t azc_g_green = (green); \
154 assert(azc_g_green <= max_green_zone, \
155 "green exceeds max: " SIZE_FORMAT, azc_g_green); \
156 } while (0)
157
158 // Range check assertions for green and yellow zone values.
159 #define assert_zone_constraints_gy(green, yellow) \
160 do { \
161 size_t azc_gy_green = (green); \
162 size_t azc_gy_yellow = (yellow); \
163 assert_zone_constraints_g(azc_gy_green); \
164 assert(azc_gy_yellow <= max_yellow_zone, \
165 "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow); \
166 assert(azc_gy_green <= azc_gy_yellow, \
167 "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")", \
369
370 assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone);
371 LOG_ZONES("Updated Refinement Zones: "
372 "green: " SIZE_FORMAT ", "
373 "yellow: " SIZE_FORMAT ", "
374 "red: " SIZE_FORMAT,
375 _green_zone, _yellow_zone, _red_zone);
376 }
377
378 void G1ConcurrentRefine::adjust(double update_rs_time,
379 size_t update_rs_processed_buffers,
380 double goal_ms) {
381 DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
382
383 if (G1UseAdaptiveConcRefinement) {
384 update_zones(update_rs_time, update_rs_processed_buffers, goal_ms);
385
386 // Change the barrier params
387 if (max_num_threads() == 0) {
388 // Disable dcqs notification when there are no threads to notify.
389 dcqs.set_process_completed_threshold(INT_MAX);
390 } else {
391 // Worker 0 is the primary; wakeup is via dcqs notification.
392 STATIC_ASSERT(max_yellow_zone <= INT_MAX);
393 size_t activate = activation_threshold(0);
394 dcqs.set_process_completed_threshold((int)activate);
395 }
396 dcqs.set_max_completed_queue((int)red_zone());
397 }
398
399 size_t curr_queue_size = dcqs.completed_buffers_num();
400 if (curr_queue_size >= yellow_zone()) {
401 dcqs.set_completed_queue_padding(curr_queue_size);
402 } else {
403 dcqs.set_completed_queue_padding(0);
404 }
405 dcqs.notify_if_necessary();
406 }
407
408 size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const {
409 Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
410 return activation_level(thresholds);
411 }
412
413 size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const {
414 Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
415 return deactivation_level(thresholds);
416 }
417
418 uint G1ConcurrentRefine::worker_id_offset() {
419 return DirtyCardQueueSet::num_par_ids();
420 }
421
422 void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers) {
423 if (num_cur_buffers > activation_threshold(worker_id + 1)) {
424 _thread_control.maybe_activate_next(worker_id);
425 }
426 }
427
428 bool G1ConcurrentRefine::do_refinement_step(uint worker_id) {
429 DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
430
431 size_t curr_buffer_num = dcqs.completed_buffers_num();
432 // If the number of the buffers falls down into the yellow zone,
433 // that means that the transition period after the evacuation pause has ended.
434 // Since the value written to the DCQS is the same for all threads, there is no
435 // need to synchronize.
436 if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= yellow_zone()) {
437 dcqs.set_completed_queue_padding(0);
438 }
439
440 maybe_activate_more_threads(worker_id, curr_buffer_num);
441
442 // Process the next buffer, if there are enough left.
443 return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(),
444 deactivation_threshold(worker_id));
445 }
|
127 }
128 }
129 }
130
131 void G1ConcurrentRefineThreadControl::stop() {
132 for (uint i = 0; i < _num_max_threads; i++) {
133 if (_threads[i] != NULL) {
134 _threads[i]->stop();
135 }
136 }
137 }
138
139 // Arbitrary but large limits, to simplify some of the zone calculations.
140 // The general idea is to allow expressions like
141 // MIN2(x OP y, max_XXX_zone)
142 // without needing to check for overflow in "x OP y", because the
143 // ranges for x and y have been restricted.
144 STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2));
145 const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort);
146 const size_t max_green_zone = max_yellow_zone / 2;
147 const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_buffers.
148 STATIC_ASSERT(max_yellow_zone <= max_red_zone);
149
150 // Range check assertions for green zone values.
151 #define assert_zone_constraints_g(green) \
152 do { \
153 size_t azc_g_green = (green); \
154 assert(azc_g_green <= max_green_zone, \
155 "green exceeds max: " SIZE_FORMAT, azc_g_green); \
156 } while (0)
157
158 // Range check assertions for green and yellow zone values.
159 #define assert_zone_constraints_gy(green, yellow) \
160 do { \
161 size_t azc_gy_green = (green); \
162 size_t azc_gy_yellow = (yellow); \
163 assert_zone_constraints_g(azc_gy_green); \
164 assert(azc_gy_yellow <= max_yellow_zone, \
165 "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow); \
166 assert(azc_gy_green <= azc_gy_yellow, \
167 "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")", \
369
370 assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone);
371 LOG_ZONES("Updated Refinement Zones: "
372 "green: " SIZE_FORMAT ", "
373 "yellow: " SIZE_FORMAT ", "
374 "red: " SIZE_FORMAT,
375 _green_zone, _yellow_zone, _red_zone);
376 }
377
378 void G1ConcurrentRefine::adjust(double update_rs_time,
379 size_t update_rs_processed_buffers,
380 double goal_ms) {
381 DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
382
383 if (G1UseAdaptiveConcRefinement) {
384 update_zones(update_rs_time, update_rs_processed_buffers, goal_ms);
385
386 // Change the barrier params
387 if (max_num_threads() == 0) {
388 // Disable dcqs notification when there are no threads to notify.
389 dcqs.set_process_completed_buffers_threshold(DirtyCardQueueSet::ProcessCompletedBuffersThresholdNever);
390 } else {
391 // Worker 0 is the primary; wakeup is via dcqs notification.
392 STATIC_ASSERT(max_yellow_zone <= INT_MAX);
393 size_t activate = activation_threshold(0);
394 dcqs.set_process_completed_buffers_threshold(activate);
395 }
396 dcqs.set_max_completed_buffers(red_zone());
397 }
398
399 size_t curr_queue_size = dcqs.completed_buffers_num();
400 if ((dcqs.max_completed_buffers() > 0) &&
401 (curr_queue_size >= yellow_zone())) {
402 dcqs.set_completed_buffers_padding(curr_queue_size);
403 } else {
404 dcqs.set_completed_buffers_padding(0);
405 }
406 dcqs.notify_if_necessary();
407 }
408
409 size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const {
410 Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
411 return activation_level(thresholds);
412 }
413
414 size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const {
415 Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
416 return deactivation_level(thresholds);
417 }
418
419 uint G1ConcurrentRefine::worker_id_offset() {
420 return DirtyCardQueueSet::num_par_ids();
421 }
422
423 void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers) {
424 if (num_cur_buffers > activation_threshold(worker_id + 1)) {
425 _thread_control.maybe_activate_next(worker_id);
426 }
427 }
428
429 bool G1ConcurrentRefine::do_refinement_step(uint worker_id) {
430 DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
431
432 size_t curr_buffer_num = dcqs.completed_buffers_num();
433 // If the number of the buffers falls down into the yellow zone,
434 // that means that the transition period after the evacuation pause has ended.
435 // Since the value written to the DCQS is the same for all threads, there is no
436 // need to synchronize.
437 if (dcqs.completed_buffers_padding() > 0 && curr_buffer_num <= yellow_zone()) {
438 dcqs.set_completed_buffers_padding(0);
439 }
440
441 maybe_activate_more_threads(worker_id, curr_buffer_num);
442
443 // Process the next buffer, if there are enough left.
444 return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(),
445 deactivation_threshold(worker_id));
446 }
|