📄 dmc.c
字号:
#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 to user mode */ NU_USER_MODE(); /* 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. *//* *//* 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 */NU_SUPERV_USER_VARIABLES /* Switch to supervisor mode */ NU_SUPERVISOR_MODE();#ifdef NU_ENABLE_STACK_CHECK /* Call stack checking function to check for an overflow condition. */ TCT_Check_Stack();#endif#ifdef NU_ENABLE_HISTORY /* Make an entry that corresponds to this function in the system history log. */ HIC_Make_History_Entry(NU_DEALLOCATE_MEMORY_ID, (UNSIGNED) memory, (UNSIGNED) 0, (UNSIGNED) 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -