- Loading...
...
*** THIS SUBSECTION NEEDS SUBSTANTIAL REWORK WITH v2.11 ***
ObjectSynchronizer::deflate_monitor_list_using_JT() is responsible for asynchronously deflating idle ObjectMonitors using a JavaThread. This function uses the more complicated lock-cur_mid_in_use-and-mid-as-we-go protocol because om_release() can do list deletions in parallel. We also lock-next-next-as-we-go to prevent an om_flush() that is behind this thread from passing us. Because this function can asynchronously interact with so many other functions, this is the largest clip of code:
L01: int ObjectSynchronizer::deflate_monitor_list_using_JT(ObjectMonitor** list_p,
L02: int* count_p,
L03: ObjectMonitor** free_head_p,
L04: ObjectMonitor** free_tail_p,
L05: ObjectMonitor** saved_mid_in_use_p) {
L06: JavaThread* self = JavaThread::current();
L07: ObjectMonitor* cur_mid_in_use = NULL;
L08: ObjectMonitor* mid = NULL;
L09: ObjectMonitor* next = NULL;
L10: ObjectMonitor* next_next = NULL;
L11: int deflated_count = 0;
L12: NoSafepointVerifier nsv;
L13: if (*saved_mid_in_use_p == NULL) {
L13L14: if ((mid = get_list_head_locked(list_p)) == NULL) {
L14L15: return 0; // The list is empty so nothing to deflate.
L15L16: }
L16L17: next = unmarked_next(mid);
L17L18: } else {
L18L19: cur_mid_in_use = *saved_mid_in_use_p;
L19L20: om_lock(cur_mid_in_use);
L20L21: mid = unmarked_next(cur_mid_in_use);
L21L22: if (mid == NULL) {
L22L23: om_unlock(cur_mid_in_use);
L23L24: *saved_mid_in_use_p = NULL;
L24L25: return 0; // The remainder is empty so nothing more to deflate.
L25L26: }
L26L27: om_lock(mid);
L27L28: next = unmarked_next(mid);
L28L29: }
L29L30: while (true) {
L30L31: if (next != NULL) {
L31L32: om_lock(next);
L32L33: next_next = unmarked_next(next);
L33L34: }
L34L35: if (mid->object() != NULL && mid->is_old() &&
L35L36: deflate_monitor_using_JT(mid, free_head_p, free_tail_p)) {
L36L37: if (cur_mid_in_use == NULL) {
L37L38: Atomic::store(list_p, next);
L38L39: } else {
L39L40: ObjectMonitor* locked_next = mark_om_ptr(next);
L40L41: cur_mid_in_use->set_next_om(locked_next);
L41L42: }
L42L43: deflated_count++;
L43L44: Atomic::dec(count_p);
L44L45: mid->set_next_om(NULL);
L45L46: mid = next; // mid keeps non-NULL next's locked state
L46L47: next = next_next;
L47L48: } else {
L48L49: if (cur_mid_in_use != NULL) {
L49L50: om_unlock(cur_mid_in_use);
L50L51: }
L51L52: cur_mid_in_use = mid;
L52L53: mid = next; // mid keeps non-NULL next's locked state
L53L54: next = next_next;
L54L55: if (SafepointMechanism::should_block(self) &&
L55L56: cur_mid_in_use != Atomic::load(list_p) && cur_mid_in_use->is_old()) {
L56L57: *saved_mid_in_use_p = cur_mid_in_use;
L57L58: om_unlock(cur_mid_in_use);
L58L59: if (mid != NULL) {
L59L60: om_unlock(mid);
L60L61: }
L61L62: return deflated_count;
L62L63: }
L63L64: }
L64L65: if (mid == NULL) {
L65L66: if (cur_mid_in_use != NULL) {
L66L67: om_unlock(cur_mid_in_use);
L67L68: }
L68L69: break; // Reached end of the list so nothing more to deflate.
L69L70: }
L70L71: }
L71L72: *saved_mid_in_use_p = NULL;
L72L73: return deflated_count;
L73L74: }
The above is not an exact copy of the code block from deflate_monitor_list_using_JT(), but it is the highlights. What the above code block needs to do is pretty simple:
...
Since we're using the more complicated lock-cur_mid_in_use-and-mid-as-we-go protocol and also the lock-next-next-as-we-go protocol, there is a mind numbing amount of detail:
...