62 } 63 64 uintx G1FreeIdSet::make_head(uint index, uintx old_head) const { 65 // Include incremented old update counter to avoid ABA problem. 66 return index | ((old_head & ~_head_index_mask) + 1 + _head_index_mask); 67 } 68 69 const uint Claimed = UINT_MAX; 70 71 uint G1FreeIdSet::claim_par_id() { 72 _sem.wait(); 73 // Semaphore gate permits passage by no more than the number of 74 // available ids, so there must be one that we can claim. But there 75 // may be multiple threads trying to claim ids at the same time. 76 uintx old_head = Atomic::load(&_head); 77 uint index; 78 while (true) { 79 index = head_index(old_head); 80 assert(index < _size, "invariant"); 81 uintx new_head = make_head(_next[index], old_head); 82 new_head = Atomic::cmpxchg(new_head, &_head, old_head); 83 if (new_head == old_head) break; 84 old_head = new_head; 85 } 86 DEBUG_ONLY(_next[index] = Claimed;) 87 return _start + index; 88 } 89 90 void G1FreeIdSet::release_par_id(uint id) { 91 uint index = id - _start; 92 assert(index < _size, "invalid id %u", id); 93 assert(_next[index] == Claimed, "precondition"); 94 uintx old_head = Atomic::load(&_head); 95 while (true) { 96 _next[index] = head_index(old_head); 97 uintx new_head = make_head(index, old_head); 98 new_head = Atomic::cmpxchg(new_head, &_head, old_head); 99 if (new_head == old_head) break; 100 old_head = new_head; 101 } 102 // Now that id has been released, permit another thread through the gate. 103 _sem.signal(); 104 } | 62 } 63 64 uintx G1FreeIdSet::make_head(uint index, uintx old_head) const { 65 // Include incremented old update counter to avoid ABA problem. 66 return index | ((old_head & ~_head_index_mask) + 1 + _head_index_mask); 67 } 68 69 const uint Claimed = UINT_MAX; 70 71 uint G1FreeIdSet::claim_par_id() { 72 _sem.wait(); 73 // Semaphore gate permits passage by no more than the number of 74 // available ids, so there must be one that we can claim. But there 75 // may be multiple threads trying to claim ids at the same time. 76 uintx old_head = Atomic::load(&_head); 77 uint index; 78 while (true) { 79 index = head_index(old_head); 80 assert(index < _size, "invariant"); 81 uintx new_head = make_head(_next[index], old_head); 82 new_head = Atomic::cmpxchg(&_head, old_head, new_head); 83 if (new_head == old_head) break; 84 old_head = new_head; 85 } 86 DEBUG_ONLY(_next[index] = Claimed;) 87 return _start + index; 88 } 89 90 void G1FreeIdSet::release_par_id(uint id) { 91 uint index = id - _start; 92 assert(index < _size, "invalid id %u", id); 93 assert(_next[index] == Claimed, "precondition"); 94 uintx old_head = Atomic::load(&_head); 95 while (true) { 96 _next[index] = head_index(old_head); 97 uintx new_head = make_head(index, old_head); 98 new_head = Atomic::cmpxchg(&_head, old_head, new_head); 99 if (new_head == old_head) break; 100 old_head = new_head; 101 } 102 // Now that id has been released, permit another thread through the gate. 103 _sem.signal(); 104 } |