How to comprehend the calls to TLSF are wrapped in irq_disable()/irq_restore()to make it thread-safe?

As per the documentation(), which says that:

TLSF-based global memory allocator. This is a malloc/free implementation built on top of the TLSF allocator. It defines a global tlsf_control block and performs allocations on that block. This implementation replaces the system malloc Additionally, the calls to TLSF are wrapped in irq_disable()/irq_restore(), to make it thread-safe.

My question is how to comprehend this: the calls to TLSF are wrapped in irq_disable()/irq_restore(), to make it thread-safe.

Thank you for your attention to this matter. Best Regards. Sunshilong


RIOT is currently only running on single core platforms. Any context switch needs to be triggered either by the running thread (e.g. `thread_yield()`, `mutex_lock()`, `msg_receive()`, or ...), or from an interrupt service routine (ISR). The first is not a problem when protecting malloc data structures: No programmer will ever (at least intentionally) trigger a context switch while a data structure is in an inconsistent state.

IRQs however can come in at any point in time, thus e.g. while an operation on a data structure is still in progress and the data structure in question is in an inconsistent state. If that data structure is touched externally while in inconsistent state, bad things will happen. This could either happen in the ISR, but also in a thread that gets scheduled after the ISR (e.g. because the ISR unblocks a higher priority thread).

A call to `irq_disable()` will result in the corresponding ISRs of any incoming IRQs to not be executed immediately. Instead, those will be delayed until after a matching call to `irq_disable()`. By wrapping access to shared data structures into a pair of `irq_disable()` and `irq_restore()`, it is guaranteed that no ISRs will trigger while the data structures are in an inconsistent state.

(One detail: If `irq_disable()` is called n times, IRQs will only be enabled after calling n matching `irq_restore()`. So it is totally safe to call `irq_disable()` while IRQs are already disabled. We only need to take great care that for every `irq_disable()` there is exactly one matching `irq_restore()`.)

So for the TLSF-based memory allocator, just this approach is used to prevent other threads (or ISRs) to touch the allocator data structures while they are in an inconsistent state.

Kind regards, Marian