- Loading...
...
L01: static bool mark_list_head(ObjectMonitor* volatile * list_p,
L02: ObjectMonitor** mid_p, ObjectMonitor** next_p) {
L03: while (true) {
L04: ObjectMonitor* mid = OrderAccess::load_acquire(list_p);
L05: if (mid == NULL) {
L06: return false; // The list is empty so nothing to mark.
L07: }
L08: if (mark_next(mid, next_p)) {
L09: if (OrderAccess::load_acquire(list_p) != mid) {
L10: // The list head changed so we have to retry.
L11: set_next(mid, *next_p); // unmark mid
L12: continue;
L13: }
L14: // We marked next field to guard against races.
L15: *mid_p = mid;
L16: return true;
L17: }
L18: }
L19: }
The above function tries to mark the next field in the list head's ObjectMonitor:
...
ObjectSynchronizer::om_release() is responsible for putting an ObjectMonitor on self's free list. If 'from_per_thread_alloc' is true, then om_release() is also responsible for extracting the ObjectMonitor from self's in-use list. The extraction from self's in-use list must happen first:
L01: if (from_per_thread_alloc) {
L02: mark_list_head(&self->om_in_use_list, &mid, &next);
L02L03: while (true) {
L03L04: if (m == mid) {
L04L05: if (Atomic::cmpxchg(next, &self->om_in_use_list, mid) != mid) {
L05L06: ObjectMonitor* marked_mid = mark_om_ptr(mid);
L06L07: Atomic::cmpxchg(next, &cur_mid_in_use->_next_om, marked_mid);
L07L08: }
L08L09: extracted = true;
L09L10: Atomic::dec(&self->om_in_use_count);
L10L11: set_next(mid, next);
L11L12: break;
L12L13: }
L13L14: if (cur_mid_in_use != NULL) {
L14L15: set_next(cur_mid_in_use, mid); // umark cur_mid_in_use
L15L16: }
L16L17: cur_mid_in_use = mid;
L17L18: mid = next;
L18L19: next = mark_next_loop(mid);
L20: L19}
L21: }
L22: prepend_to_om_free_list(self, m);
Most of the The above code block extracts 'm' from self's in-use list; it is not an exact quote from om_release(), but it is the highlights:
The last line of the code block (L22) prepends 'm' to self's free list.
...