AnsweredAssumed Answered

MQX 4.1 _mem_get_size()

Question asked by Matt Osborne on Aug 17, 2018
Latest reply on Aug 20, 2018 by Matt Osborne

Hello,

hoping that someone can confirm that _mem_get_size() can incorrectly generate an MQX_INVALID_CHECKSUM error when preempted by a higher priority task which frees the previous block and has to coalesce the newly freed block with an already free block immediately before it. From _mem_get_size():

#if MQX_CHECK_VALIDITY
    if ((!VALID_CHECKSUM(block_ptr))) {        
        kernel_data->KD_POOL.POOL_BLOCK_IN_ERROR = block_ptr;
        _task_set_error(MQX_INVALID_CHECKSUM);
        return (0);
    } /* Endif */
#endif

 

For the following memory block state:

Address 1 - Block A - Free

Address 2 - Block B - Allocated

Address 3 - Block C - Allocated

 

Sequence of operations:

1. Task L is active and calls _mem_get_size(Address 3)

2. While executing VALID_CHECKSUM calculation (after loading the PREVBLOCK address but before performing the CHECKSUM comparison), Task L is preempted by a higher priority Task H.

3. Task H calls _mem_free(Address 2), which needs to coalesce; _mem_check_coalesce_internal() changes Block C PREVBLOCK from Block B to Block A, and calculates and sets a new Block C CHECKSUM.

4. Task H finishes and Task L becomes active.

5. Task L finishes the VALID_CHECKSUM calculation on Block C but the calculated value was generated when PREVBLOCK pointed to Block B, and the CHECKSUM value was generated when PREVBLOCK pointed to Block A, resulting in an MQX_INVALID_CHECKSUM error.

 

So it looks to me like _mem_get_size() (_mem_transfer() too) should be wrapping the VALID_CHECKSUM calculation in INT_DISABLE/INT_ENABLE calls.

 

Thanks

Outcomes