📄 dms.c
字号:
/* Is this free block, minus the overhead, already aligned? */ if (address % alignment != 0) { /* Not aligned, can the free block be split in front? */ next_aligned = address + (alignment - 1); next_aligned /= alignment; next_aligned *= alignment; split_size = next_aligned - address; /* Is space from start of block to aligned location large enough to contain 2 DM_OVERHEAD plus pool -> dm_min_allocation? */ if (split_size < ((2 * DM_OVERHEAD) + pool -> dm_min_allocation)) { /* No, so try to make space for overhead and dm_min_allocation */ next_aligned = address + (2 * DM_OVERHEAD) + (pool -> dm_min_allocation) + (alignment - 1); next_aligned /= alignment; next_aligned *= alignment; split_size = next_aligned - address; } /* Adjust free_size for result of front split */ if (free_size > split_size) free_size -= split_size; else /* Can't adjust block beginning, so keep searching */ free_size = 0; } } /* Determine if the search should continue. */ if (free_size < size) /* Large enough block has not been found. Move the search pointer to the next block. */ memory_ptr = memory_ptr -> dm_next_memory; } while((free_size < size) && (memory_ptr != pool -> dm_search_ptr)); /* Determine if the memory is available. */ if (free_size >= size) { /* A block that satisfies the request has been found. */ /* Is a front split required? The front split will represent the chunk of memory that goes from the last pointer to the aligned address. */ if(address % alignment != 0) { /* Not aligned, front split the block, leaving an allocated block. */ new_ptr = (DM_HEADER*)(((UNSIGNED)(memory_ptr)) + split_size); /* Mark the new block as free. */ new_ptr -> dm_memory_free = NU_TRUE; /* Put the pool pointer into the new block. */ new_ptr -> dm_memory_pool = pool; /* Build the necessary pointers. */ new_ptr -> dm_previous_memory = memory_ptr; new_ptr -> dm_next_memory = memory_ptr -> dm_next_memory; (new_ptr -> dm_next_memory) -> dm_previous_memory = new_ptr; memory_ptr -> dm_next_memory = new_ptr; /* Decrement the available byte count by one DM_OVERHEAD. */ pool -> dm_available = pool -> dm_available - DM_OVERHEAD; /* Point to new aligned free block. */ memory_ptr = new_ptr; } /* Determine if the remaining block needs to be tail split. */ if (free_size >= (size + DM_OVERHEAD + pool -> dm_min_allocation)) { /* Yes, split the block. */ new_ptr = (DM_HEADER *) (((BYTE_PTR) memory_ptr) + size + DM_OVERHEAD); /* Mark the new block as free. */ new_ptr -> dm_memory_free = NU_TRUE; /* Put the pool pointer into the new block. */ new_ptr -> dm_memory_pool = pool; /* Build the necessary pointers. */ new_ptr -> dm_previous_memory = memory_ptr; new_ptr -> dm_next_memory = memory_ptr -> dm_next_memory; (new_ptr -> dm_next_memory) -> dm_previous_memory = new_ptr; memory_ptr -> dm_next_memory = new_ptr; /* Decrement the available byte count. */ pool -> dm_available = pool -> dm_available - size - DM_OVERHEAD; } else /* Decrement the entire free size from the available bytes count. */ pool -> dm_available = pool -> dm_available - free_size; /* Mark the allocated block as not available. */ memory_ptr -> dm_memory_free = NU_FALSE; /* Should the search pointer be moved? */ if (pool -> dm_search_ptr == memory_ptr) /* Move the search pointer to the next free memory slot. */ pool -> dm_search_ptr = memory_ptr -> dm_next_memory; /* Return a memory address to the caller. */ *return_pointer = (VOID *) (((BYTE_PTR) memory_ptr) + DM_OVERHEAD);#ifdef INCLUDE_PROVIEW _RTProf_DumpMemoryPool(RT_PROF_ALLOCATE_MEMORY,pool,RT_PROF_OK);#endif /*INCLUDE_PROVIEW*/ } else { /* Enough dynamic memory is not available. Determine if suspension is required. */ if (suspend) { /* Suspension is selected. */ /* Increment the number of tasks waiting. */ pool -> dm_tasks_waiting++;#ifdef INCLUDE_PROVIEW _RTProf_DumpMemoryPool(RT_PROF_ALLOCATE_MEMORY,pool,RT_PROF_WAIT);#endif /*INCLUDE_PROVIEW*/ /* Setup the suspend block and suspend the calling task. */ suspend_ptr = &suspend_block; suspend_ptr -> dm_memory_pool = pool; suspend_ptr -> dm_request_size = size; suspend_ptr -> dm_suspend_link.cs_next = NU_NULL; suspend_ptr -> dm_suspend_link.cs_previous = NU_NULL; task = (TC_TCB *) TCT_Current_Thread(); suspend_ptr -> dm_suspended_task = task; /* Determine if priority or FIFO suspension is associated with the memory pool. */ if (pool -> dm_fifo_suspend) { /* FIFO suspension is required. Link the suspend block into the list of suspended tasks on this memory pool. */ CSC_Place_On_List((CS_NODE **) &(pool -> dm_suspension_list), &(suspend_ptr -> dm_suspend_link)); } else { /* Get the priority of the current thread so the suspend block can be placed in the appropriate place. */ suspend_ptr -> dm_suspend_link.cs_priority = TCC_Task_Priority(task); CSC_Priority_Place_On_List((CS_NODE **) &(pool -> dm_suspension_list), &(suspend_ptr -> dm_suspend_link)); } /* Protect against system access. */ TCT_System_Protect(); /* Save the list protection in preparation for suspension. */ TCT_Set_Suspend_Protect(&(pool -> dm_protect)); /* Release protection of dynamic memory pool. */ TCT_Unprotect_Specific(&(pool -> dm_protect)); /* Finally, suspend the calling task. Note that the suspension call automatically clears the system protection. */ TCC_Suspend_Task((NU_TASK *) task, NU_MEMORY_SUSPEND, DMC_Cleanup, suspend_ptr, suspend); /* Pickup the return status. */ status = suspend_ptr -> dm_return_status; *return_pointer = suspend_ptr -> dm_return_pointer; } else { /* No suspension requested. Simply return an error status. */ status = NU_NO_MEMORY; *return_pointer = NU_NULL;#ifdef INCLUDE_PROVIEW _RTProf_DumpMemoryPool(RT_PROF_ALLOCATE_MEMORY,pool,RT_PROF_FAIL);#endif /*INCLUDE_PROVIEW*/ } } /* Release protection of the memory pool. */ TCT_Unprotect(); /* Return to user mode */ NU_USER_MODE(); /* Return the completion status. */ return(status);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -