Tuesday, August 13, 2013

Variable Vs Fixed memory pool: Releasing memory block

① Difference between variable size memory pool and fixed size memory pool

In variable memory pool, the released memory block is first merged with the pool and then the waiting tasks are searched for. And, the memory block is inserted in the list exactly where it is acquired. In other words, the memory block is inserted in the order of how physically they are located. So, list is parsed through till the exact location is found.
 
But, for fixed memory pool, before adding the released memory block to the list, the waiting tasks are searched for. If there is a waiting task, then the block is assigned to the task. And, the memory block is always added at the head of the list. So, the fixed memory blocks are not necessarily allocated in the order of how physically they are located.

② ITRON implementation of rel_mpl()

ER rel_mpl(ID mplid, VP blk)
{
        Check context. If called from ISR,
                return E_CTX;
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        /* Validity checks */
        If (address is not aligned to header size) OR
            (input pointer is out of memory pool range)
                return E_PAR;
        Retrieve back to the start address of block by (input pointer - 2 words)
        Insert the memory block in the list at the exact position from where it is taken
        /* One block is released. Check does it satisfy the first waiting task */
        Traverse each queue from starting of memory pool queue till queue tail is reached {
                Till (valid task exists at head of the queue) {
                        Get requested block size from task's context
                        As if called get_blk(), add header size to this requested size and
                        Try to allocate the block
                        If (block is not allocated)
                                goto mpl_ext;
                        /* block is allocated */
                        Store requested size + header size at first word of the block
                        Advance the acquired block's address by two words and
                            store it in the return pointer that is got from task's context;
                        if (task is waiting in Timeout) {
                                Remove from timer queue
                        }
                        Set task status ad Ready
                        if (the task is NOT suspended) {
                                If (the task priority is higher than the current)
                                        Set to call scheduler when quitting this function
                                Change the task to the Ready Queue of corresponding priority
                        } else {
                                Just delete the task from the memory pool queue
                        }
                }
        }
        if (set to call scheduler) {
                Call scheduler
                Return error code that is set in scheduler
        }
        Otherwise, exit critical section and return error code
}

Insert operation ()
{
        Take the size (user requested size + size of header) from the first word of block
        Validity check the size if less than header size or end of block is out of memory pool range
        Round up the size to multiple of Basic unit size(Header size)
        Assume the head pointer as an empty block of size zero
        /* keep two consecutive blocks as previous and next nodes and check for
           insertion of the input block */
        Start with head pointer as previous node;
        Keep the size of previous node as zero;
        Keep the node pointed by head as next node;
        Till the node is inserted {
                if (next node == NULL OR next node start address > input block's start) {
                        Validate if input block start + size do not overlap next node;
                        /* Check if prev node is adjacent to input block */
                        if (input block start == prev node + size of prev node) {
                                Add input block size to size of prev node;
                                /* input block no more exists. it is to be combined with prev */
                        } else {
                                /* At front side, this block will remain separate, So, */
                                /* Update the prev node to point this input node; */
                                prev node->next = input block;
                                /* Yet to check if next node can be combined with this */
                                Make this input node as prev node
                                Make this node size as size of prev node
                        }
                        if (next node is NULL) {
                                /* no second half. So, update inserted node's fields */
                                Update prev node-> next = NULL;
                                Update prev node-> size = size of prev node;
                        } else if (next node start addr == prev node addr + size of prev node) {
                                /* next node needs to be combined */
                                prev node->next = next node->next;
                                prev node->size = size of prev node + size of next node;
                        } else { /* At back side, this block will remain separate */
                                prev node->next = next node;
                                prev node->size = size of prev node;
                        }
                        /* Inserted. So */
                        return;
                }
                prev node = next node;
                next node = next node->next;
                size of prev node = prev node->size;
                Validate prev node does not overlap with input block
        }
        return;
}

② ITRON implementation of rel_mpf()

ER rel_mpf(ID mpfid, VP blf)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        /* Validate the pointer to the block argument */
        If the block is not aligned to the CPU word OR
        if it is out of range of memory pool
                return E_PAR;
        If (head pointer is NULL) {
        /* memory pool is empty. There should be some tasks waiting for memory */
        /* awake one task at the head of the queue and assign the memory block */
                Till (end of queue (tail) is reached) {
                        if (valid task found sleeping) {
                                Get the return pointer from task's context;
                                Assign the block address to the return pointer;
                                if (task is waiting in Timeout) {
                                         Remove from timer queue
                                }
                                 Set task status ad Ready
                                if (the task is NOT suspended) {
                                        Change the task to the Ready Queue of corresponding priority
                                        If (the task priority is higher than the current){
                                                call scheduler
                                                return error code from scheduler
                                        } else {
                                                Exit critical section and return the error code from it
                                        }
                                } else {
                                        Just delete the task from the memory pool queue
                                        Exit critical section and return the error code from it
                                }
                        }
                }
        }
        /* Add the memory block at the head of the list */
        Assign the head pointer to the first word of the block
        head pointer = block;
        Increment the counter for free blocks
        Exit critical section
        return E_OK;
}
Advancing towards another milestone! Visit other posts under ROTS label.

No comments: