view src/gpf/frame/vsi_mem.c @ 230:baa738eeb842

FCBM code implemented in first pass
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 01 May 2021 10:05:53 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/* 
+------------------------------------------------------------------------------
|  File:       vsi_mem.c
+------------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG 
|                 All rights reserved. 
| 
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 The receipt of or possession of this file does not convey 
|                 any rights to reproduce or disclose its contents or to 
|                 manufacture, use, or sell anything it may describe, in 
|                 whole, or in part, without the specific written consent of 
|                 Texas Instruments Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  This Module defines the virtual system interface part
|             for the dynamic memory pools.
+----------------------------------------------------------------------------- 
*/ 

#ifndef __VSI_MEM_C__
#define __VSI_MEM_C__
#endif

/*==== INCLUDES ===================================================*/

#include "string.h"

#include "typedefs.h"
#include "vsi.h"
#include "os.h"
#include "frm_defs.h"
#include "frm_types.h"
#include "frm_glob.h"

#ifdef NU_DEBUG
 #include "frame.h"
#endif

#ifdef MEMORY_SUPERVISION
 #include "tools.h"
#endif

/*==== CONSTANTS ==================================================*/

#ifndef RUN_INT_RAM
char const *waited_str = "Waited for partition";
char const *bigger_str = "Bigger partition allocated than requested";
char const *free_str   = "Partition Deallocation failed";
#else
extern char const *waited_str;
extern char const *bigger_str;
extern char const *free_str;
#endif

#ifdef NU_DEBUG
extern char const *freed_str;
#endif
 
/*==== TYPES ======================================================*/


/*==== EXTERNALS ==================================================*/

/* -------------- S H A R E D - BEGIN ---------------- */
#ifdef _TOOLS_
#pragma data_seg("FRAME_SHARED") 
#endif

#if !defined (_TOOLS_) && !defined (_LINUX_) && !defined (_SOLARIS_)
extern const T_FRM_PARTITION_GROUP_CONFIG partition_grp_config[];
#endif

/*==== VARIABLES ==================================================*/

#ifndef RUN_INT_RAM
 char init_partition_memory = DISABLE_PARTITON_INIT;
 char init_partition_pattern = 0;
 T_HANDLE vsi_m_sem_handle = VSI_ERROR;
#else
 extern char init_partition_memory;
 extern char init_partition_pattern;
 extern T_HANDLE vsi_m_sem_handle;
#endif
	        
#ifdef _TOOLS_
#pragma data_seg()
#endif
/* -------------- S H A R E D - END ---------------- */

/*==== FUNCTIONS ==================================================*/

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_new           |
+--------------------------------------------------------------------+

  PURPOSE : allocate a partition of a pool defined by the parameter type

*/

T_VOID_STRUCT * vsi_m_new (ULONG Size, ULONG type FILE_LINE_TYPE)
{
LONG Status;
T_VOID_STRUCT *prim;
OS_HANDLE pool;
T_HANDLE Caller;
ULONG flags;
ULONG suspend;

  Caller = 0;

  pool  = type & VSI_MEM_POOL_MASK;
  flags = type & VSI_MEM_FLAG_MASK;

  if ( flags & VSI_MEM_NON_BLOCKING )
    suspend = OS_NO_SUSPEND;
  else
    suspend = OS_SUSPEND;

  Status = os_AllocatePartition ( Caller, &prim, Size, suspend, pool );

  switch ( Status )
  {
    case OS_OK:
    break;
    case OS_WAITED:
#ifdef NU_DEBUG
      Caller = e_running[os_MyHandle()];
      pf_handle_warning ( OS_SYST_WRN_WAIT_PARTITION, "%s %s, entity %s, Size %d, %s(%d)", 
                          syst_wrn, waited_str, pf_TaskTable[Caller].Name, Size FILE_LINE_MACRO_PASSED );
#endif
    break;
    case OS_ERROR:
    case OS_TIMEOUT:
      if ( !(flags & VSI_MEM_NON_BLOCKING) )
      {
        /* fatal error for blocking allocation and 'HISR' caller */
        Caller = e_running[os_MyHandle()];
        vsi_o_assert ( NO_TASK, OS_SYST_ERR_NO_PARTITION FILE_LINE_MACRO_PASSED,
                       "No Partition available, entity %s, size %d",
                       pf_TaskTable[Caller].Name, Size );
      }
      return NULL;
    /*lint -e527 suppress Warning -- Unreachable */
    break;
    /*lint +e527 */
    case OS_ALLOCATED_BIGGER:
#ifdef NU_DEBUG
      Caller = e_running[os_MyHandle()];
      pf_handle_warning ( OS_SYST_WRN_BIG_PARTITION, "%s %s, entity %s, Size %d, %s(%d)", 
                          syst_wrn, bigger_str, pf_TaskTable[Caller].Name, Size FILE_LINE_MACRO_PASSED );
#endif
    break;
    default:
      return NULL;
    /*lint -e527 suppress Warning -- Unreachable */
    break;
    /*lint +e527 */
  }

  prim = prim + PPM_OFFSET;

  if ( init_partition_memory )
  {
    memset( (char*)prim, init_partition_pattern, (unsigned int)Size );
  }
#ifdef MEMORY_SUPERVISION
  /*
   * Pools registered via vsi_m_register_pool() cannot be handle by the partition supervision. The
   * id therefor is set to 0, to allow the supervision functions to ignore them.
   */
  if ( pool == DmemGroupHandle )
  {
    /* for primitive vsi_ppm_new() is called after the opc has been entered in the header */
    Caller = e_running[os_MyHandle()];
    vsi_ppm_new ( Caller, Size, (T_PRIM_HEADER*)prim, file, line );
  }
#endif /* MEMORY_SUPERVISION */

  return prim;
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_new_size      |
+--------------------------------------------------------------------+

  PURPOSE : allocate partition and retern partition size

*/
T_VOID_STRUCT *vsi_m_new_size ( ULONG size, ULONG type,
                                ULONG *partition_size FILE_LINE_TYPE)
{
T_FRM_PARTITION_POOL_CONFIG * pool_config;
T_VOID_STRUCT *prim;

  if ( ( prim = vsi_m_new ( size, type FILE_LINE ) ) != NULL )
  {
#if defined (_TOOLS_) || defined (_LINUX_) || defined (_SOLARIS_)
    *partition_size = size;
#else
    pool_config = (T_FRM_PARTITION_POOL_CONFIG*)partition_grp_config[PrimGroupHandle].grp_config;
    while ( pool_config != NULL )
    {
      if ( size <= pool_config->part_size )
      {
        *partition_size = pool_config->part_size;
        break;
      }
      else
      {
        pool_config++;
      }
    }
#endif
  }
  return (prim);
}
#endif

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_free          |
+--------------------------------------------------------------------+

  PURPOSE : deallocate a partition

*/

int vsi_m_free (T_VOID_STRUCT **Msg FILE_LINE_TYPE)
{
T_HANDLE Caller;
#ifdef MEMORY_SUPERVISION
  Caller = e_running[os_MyHandle()];
  vsi_ppm_free ( Caller, (T_PRIM_HEADER*)*Msg, file, line );
#endif

  Caller = 0;
  if ( os_DeallocatePartition ( Caller, *Msg - PPM_OFFSET ) != OS_ERROR )
  {
    *Msg = NULL;
    return VSI_OK;
  }
#ifdef NU_DEBUG
  Caller = e_running[os_MyHandle()];
  pf_handle_warning ( OS_SYST_WRN_FREE_FAILED, "%s %s in %s, %s(%d)", 
                      syst_wrn, free_str, pf_TaskTable[Caller].Name FILE_LINE_MACRO_PASSED );
#endif
  return VSI_ERROR;
}
#endif

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_cnew          |
+--------------------------------------------------------------------+

  PURPOSE : allocate a memory with reference counter

*/

T_VOID_STRUCT * vsi_m_cnew (ULONG size, ULONG type FILE_LINE_TYPE)
{
T_M_HEADER *mem;
#ifdef MEMORY_SUPERVISION
T_HANDLE caller;
#endif

  if ( (mem = (T_M_HEADER*)vsi_m_new ( size+sizeof(T_M_HEADER), type FILE_LINE )) != NULL )
  {
    /* set reference counter */
    mem->ref_cnt = 1;
    /* set descriptor type */
    mem->desc_type = (SHORT)((type & VSI_MEM_DESC_MASK) >> 16);
    /* return pointer to user data */
#ifdef MEMORY_SUPERVISION
    caller = e_running[os_MyHandle()];
    vsi_ppm_new ( caller, size+sizeof(T_M_HEADER), (T_PRIM_HEADER*)mem, file, line );
#endif
    return (T_VOID_STRUCT*)(mem + 1);
  }
  else
  {
    return NULL;
  }

}
#endif

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_cfree         |
+--------------------------------------------------------------------+

  PURPOSE : allocate a memory with reference counter

*/

int vsi_m_cfree (T_VOID_STRUCT **ptr FILE_LINE_TYPE)
{
T_HANDLE caller = 0;
LONG sts;
T_M_HEADER *mem;

  /* get pointer to start of partition. Here is the reference counter */
  mem = (T_M_HEADER*)*ptr - 1;

#ifdef NU_DEBUG
  if ( os_is_valid_partition ((T_VOID_STRUCT*)mem) )
  {
    /* free to non-partition memory */
    caller = e_running[os_MyHandle()];
    vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED,
                   "MFREE to non-partition memory, entity %s, ptr 0x%x", pf_TaskTable[caller].Name, *ptr );
    return VSI_ERROR;
  }
#endif

  sts = os_ObtainSemaphore (caller, vsi_m_sem_handle, OS_SUSPEND);
  if ( sts == OS_ERROR || sts == OS_TIMEOUT )
  {
    /* Semaphore invalid or overrun */
    caller = e_running[os_MyHandle()];
    vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED,
                   "Ref Cnt Semaphore overrun, entity %s", pf_TaskTable[caller].Name );
    return VSI_ERROR;
  }
  if ( mem->ref_cnt <= 0 )
  {
#ifdef NU_DEBUG
    /* partition already freed */
    caller = e_running[os_MyHandle()];
    pf_handle_warning ( OS_SYST_WRN_MULTIPLE_FREE, "%s %s in %s, %s(%d)", 
                        syst_wrn, freed_str, pf_TaskTable[caller].Name FILE_LINE_MACRO_PASSED );
#endif
    os_ReleaseSemaphore (caller, vsi_m_sem_handle);
    return VSI_OK;
  }
  if ( --(mem->ref_cnt) == 0 )
  {
#ifdef _NUCLEUS_
#ifdef NU_DEBUG

    if ( os_PartitionCheck( (ULONG*)mem ) == OS_PARTITION_GUARD_PATTERN_DESTROYED )
    {
      caller = e_running[os_MyHandle()];
      os_ReleaseSemaphore (caller, vsi_m_sem_handle);
      vsi_o_assert ( caller, OS_SYST_ERR_PCB_PATTERN FILE_LINE_MACRO_PASSED,
                     "Partition Guard Pattern destroyed (MFREE),Task %s,Partition 0x%x",
                     pf_TaskTable[caller].Name, mem );
      return VSI_ERROR;
    }
#endif
#endif
    if (vsi_m_free ( (T_VOID_STRUCT**)&mem FILE_LINE ) != VSI_OK)
    {
      os_ReleaseSemaphore (caller, vsi_m_sem_handle);
      return VSI_ERROR;
    }

    *ptr=NULL;
  }
  os_ReleaseSemaphore (caller, vsi_m_sem_handle);
  return VSI_OK;

}
#endif

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_cfree         |
+--------------------------------------------------------------------+

  PURPOSE : allocate a memory with reference counter

*/

int vsi_m_attach (T_VOID_STRUCT *ptr FILE_LINE_TYPE)
{
T_HANDLE caller = 0;
LONG sts;
T_M_HEADER *mem;

  /* get pointer to start of partition. Here is the reference counter */
  mem = (T_M_HEADER*)ptr - 1;

#ifdef NU_DEBUG
  if ( os_is_valid_partition ((T_VOID_STRUCT*)mem) )
  {
    /* attach to non-partition memory */
    caller = e_running[os_MyHandle()];
    vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED,
                   "MATTACH to non-partition memory, entity %s, ptr 0x%x", pf_TaskTable[caller].Name, ptr );
  }
#endif
  sts = os_ObtainSemaphore (caller, vsi_m_sem_handle, OS_SUSPEND);
  if ( sts == OS_ERROR || sts == OS_TIMEOUT )
  {
    /* Semaphore invalid or overrun */
    caller = e_running[os_MyHandle()];
    vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED,
                   "Ref Cnt Semaphore overrun, entity %s", pf_TaskTable[caller].Name );
  }
  if ( mem->ref_cnt <= 0 )
  {
    /* attach to non allocated memory */
    caller = e_running[os_MyHandle()];
    vsi_o_assert ( NO_TASK, OS_SYST_ERR FILE_LINE_MACRO_PASSED,
                   "MATTACH to free memory, entity %s, ptr 0x%x", pf_TaskTable[caller].Name, ptr );
  }
  else
  {
    /* increment reference counter */
    mem->ref_cnt++;
  }
  os_ReleaseSemaphore (caller, vsi_m_sem_handle);
  return VSI_OK;

}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_status        |
+--------------------------------------------------------------------+

  PURPOSE : retrieve number of used/available partitions

*/

GLOBAL int vsi_m_status ( T_HANDLE caller, ULONG size, USHORT type, USHORT *free, USHORT *alloc )
{
#ifdef _NUCLEUS_
OS_HANDLE pool;

  pool = type & VSI_MEM_POOL_MASK;

  if ( os_GetPartitionPoolStatus ( size, pool, free, alloc ) == OS_OK )
    return VSI_OK;
  else
#endif
    return VSI_ERROR;
}
#endif

#ifndef _TOOLS_
#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_register_pool |
+--------------------------------------------------------------------+

  PURPOSE : register a new partition pool group to be accessable via VSI

*/

GLOBAL int vsi_m_register_pool ( char * name, T_HANDLE * pool_gr_id )
{
OS_HANDLE pool_gr;
  
  if ( os_GetPartitionGroupHandle (OS_NOTASK, name, &pool_gr) == OS_OK )
  {
    *pool_gr_id = (T_HANDLE)pool_gr;
    return VSI_OK;
  }
  else
  {
    return VSI_ERROR;
  }
}
#endif
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : VSI_MEM             |
| STATE   : code                       ROUTINE : vsi_m_init          |
+--------------------------------------------------------------------+

  PURPOSE : retrieve number of used/available partitions

*/

GLOBAL int vsi_m_init ( char enable_init, char pattern )
{

  init_partition_memory  = enable_init;
  init_partition_pattern = pattern; 
  os_CreateSemaphore ( 0, (char*)"VSI_MSEM", 1, &vsi_m_sem_handle, 0 );

  return VSI_OK;
}
#endif