Merge pull request #2810 from kumpera/fix_hazard_free
Fix hazard free
Replace usage of mono_thread_hazardous_free_or_queue and remove it.
mono_thread_hazardous_free_or_queue has a fundamentally broken design.
It allows arbitrary free code to run in the context of its caller.
The sync/async split on where it's called is not enough to know whether
we can run free'ing code or not.
Since in sync context we called free functions that could take locks,
it happened that those locks conflicted with the ones already taken.
In particular, mono_jit_info_table_free did take a domain lock and
quite a few of the sync context calls would hold locks that must
not be held when taking a domain lock.
This, is practice, means that we'd need to partition the free calls
into 3 groups: async context, reentrant context (no runtime locks held)
and sync context (maybe some locks held).
There was no case where reentrant context would be usable meaning,
in practice, that all calls happens in what effectively is async context
where free functions can't be called.
The new design is a lot more straightforward:
- No implicit free queue pumping
- A pair of free functions with well defined behavior.
mono_thread_hazardous_try_free - to be used where the caller expects the free function to be called
mono_thread_hazardous_queue_free - to be used where the caller don't expect the free function to be called [1]
- Explicit pumping on places that known to be ok
Thread detach
Finalizer thread
[1] This might sound like a weird condition, but a lot of lock-free code
have compensation logic that trigger free'ing during lookups.