📄 dmc.c
字号:
#ifdef NU_ENABLE_HISTORY
/* Make an entry that corresponds to this function in the system history
log. */
HIC_Make_History_Entry(NU_ALLOCATE_MEMORY_ID, (UNSIGNED) pool,
(UNSIGNED) return_pointer, (UNSIGNED) size);
#endif
/* Initialize the status as successful. */
status = NU_SUCCESS;
/* Adjust the request to a size evenly divisible by the number of bytes
in an UNSIGNED data element. Also, check to make sure it is of the
minimum size. */
if (size < pool -> dm_min_allocation)
/* Change size to the minimum allocation. */
size = pool -> dm_min_allocation;
else
/* Insure that size is a multiple of the UNSIGNED size. */
size =
((size + sizeof(UNSIGNED) - 1)/sizeof(UNSIGNED)) * sizeof(UNSIGNED);
/* Protect against simultaneous access to the memory pool. */
TCT_Protect(&(pool -> dm_protect));
/* Search the memory list for the first available block of memory that
satisfies the request. Note that blocks are merged during the
deallocation function. */
memory_ptr = pool -> dm_search_ptr;
do
{
/* Determine if the block is free and if it can satisfy the request. */
if (memory_ptr -> dm_memory_free)
/* Calculate the free block size. */
free_size = (((BYTE_PTR) (memory_ptr -> dm_next_memory)) -
((BYTE_PTR) memory_ptr)) - DM_OVERHEAD;
else
/* There are no free bytes available. */
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. */
/* Determine if the block needs to be 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 the completion status. */
return(status);
}
/*************************************************************************/
/* */
/* FUNCTION */
/* */
/* DMC_Deallocate_Memory */
/* */
/* DESCRIPTION */
/* */
/* This function deallocates a previously allocated dynamic memory */
/* block. The deallocated dynamic memory block is merged with any */
/* adjacent neighbors. This insures that there are no consecutive */
/* blocks of free memory in the pool (makes the search easier!). */
/* If there is a task waiting for dynamic memory, a determination */
/* of whether or not the request can now be satisfied is made after */
/* the deallocation is complete. */
/* */
/* AUTHOR */
/* */
/* Accelerated Technology, Inc. */
/* */
/* CALLED BY */
/* */
/* Application */
/* DMCE_Deallocate_Memory Error checking shell */
/* */
/* CALLS */
/* */
/* CSC_Remove_From_List Remove from suspend list */
/* [HIC_Make_History_Entry] Make entry in history log */
/* TCC_Resume_Task Resume a suspended task */
/* [TCT_Check_Stack] Stack checking function */
/* TCT_Control_To_System Transfer control to system */
/* TCT_Set_Current_Protect Set current protection */
/* TCT_System_Protect Protect system structures */
/* TCT_System_Unprotect Release system protection */
/* TCT_Protect Protect dynamic memory pool */
/* TCT_Unprotect Release protection */
/* */
/* INPUTS */
/* */
/* memory Pointer to dynamic memory */
/* */
/* OUTPUTS */
/* */
/* NU_SUCCESS */
/* */
/* HISTORY */
/* */
/* DATE REMARKS */
/* */
/* 03-01-1993 Created initial version 1.0 */
/* 04-19-1993 Verified version 1.0 */
/* 03-01-1994 Added register options, changed */
/* protection logic to reduce */
/* overhead, resulting in */
/* version 1.1 */
/* */
/* 03-18-1994 Verified version 1.1 */
/* */
/*************************************************************************/
STATUS DMC_Deallocate_Memory(VOID *memory)
{
R1 DM_PCB *pool; /* Pool pointer */
R3 DM_SUSPEND *suspend_ptr; /* Pointer to suspend block */
R2 DM_HEADER *header_ptr; /* Pointer to memory hdr */
R4 DM_HEADER *new_ptr; /* New memory block pointer */
UNSIGNED size; /* Suspended task request */
UNSIGNED free_size; /* Amount of free bytes */
STATUS preempt; /* Preemption flag */
STATUS status; /* Completion status */
#ifdef NU_ENABLE_STACK_CHECK
/* Call stack checking function to check for an overflow condition. */
TCT_Check_Stack();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -