I think the implementation here (and possibly many other implementation) has this bug:
For example, assume we have 2 threads:
- Thread 1 does the get() of SharedAtomicPtr ptr
- Thread 2 does the store() of ptr.
With following interleaving actions:
- Thread 1 increases the local refcount and load the pointer to the control block from
ptr
- Thread 1 increases the global refcount from the control block. (global refcount now = 2)
- Thread 2 comes along and update the 48 bits pointer to the new control block
- BUT before thread 2 can increase the global refcount, it's temporary paused by system scheduler.
- Thread 1 then tries to decrease the local refcount, finds out that the 48 bits pointer has changed
- Thread 1 decrease the global refcount. (global refcount now = 1)
- Thread 1 then starts using the object
- After finish using the object, Thread 1 then decrease the global refcount. (global refcount now = 0)
- Thread 1 does the deletion on the control block.
- Finally thread 2 is resumed, and then it tries to increase the global refcount. But the control block has already been freed => use-after-free bug
Did I get something wrong somewhere.
Or the algorithm itself is incorrect?
I think the implementation here (and possibly many other implementation) has this bug:
For example, assume we have 2 threads:
With following interleaving actions:
ptrDid I get something wrong somewhere.
Or the algorithm itself is incorrect?