This section describes some of the important restrictions the LMM places on its use. Many of these are restrictions one would expect to be present; however, they are listed here anyway in order to make them explicit and to make it more clear in what situations the LMM can and can't be used.
As mentioned previously, the LMM implements no internal synchronization mechanisms, so if it is used in a multithreaded environment, the caller must explicitly serialize execution when performing operations on a particular LMM pool.
If a client uses multiple LMM memory pools, then each pool must manage disjoint blocks of memory. In other words, a particular chunk of memory must never be present on two or more LMM pools at once. However, as long as the actual memory blocks in different pools are disjoint, the overall memory regions managed by the pools can overlap. For example, it is OK if pages 1 and 3 are managed by one LMM pool and page 2 is managed by another, as long as none of those pages are managed by two LMM pools at once.
The LMM uses the memory it manages as storage space for free list information. This means that the LMM is not suitable for managing memory that cannot be accessed directly using normal C pointer arithmetic in the local address space, or memory with special access semantics, such as flash memory. In such a situation, you must use a memory management system that stores free memory metadata separately from the free memory itself.
The LMM guarantees that it will not use any memory other than the memory explicitly given to it for its use through the lmm_init, lmm_add_region, and lmm_add_free calls. This implies that no ``destructor'' functions need to be provided by the library in order to destroy LMM pools, regions, or free lists: an LMM pool can be ``destroyed'' by the caller simply by overwriting or reinitializing the memory with something else. Of course, it is up to the caller to ensure that no attempts are made to use an LMM pool that has been destroyed.