From _mem_free (this is in all versions of MQX I have access to ...)
/* Reset the _mem_test pointers */ | |
mem_pool_ptr->POOL_PHYSICAL_CHECK_BLOCK = (STOREBLOCK_STRUCT_PTR) mem_pool_ptr->POOL_PTR; | |
mem_pool_ptr->POOL_FREE_CHECK_BLOCK = mem_pool_ptr->POOL_FREE_LIST_PTR; |
_INT_ENABLE(); |
And from _mem_test
next_block_ptr = NEXT_PHYS(mem_pool_ptr->POOL_PHYSICAL_CHECK_BLOCK); | |
if (next_block_ptr->PREVBLOCK != mem_pool_ptr->POOL_PHYSICAL_CHECK_BLOCK){ | |
mem_pool_ptr->POOL_BLOCK_IN_ERROR = next_block_ptr; | |
_int_enable(); | |
result = MQX_CORRUPT_STORAGE_POOL; | |
break; | |
} /* Endif */ | |
mem_pool_ptr->POOL_PHYSICAL_CHECK_BLOCK = next_block_ptr; |
The problem, if I understand correctly, is that if _mem_free gets called from another task while _mem_test is running, the "POOL_PHYSICAL_CHECK_BLOCK" gets reset to the beginning of the pool and the _mem_test starts over again.
The MQX Manual states...
The function can be called by only one task at a time because it keeps state-inprogress
variables that MQX controls. This mechanism lets other tasks allocate
and free memory while _mem_test() runs.
In the case of my system this means that my call to _mem_test never completes.
Does anyone have a solution that does not disable interrupts for the duration of the _mem_test?
Hi Don Marquardt,
Actually in _mem_free() and _mem_test(), the interrupt is disabled before the code starts to operate on the pointers, so when one task is running the _mem_test() while another invokes _mem_free(), the task switch would not happen when interrupt is disbaled, so I think you needn't worry about the case that _mem_free gets called from another task while _mem_test is running.
Hope that helps,
Have a great day,
Kan
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I understand that. The problem is that although the pointers are being used "safely", if your system is doing a lot of mem allocs and frees, the pointer gets reset to the beginning of the free pool each time free is called.
That means that mem_test starts over at the beginning of the pool and potentially never finishes.
Hi Don Marquardt,
Actually I am a little bit confused why you said "That means that mem_test starts over at the beginning of the pool and potentially never finishes." I agree _mem_test() starts from the beginning of the checking pointers when it is invoked after some task invokes _mem_free() , but during _mem_test() running, the context would not switch to other tasks , so _mem_alloc and _mem_free would not be possibly invoked during that period until _mem_test() is finished or task switching API is called explicitly in _mem_test() , so I don't understand in which case _mem_test() would never finish. Would you please help to clarify? Thanks for your patience!!
Have a nice weekend!!
B.R
Kan
The issue is that both mem_test and mem_free reset the pointer(POOL_PHYSICAL_CHECK_BLOCK) used by mem_test.
at approx line 93 in mem_tesp.c...
mem_pool_ptr->POOL_PHYSICAL_CHECK_BLOCK = next_block_ptr; | |
_int_enable(); |
} /* Endwhile */
and in mem_free.c at approx line 243
/* Reset the _mem_test pointers */
mem_pool_ptr->POOL_PHYSICAL_CHECK_BLOCK =
(STOREBLOCK_STRUCT_PTR)mem_pool_ptr->POOL_PTR;
So what happens is that mem_test will potentially start over again.