usword_t SubzoneBlockRef::refcount() const { int refcount = 0; Admin *admin = subzone()->admin(); SpinLock lock(admin->lock()); if (has_refcount()) { // non-zero reference count, check the overflow table. // BlockRef FIXME: use q instead of address in hash map? PtrIntHashMap &retains = admin->retains(); PtrIntHashMap::iterator retain_iter = retains.find(address()); if (retain_iter != retains.end() && retain_iter->first == address()) { refcount = retain_iter->second; } else { refcount = 1; } } return refcount; }
usword_t SubzoneBlockRef::inc_refcount() const { int refcount; Admin *admin = subzone()->admin(); SpinLock lock(admin->lock()); void *block = address(); if (has_refcount()) { // non-trivial reference count, check the overflow table. PtrIntHashMap &retains = admin->retains(); PtrIntHashMap::iterator retain_iter = retains.find(block); if (retain_iter != retains.end() && retain_iter->first == block) { refcount = ++retain_iter->second; } else { // transition from 1 -> 2 refcount = (retains[block] = 2); } } else { // transition from 0 -> 1 Thread &thread = admin->zone()->registered_thread(); thread.block_escaped(*this); subzone()->set_has_refcount(q()); refcount = 1; } return refcount; }
usword_t SubzoneBlockRef::dec_refcount() const { Admin *admin = subzone()->admin(); SpinLock lock(admin->lock()); return dec_refcount_no_lock(); }