Skip to content

Commit bb309c3

Browse files
committed
Cowns: Use atomic RC for cowns
1 parent c823407 commit bb309c3

1 file changed

Lines changed: 31 additions & 2 deletions

File tree

Include/refcount.h

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@ static inline Py_ALWAYS_INLINE void _Py_CLEAR_IMMUTABLE(PyObject *op)
157157
#endif
158158
}
159159

160+
/** Currently, only cowns require atomic reference counting.
161+
* Immutable objects are handled separately.
162+
*/
163+
static inline int _PyRegion_NeedsAtomicRc(PyObject *obj) {
164+
// Cown objects always have their region set to `_Py_COWN_REGION`
165+
// directly. It's not possible to merge regions into the cown
166+
// region, therefore, we don't need to check if the region field
167+
// is part of a union find.
168+
return obj->ob_region == _Py_COWN_REGION;
169+
}
170+
160171
// Py_REFCNT() implementation for the stable ABI
161172
PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob);
162173

@@ -166,6 +177,10 @@ PyAPI_FUNC(Py_ssize_t) Py_REFCNT(PyObject *ob);
166177
#else
167178
static inline Py_ssize_t _Py_REFCNT(PyObject *ob) {
168179
#if !defined(Py_GIL_DISABLED)
180+
// FIXME: This for some reason doesn't compile
181+
// if (_PyRegion_NeedsAtomicRc(ob)) {
182+
// return _Py_atomic_load_uint32_relaxed(&ob->ob_refcnt);
183+
// }
169184
return _Py_IMMUTABLE_FLAG_CLEAR(ob->ob_refcnt);
170185
#else
171186
uint32_t local = _Py_atomic_load_uint32_relaxed(&ob->ob_ref_local);
@@ -257,6 +272,9 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
257272
// TODO(Immutable): Care should be taken to make the whole SCC mutable
258273
// again if needed.
259274
}
275+
// FIXME: Setting the ref count for cowns is dangerous
276+
// investigate if this is really needed.
277+
assert(!_PyRegion_NeedsAtomicRc(ob));
260278
#ifndef Py_GIL_DISABLED
261279
#if SIZEOF_VOID_P > 4
262280
ob->ob_refcnt = (PY_UINT32_T)refcnt;
@@ -403,7 +421,11 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
403421
return;
404422
#endif
405423
}
406-
op->ob_refcnt = (uint32_t)cur_refcnt + 1;
424+
if (_PyRegion_NeedsAtomicRc(op)) {
425+
_Py_atomic_add_uint32(&op->ob_refcnt, 1);
426+
} else {
427+
op->ob_refcnt = (uint32_t)cur_refcnt + 1;
428+
}
407429
#else
408430
if (_Py_IsImmortalOrImmutable(op)) {
409431
if (_Py_IsImmortal(op)) {
@@ -576,7 +598,14 @@ static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
576598
#endif
577599
}
578600
_Py_DECREF_STAT_INC();
579-
if (--op->ob_refcnt == 0) {
601+
uint32_t rc;
602+
if (_PyRegion_NeedsAtomicRc(ob)) {
603+
rc = _Py_atomic_sub_uint32(&ob->ob_refcnt, 1);
604+
} else {
605+
rc = --op->ob_refcnt;
606+
}
607+
608+
if (rc == 0) {
580609
_Py_Dealloc(op);
581610
}
582611
}

0 commit comments

Comments
 (0)