DISPATCH_NOINLINE _os_object_t _os_object_retain(_os_object_t obj) { int xref_cnt = _os_object_xrefcnt_inc(obj); if (slowpath(xref_cnt <= 0)) { _OS_OBJECT_CLIENT_CRASH("Resurrection of an object"); } return obj; }
bool _os_object_allows_weak_reference(_os_object_t obj) { int xref_cnt = obj->os_obj_xref_cnt; if (slowpath(xref_cnt == -1)) { return false; } if (slowpath(xref_cnt < -1)) { _OS_OBJECT_CLIENT_CRASH("Over-release of an object"); } return true; }
DISPATCH_NOINLINE void _os_object_release(_os_object_t obj) { int xref_cnt = _os_object_xrefcnt_dec(obj); if (fastpath(xref_cnt >= 0)) { return; } if (slowpath(xref_cnt < -1)) { _OS_OBJECT_CLIENT_CRASH("Over-release of an object"); } return _os_object_xref_dispose(obj); }
DISPATCH_NOINLINE _os_object_t _os_object_retain_with_resurrect(_os_object_t obj) { int xref_cnt = _os_object_xrefcnt_inc(obj); if (slowpath(xref_cnt < 0)) { _OS_OBJECT_CLIENT_CRASH("Resurrection of an overreleased object"); } if (slowpath(xref_cnt == 0)) { _os_object_retain_internal(obj); } return obj; }
DISPATCH_NOINLINE _os_object_t _os_object_retain(_os_object_t obj) { int xref_cnt = obj->os_obj_xref_cnt; if (slowpath(xref_cnt == _OS_OBJECT_GLOBAL_REFCNT)) { return obj; // global object } xref_cnt = dispatch_atomic_inc2o(obj, os_obj_xref_cnt, relaxed); if (slowpath(xref_cnt <= 0)) { _OS_OBJECT_CLIENT_CRASH("Resurrection of an object"); } return obj; }
DISPATCH_NOINLINE void _os_object_release(_os_object_t obj) { int xref_cnt = obj->os_obj_xref_cnt; if (slowpath(xref_cnt == _OS_OBJECT_GLOBAL_REFCNT)) { return; // global object } xref_cnt = dispatch_atomic_dec2o(obj, os_obj_xref_cnt, relaxed); if (fastpath(xref_cnt >= 0)) { return; } if (slowpath(xref_cnt < -1)) { _OS_OBJECT_CLIENT_CRASH("Over-release of an object"); } return _os_object_xref_dispose(obj); }
bool _os_object_retain_weak(_os_object_t obj) { int xref_cnt = obj->os_obj_xref_cnt; if (slowpath(xref_cnt == _OS_OBJECT_GLOBAL_REFCNT)) { return true; // global object } retry: if (slowpath(xref_cnt == -1)) { return false; } if (slowpath(xref_cnt < -1)) { goto overrelease; } if (slowpath(!dispatch_atomic_cmpxchgvw2o(obj, os_obj_xref_cnt, xref_cnt, xref_cnt + 1, &xref_cnt, relaxed))) { goto retry; } return true; overrelease: _OS_OBJECT_CLIENT_CRASH("Over-release of an object"); }
static voucher_t _voucher_find_and_retain(mach_voucher_t kv) { voucher_t v; if (!kv) return NULL; _vouchers_lock_lock(); TAILQ_FOREACH(v, _vouchers_head(kv), v_list) { if (v->v_ipc_kvoucher == kv) { int xref_cnt = os_atomic_inc2o(v, os_obj_xref_cnt, relaxed); _dispatch_voucher_debug("retain -> %d", v, xref_cnt + 1); if (slowpath(xref_cnt < 0)) { _dispatch_voucher_debug("over-release", v); _OS_OBJECT_CLIENT_CRASH("Voucher over-release"); } if (xref_cnt == 0) { // resurrection: raced with _voucher_remove (void)os_atomic_inc2o(v, os_obj_ref_cnt, relaxed); } break; } } _vouchers_lock_unlock(); return v; }