diff src/nucleus/dmc.c @ 0:4e78acac3d88

src/{condat,cs,gpf,nucleus}: import from Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:23:26 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/nucleus/dmc.c	Fri Oct 16 06:23:26 2020 +0000
@@ -0,0 +1,1084 @@
+/*************************************************************************/
+/*                                                                       */
+/*               Copyright Mentor Graphics Corporation 2002              */
+/*                         All Rights Reserved.                          */
+/*                                                                       */
+/* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS  */
+/* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS   */
+/* SUBJECT TO LICENSE TERMS.                                             */
+/*                                                                       */
+/*************************************************************************/
+
+/*************************************************************************/
+/*                                                                       */
+/* FILE NAME                                               VERSION       */
+/*                                                                       */
+/*      dmc.c                                          Nucleus PLUS 1.14 */
+/*                                                                       */
+/* COMPONENT                                                             */
+/*                                                                       */
+/*      DM - Dynamic Memory Management                                   */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This file contains the core routines for the Dynamic Memory      */
+/*      Management component.                                            */
+/*                                                                       */
+/* DATA STRUCTURES                                                       */
+/*                                                                       */
+/*      None                                                             */
+/*                                                                       */
+/* FUNCTIONS                                                             */
+/*                                                                       */
+/*      DMC_Create_Memory_Pool              Create a dynamic memory pool */
+/*      DMC_Delete_Memory_Pool              Delete a dynamic memory pool */
+/*      DMC_Allocate_Memory                 Allocate a memory block from */
+/*                                            a dynamic memory pool      */
+/*      DMC_Deallocate_Memory               Deallocate a memory block    */
+/*                                            from a dynamic memory pool */
+/*      DMC_Cleanup                         Cleanup on timeout or a      */
+/*                                            terminate condition        */
+/*                                                                       */
+/* DEPENDENCIES                                                          */
+/*                                                                       */
+/*      cs_extr.h                           Common Service functions     */
+/*      tc_extr.h                           Thread Control functions     */
+/*      dm_extr.h                           Partition functions          */
+/*      hi_extr.h                           History functions            */
+/*                                                                       */
+/* HISTORY                                                               */
+/*                                                                       */
+/*      DATE                    REMARKS                                  */
+/*                                                                       */
+/*      03-01-1993      Created initial version 1.0                      */
+/*      04-19-1993      Verified version 1.0                             */
+/*      08-09-1993      Corrected pointer retrieval                      */
+/*                      loop, resulting in version 1.0a                  */
+/*      08-09-1993      Verified version 1.0a                            */
+/*      03-01-1994      Moved non-core functions into                    */
+/*                      supplemental files, changed                      */
+/*                      function interfaces to match                     */
+/*                      those in prototype, added                        */
+/*                      register options, changed                        */
+/*                      protection logic to reduce                       */
+/*                      overhead, resulting in                           */
+/*                      version 1.1                                      */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*      04-17-1996      updated to version 1.2                           */
+/*      03-24-1998      Released version 1.3.                            */
+/*      03-26-1999      Released 1.11m (new release                      */
+/*                        numbering scheme)                              */
+/*      04-17-2002      Released version 1.13m                           */
+/*      11-07-2002      Released version 1.14                            */
+/*************************************************************************/
+#define         NU_SOURCE_FILE
+
+
+#include        "cs_extr.h"                 /* Common service functions  */
+#include        "tc_extr.h"                 /* Thread control functions  */
+#include        "dm_extr.h"                 /* Dynamic memory functions  */
+#include        "hi_extr.h"                 /* History functions         */
+#include        "profiler.h"                /* ProView interface         */
+
+
+/* Define external inner-component global data references.  */
+
+extern CS_NODE         *DMD_Created_Pools_List;
+extern UNSIGNED         DMD_Total_Pools;
+extern TC_PROTECT       DMD_List_Protect;
+
+
+/* Define internal component function prototypes.  */
+
+VOID    DMC_Cleanup(VOID *information);
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      DMC_Create_Memory_Pool                                           */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function creates a dynamic memory pool and then places it   */
+/*      on the list of created dynamic memory pools.                     */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      DMCE_Create_Memory_Pool             Error checking shell         */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      CSC_Place_On_List                   Add node to linked-list      */
+/*      [HIC_Make_History_Entry]            Make entry in history log    */
+/*      [TCT_Check_Stack]                   Stack checking function      */
+/*      TCT_Protect                         Data structure protect       */
+/*      TCT_Unprotect                       Un-protect data structure    */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      pool_ptr                            Memory pool control block    */
+/*                                            pointer                    */
+/*      name                                Memory pool name             */
+/*      start_address                       Starting address of the pool */
+/*      pool_size                           Number of bytes in the pool  */
+/*      min_allocation                      Minimum allocation size      */
+/*      suspend_type                        Suspension type              */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      NU_SUCCESS                                                       */
+/*                                                                       */
+/* HISTORY                                                               */
+/*                                                                       */
+/*         DATE                    REMARKS                               */
+/*                                                                       */
+/*      03-01-1993      Created initial version 1.0                      */
+/*      04-19-1993      Verified version 1.0                             */
+/*      03-01-1994      Changed function interfaces to                   */
+/*                      match those in prototype,                        */
+/*                      added register options,                          */
+/*                      resulting in version 1.1                         */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*                                                                       */
+/*************************************************************************/
+STATUS  DMC_Create_Memory_Pool(NU_MEMORY_POOL *pool_ptr, CHAR *name,
+                        VOID *start_address, UNSIGNED pool_size,
+                        UNSIGNED min_allocation, OPTION suspend_type)
+{
+
+R1 DM_PCB      *pool;                       /* Pool control block ptr    */
+INT             i;                          /* Working index variable    */
+DM_HEADER      *header_ptr;                 /* Partition block header ptr*/
+NU_SUPERV_USER_VARIABLES
+
+    /* Switch to supervisor mode */
+    NU_SUPERVISOR_MODE();
+
+    /* Move input pool pointer into internal pointer.  */
+    pool =  (DM_PCB *) pool_ptr;
+
+
+#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_CREATE_MEMORY_POOL_ID, (UNSIGNED) pool,
+                        (UNSIGNED) start_address, (UNSIGNED) pool_size);
+
+#endif
+
+    /* First, clear the partition pool ID just in case it is an old
+       pool control block.  */
+    pool -> dm_id =             0;
+
+    /* Fill in the partition pool name.  */
+    for (i = 0; i < NU_MAX_NAME; i++)
+        pool -> dm_name[i] =  name[i];
+
+    /* Convert the pool's size into something that is evenly divisible by
+       the sizeof an UNSIGNED data element.  */
+    pool_size =  (pool_size/sizeof(UNSIGNED)) * sizeof(UNSIGNED);
+
+    /* Save the starting address and size parameters in the dynamic memory
+       control block.  */
+    pool -> dm_start_address =   start_address;
+    pool -> dm_pool_size =       pool_size;
+    pool -> dm_min_allocation =
+                ((min_allocation + sizeof(UNSIGNED) - 1)/sizeof(UNSIGNED)) *
+                                                              sizeof(UNSIGNED);
+
+    /* Setup the dynamic memory pool suspension type.  */
+    if (suspend_type == NU_FIFO)
+
+        /* FIFO suspension is selected, setup the flag accordingly.  */
+        pool -> dm_fifo_suspend =  NU_TRUE;
+    else
+
+        /* Priority suspension is selected.  */
+        pool -> dm_fifo_suspend =  NU_FALSE;
+
+    /* Clear the suspension list pointer.  */
+    pool -> dm_suspension_list =  NU_NULL;
+
+    /* Clear the number of tasks waiting on the dynamic memory pool.  */
+    pool -> dm_tasks_waiting =  0;
+
+    /* Initialize link pointers.  */
+    pool -> dm_created.cs_previous =    NU_NULL;
+    pool -> dm_created.cs_next =        NU_NULL;
+
+    /* Build a single block that has all of the memory.  */
+    header_ptr =  (DM_HEADER *) start_address;
+
+    /* Initialize the memory parameters.  */
+    pool -> dm_available =       pool_size - (2 * DM_OVERHEAD);
+    pool -> dm_memory_list =     header_ptr;
+    pool -> dm_search_ptr =      header_ptr;
+
+    /* Build the block header.  */
+    header_ptr -> dm_memory_pool =  pool;
+    header_ptr -> dm_memory_free =  NU_TRUE;
+    header_ptr -> dm_next_memory =  (DM_HEADER *)
+           (((BYTE_PTR) header_ptr) + pool -> dm_available + DM_OVERHEAD);
+    header_ptr -> dm_previous_memory =  header_ptr -> dm_next_memory;
+
+    /* Build the small trailer block that prevents block merging when the
+       pool wraps around.  Note that the list is circular so searching can
+       wrap across the physical end of the memory pool.  */
+    header_ptr =  header_ptr -> dm_next_memory;
+    header_ptr -> dm_next_memory =  (DM_HEADER *) start_address;
+    header_ptr -> dm_previous_memory =  (DM_HEADER *) start_address;
+    header_ptr -> dm_memory_pool =  pool;
+    header_ptr -> dm_memory_free =  NU_FALSE;
+
+    /* Initialize the protection structure.  */
+    pool -> dm_protect.tc_tcb_pointer =  NU_NULL;
+
+    /* Protect against access to the list of created memory pools.  */
+    TCT_Protect(&DMD_List_Protect);
+
+    /* At this point the dynamic memory pool is completely built.  The ID can
+       now be set and it can be linked into the created dynamic memory
+       pool list. */
+    pool -> dm_id =  DM_DYNAMIC_ID;
+
+    /* Link the memory pool into the list of created memory pools and
+       increment the total number of pools in the system.  */
+    CSC_Place_On_List(&DMD_Created_Pools_List, &(pool -> dm_created));
+    DMD_Total_Pools++;
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpMemoryPool(RT_PROF_CREATE_MEMORY_POOL,pool,RT_PROF_OK);
+#endif /*INCLUDE_PROVIEW*/
+    /* Release protection against access to the list of created memory
+       pools.  */
+    TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return successful completion.  */
+    return(NU_SUCCESS);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      DMC_Delete_Memory_Pool                                           */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function deletes a dynamic memory pool and removes it from  */
+/*      the list of created memory pools.  All tasks suspended on the    */
+/*      memory pool are resumed with the appropriate error status.       */
+/*      Note that this function does not free any memory associated with */
+/*      either the pool area or the pool control block.                  */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      DMCE_Delete_Memory_Pool             Error checking shell         */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      CSC_Remove_From_List                Remove node from 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_Protect                         Protect created list         */
+/*      TCT_Set_Current_Protect             Modify current protection    */
+/*      TCT_System_Protect                  Setup system protection      */
+/*      TCT_System_Unprotect                Release system protection    */
+/*      TCT_Unprotect                       Release protection           */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      pool_ptr                            Memory pool control block    */
+/*                                            pointer                    */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      NU_SUCCESS                                                       */
+/*                                                                       */
+/* HISTORY                                                               */
+/*                                                                       */
+/*         DATE                    REMARKS                               */
+/*                                                                       */
+/*      03-01-1993      Created initial version 1.0                      */
+/*      04-19-1993      Verified version 1.0                             */
+/*      03-01-1994      Changed function interfaces to                   */
+/*                      match those in prototype,                        */
+/*                      added register options, changed                  */
+/*                      protection logic to reduce                       */
+/*                      overhead, resulting in                           */
+/*                      version 1.1                                      */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*                                                                       */
+/*************************************************************************/
+STATUS  DMC_Delete_Memory_Pool(NU_MEMORY_POOL *pool_ptr)
+{
+
+R1 DM_PCB      *pool;                       /* Pool control block ptr    */
+DM_SUSPEND     *suspend_ptr;                /* Suspend block pointer     */
+DM_SUSPEND     *next_ptr;                   /* Next suspend block        */
+STATUS          preempt;                    /* Status for resume call    */
+NU_SUPERV_USER_VARIABLES
+
+    /* Switch to supervisor mode */
+    NU_SUPERVISOR_MODE();
+
+    /* Move input pool pointer into internal pointer.  */
+    pool =  (DM_PCB *) pool_ptr;
+
+#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_DELETE_MEMORY_POOL_ID, (UNSIGNED) pool,
+                                        (UNSIGNED) 0, (UNSIGNED) 0);
+
+#endif
+
+    /* Protect against simultaneous access to the memory pool.  */
+    TCT_Protect(&(pool -> dm_protect));
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpMemoryPool(RT_PROF_DELETE_MEMORY_POOL,pool,RT_PROF_OK);
+#endif /*INCLUDE_PROVIEW*/
+    /* Clear the memory pool ID.  */
+    pool -> dm_id =  0;
+
+    /* Release protection.  */
+    TCT_Unprotect();
+
+    /* Protect against access to the list of created memory pools.  */
+    TCT_Protect(&DMD_List_Protect);
+
+    /* Remove the memory pool from the list of created memory pools.  */
+    CSC_Remove_From_List(&DMD_Created_Pools_List, &(pool -> dm_created));
+
+    /* Decrement the total number of created memory pools.  */
+    DMD_Total_Pools--;
+
+    /* Pickup the suspended task pointer list.  */
+    suspend_ptr =  pool -> dm_suspension_list;
+
+    /* Walk the chain task(s) currently suspended on the memory pool.  */
+    preempt =  0;
+    while (suspend_ptr)
+    {
+
+        /* Protect against system access.  */
+        TCT_System_Protect();
+
+        /* Resume the suspended task.  Insure that the status returned is
+           NU_POOL_DELETED.  */
+        suspend_ptr -> dm_return_pointer =  NU_NULL;
+        suspend_ptr -> dm_return_status =   NU_POOL_DELETED;
+
+        /* Point to the next suspend structure in the link.  */
+        next_ptr =  (DM_SUSPEND *) (suspend_ptr -> dm_suspend_link.cs_next);
+
+        /* Resume the specified task.  */
+        preempt =  preempt |
+            TCC_Resume_Task((NU_TASK *) suspend_ptr -> dm_suspended_task,
+                                                NU_MEMORY_SUSPEND);
+
+        /* Determine if the next is the same as the current pointer.  */
+        if (next_ptr == pool -> dm_suspension_list)
+
+            /* Clear the suspension pointer to signal the end of the list
+               traversal.  */
+            suspend_ptr =  NU_NULL;
+        else
+
+            /* Move the next pointer into the suspend block pointer.  */
+            suspend_ptr =  next_ptr;
+
+        /* Modify current protection.  */
+        TCT_Set_Current_Protect(&DMD_List_Protect);
+
+        /* Clear the system protection.  */
+        TCT_System_Unprotect();
+    }
+
+    /* Determine if preemption needs to occur.  */
+    if (preempt)
+
+        /* Transfer control to system to facilitate preemption.  */
+        TCT_Control_To_System();
+
+    /* Release protection against access to the list of created memory
+       pools. */
+    TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return a successful completion.  */
+    return(NU_SUCCESS);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      DMC_Allocate_Memory                                              */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function allocates memory from the specified dynamic memory */
+/*      pool.  If dynamic memory is currently available, this function   */
+/*      is completed immediately.  Otherwise, if there is not enough     */
+/*      memory currently available, task suspension is possible.         */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      DMCE_Allocate_Memory                Error checking shell         */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      CSC_Place_On_List                   Place on suspend list        */
+/*      [HIC_Make_History_Entry]            Make entry in history log    */
+/*      TCC_Suspend_Task                    Suspend calling task         */
+/*      TCC_Task_Priority                   Pickup task priority         */
+/*      [TCT_Check_Stack]                   Stack checking function      */
+/*      TCT_Current_Thread                  Pickup current thread pointer*/
+/*      TCT_Protect                         Protect memory pool          */
+/*      TCT_Set_Suspend_Protect             Save suspend protection      */
+/*      TCT_System_Protect                  Protect system structures    */
+/*      TCT_Unprotect                       Release protection           */
+/*      TCT_Unprotect_Specific              Release specific protection  */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      pool_ptr                            Memory pool pointer          */
+/*      return_pointer                      Pointer to the destination   */
+/*                                            memory pointer             */
+/*      size                                Number of bytes requested    */
+/*      suspend                             Suspension option if full    */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      NU_SUCCESS                          If service is successful     */
+/*      NU_NO_MEMORY                        Memory not available         */
+/*      NU_TIMEOUT                          If timeout on service        */
+/*      NU_POOL_DELETED                     If memory pool deleted       */
+/*                                            during suspension          */
+/*                                                                       */
+/* HISTORY                                                               */
+/*                                                                       */
+/*         DATE                    REMARKS                               */
+/*                                                                       */
+/*      03-01-1993      Created initial version 1.0                      */
+/*      04-19-1993      Verified version 1.0                             */
+/*      03-01-1994      Changed function interfaces to                   */
+/*                      match those in prototype,                        */
+/*                      added register options, changed                  */
+/*                      protection logic to reduce                       */
+/*                      overhead, resulting in                           */
+/*                      version 1.1                                      */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*                                                                       */
+/*************************************************************************/
+STATUS  DMC_Allocate_Memory(NU_MEMORY_POOL *pool_ptr, VOID **return_pointer,
+                                        UNSIGNED size, UNSIGNED suspend)
+{
+
+R1 DM_PCB      *pool;                       /* Pool control block ptr    */
+R2 DM_SUSPEND  *suspend_ptr;                /* Pointer to suspend block  */
+DM_SUSPEND      suspend_block;              /* Allocate suspension block */
+R4 DM_HEADER   *memory_ptr;                 /* Pointer to memory         */
+R3 DM_HEADER   *new_ptr;                    /* New split block pointer   */
+UNSIGNED        free_size;                  /* Size of block found       */
+TC_TCB         *task;                       /* Task pointer              */
+STATUS          status;                     /* Completion status         */
+NU_SUPERV_USER_VARIABLES
+
+    /* Switch to supervisor mode */
+    NU_SUPERVISOR_MODE();
+
+    /* Move input pool pointer into internal pointer.  */
+    pool =  (DM_PCB *) pool_ptr;
+
+
+#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_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 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);
+
+#endif
+
+    /* Initialize the status as successful.  */
+    status =  NU_SUCCESS;
+
+    /* Pickup the associated pool's pointer.  It is inside the header of
+       each memory.  */
+    header_ptr =  (DM_HEADER *) (((BYTE_PTR) memory) - DM_OVERHEAD);
+    pool =        header_ptr -> dm_memory_pool;
+
+    /* Protect against simultaneous access to the memory pool.  */
+    TCT_Protect(&(pool -> dm_protect));
+
+    /* Mark the memory as available.  */
+    header_ptr -> dm_memory_free =  NU_TRUE;
+
+    /* Adjust the available number of bytes.  */
+    pool -> dm_available =  pool -> dm_available +
+                        (((BYTE_PTR) (header_ptr -> dm_next_memory)) -
+                           ((BYTE_PTR) header_ptr)) - DM_OVERHEAD;
+
+    /* Determine if the block can be merged with the previous neighbor.  */
+    if ((header_ptr -> dm_previous_memory) -> dm_memory_free)
+    {
+
+        /* Adjust the available number of bytes.  */
+        pool -> dm_available =  pool -> dm_available + DM_OVERHEAD;
+
+        /* Yes, merge block with previous neighbor.  */
+        (header_ptr -> dm_previous_memory) -> dm_next_memory =
+                                header_ptr -> dm_next_memory;
+        (header_ptr -> dm_next_memory) -> dm_previous_memory =
+                                header_ptr -> dm_previous_memory;
+
+        /* Move header pointer to previous.  */
+        header_ptr =  header_ptr -> dm_previous_memory;
+
+        /* Adjust the search pointer to the new merged block.  */
+        pool -> dm_search_ptr =  header_ptr;
+    }
+
+    /* Determine if the block can be merged with the next neighbor.  */
+    if ((header_ptr -> dm_next_memory) -> dm_memory_free)
+    {
+
+        /* Adjust the available number of bytes.  */
+        pool -> dm_available =  pool -> dm_available + DM_OVERHEAD;
+
+        /* Yes, merge block with next neighbor.  */
+        new_ptr =  header_ptr -> dm_next_memory;
+        (new_ptr -> dm_next_memory) -> dm_previous_memory =
+                                                header_ptr;
+        header_ptr -> dm_next_memory = new_ptr -> dm_next_memory;
+
+        /* Adjust the search pointer to the new merged block.  */
+        pool -> dm_search_ptr =  header_ptr;
+    }
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpMemoryPool(RT_PROF_DEALLOCATE_MEMORY,pool,RT_PROF_OK);
+#endif /*INCLUDE_PROVIEW*/
+    /* Determine if another task is waiting for memory from the pool.  */
+    suspend_ptr =  pool -> dm_suspension_list;
+    preempt =      0;
+    while (suspend_ptr)
+    {
+
+        /* Yes, another task is waiting for memory from the pool.  Search
+           the pool in the same manner as the memory allocation function.  */
+        size =        suspend_ptr -> dm_request_size;
+        header_ptr =  pool -> dm_search_ptr;
+        do
+        {
+
+            /* Determine if the block is free and if it can satisfy the request
+               of the first task waiting. */
+            if (header_ptr -> dm_memory_free)
+
+                /* Calculate the free block size.  */
+                free_size =  (((BYTE_PTR) (header_ptr -> dm_next_memory)) -
+                               ((BYTE_PTR) header_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.  */
+                header_ptr =  header_ptr -> dm_next_memory;
+        } while((free_size < size) && (header_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) header_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 =  header_ptr;
+                new_ptr -> dm_next_memory =      header_ptr -> dm_next_memory;
+                (new_ptr -> dm_next_memory) -> dm_previous_memory =  new_ptr;
+                header_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.  */
+            header_ptr -> dm_memory_free =  NU_FALSE;
+
+            /* Should the search pointer be moved?   */
+            if (pool -> dm_search_ptr == header_ptr)
+
+                /* Move the search pointer to the next free memory slot.  */
+                pool -> dm_search_ptr =  header_ptr -> dm_next_memory;
+
+            /* Decrement the number of tasks waiting counter.  */
+            pool -> dm_tasks_waiting--;
+
+            /* Remove the first suspended block from the list.  */
+            CSC_Remove_From_List((CS_NODE **) &(pool -> dm_suspension_list),
+                                        &(suspend_ptr -> dm_suspend_link));
+
+            /* Setup the appropriate return value.  */
+            suspend_ptr -> dm_return_status =   NU_SUCCESS;
+            suspend_ptr -> dm_return_pointer =  (VOID *)
+                                (((BYTE_PTR) header_ptr) + DM_OVERHEAD);
+
+            /* Setup system protect while task is being resumed.  */
+            TCT_System_Protect();
+
+            /* Resume the suspended task.  */
+            preempt =  preempt |
+              TCC_Resume_Task((NU_TASK *) suspend_ptr -> dm_suspended_task,
+                                                        NU_MEMORY_SUSPEND);
+
+            /* Switch back to the pool protection.  */
+            TCT_Set_Current_Protect(&(pool -> dm_protect));
+
+            /* Release system protection.  */
+            TCT_System_Unprotect();
+
+            /* Pickup the next suspension pointer.  */
+            suspend_ptr =  pool -> dm_suspension_list;
+        }
+        else
+
+            /* Not enough memory for suspended task. */
+            suspend_ptr =  NU_NULL;
+    }
+
+    /* Determine if a preempt condition is present.  */
+    if (preempt)
+
+        /* Transfer control to the system if the resumed task function
+           detects a preemption condition.  */
+        TCT_Control_To_System();
+
+    /* Release protection of the memory pool.  */
+    TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return the completion status.  */
+    return(status);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      DMC_Cleanup                                                      */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function is responsible for removing a suspension block     */
+/*      from a memory pool.  It is not called unless a timeout or        */
+/*      a task terminate is in progress.  Note that protection is        */
+/*      already in effect - the same protection at suspension time.      */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      TCC_Timeout                         Task timeout                 */
+/*      TCC_Terminate                       Task terminate               */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      CSC_Remove_From_List                Remove suspend block from    */
+/*                                            the suspension list        */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      information                         Pointer to suspend block     */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      None                                                             */
+/*                                                                       */
+/* HISTORY                                                               */
+/*                                                                       */
+/*         DATE                    REMARKS                               */
+/*                                                                       */
+/*      03-01-1993      Created initial version 1.0                      */
+/*      04-19-1993      Verified version 1.0                             */
+/*                                                                       */
+/*************************************************************************/
+VOID  DMC_Cleanup(VOID *information)
+{
+
+DM_SUSPEND      *suspend_ptr;               /* Suspension block pointer  */
+NU_SUPERV_USER_VARIABLES
+
+    /* Switch to supervisor mode */
+    NU_SUPERVISOR_MODE();
+
+    /* Use the information pointer as a suspend pointer.  */
+    suspend_ptr =  (DM_SUSPEND *) information;
+
+    /* By default, indicate that the service timed-out.  It really does not
+       matter if this function is called from a terminate request since
+       the task does not resume.  */
+    suspend_ptr -> dm_return_status =   NU_TIMEOUT;
+    suspend_ptr -> dm_return_pointer =  NU_NULL;
+
+    /* Decrement the number of tasks waiting counter.  */
+    (suspend_ptr -> dm_memory_pool) -> dm_tasks_waiting--;
+
+    /* Unlink the suspend block from the suspension list.  */
+    CSC_Remove_From_List((CS_NODE **)
+                &((suspend_ptr -> dm_memory_pool) -> dm_suspension_list),
+                                &(suspend_ptr -> dm_suspend_link));
+
+    /* Return to user mode */
+    NU_USER_MODE();
+}
+
+
+
+
+
+
+