view src/gpf/frame/frame.c @ 268:f2e52cab0a73

abb_inth.c: check all interrupt causes, not just one The original code used if - else if - else if etc constructs, thus the first detected interrupt was the only one handled. However, Iota ITSTATREG is a clear-on-read register, thus if we only handle the first detected interrupt and skip checking the others, then the other interrupts will be lost, if more than one interrupt happened to occur in one ABB interrupt handling cycle - a form of rare race condition. Change the code to check all interrupts that were read in this cycle.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 13 Jun 2021 18:17:53 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/* 
+------------------------------------------------------------------------------
|  File:       frame.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 Modul defines the general frame functionality.
+----------------------------------------------------------------------------- 
*/ 


#ifndef __FRAME_C__
#define __FRAME_C__
#endif

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

#include <stdarg.h>
#include "typedefs.h"
#include "string.h"
#include "stdio.h"

#include "glob_defs.h"
#include "os.h"
#include "vsi.h"
#include "pei.h"
#include "frame.h"
#include "tools.h"
#include "gdi.h"
#include "frm_defs.h"
#include "frm_types.h"
#include "frm_glob.h"
#include "route.h"
#include "p_frame.h"
#include "prf_func.h"
#ifdef _ESF_SUPPORT_
#include "esf_func.h"
#endif
#include "frm_ext.h"

/*==== TYPES ======================================================*/

typedef struct
{
  char const *Name;
  USHORT Id;
} T_NAME_ID;

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

#define RUNNING   0x01
#undef VSI_CALLER
#define VSI_CALLER   TaskHandle,

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

#if defined _NUCLEUS_ && !defined _TARGET_
extern char TraceBuffer[];
#endif

#ifndef _TOOLS_
extern const T_MEMORY_POOL_CONFIG memory_pool_config[];
extern const T_FRM_PARTITION_GROUP_CONFIG partition_grp_config[];
extern T_HANDLE MemoryPoolHandle[];
extern OS_HANDLE PoolGroupHandle[];
extern const T_DRV_LIST DrvList[]; 
#ifdef MEMORY_SUPERVISION      
extern USHORT NumberOfPPMPartitions;
extern USHORT NumOfPPMPools;
extern USHORT NumOfPPMGroups;
extern USHORT NumOfPrimPools;
extern USHORT NumOfDmemPools;
#endif
#endif

extern T_DRV_LIST const *DriverConfigList;

#ifndef _TOOLS_
extern const T_COMPONENT_ADDRESS *ComponentTables[];
extern const char * const frame_version_date;
extern const char * const frame_version_time;
extern const char * const misc_version_date;
extern const char * const misc_version_time;
extern const char * const tif_version_date;
extern const char * const tif_version_time;
#endif

#ifdef _TOOLS_
  __declspec (dllimport) T_HANDLE TST_Handle;
#else
  extern T_HANDLE TST_Handle;
#endif

#ifdef MEMORY_SUPERVISION
extern int ppm_check_partition_owner;
#endif

/*==== VARIABLES ==================================================*/
    
#ifndef RUN_INT_RAM
UBYTE SuppressOK=1;
GLOBAL T_HANDLE MemPoolHandle;                                                 
GLOBAL T_HANDLE PrimGroupHandle;
GLOBAL T_HANDLE DmemGroupHandle;
GLOBAL T_HANDLE TestGroupHandle;
GLOBAL T_HANDLE LemuGroupHandle;
GLOBAL T_HANDLE int_data_pool_handle;
GLOBAL T_HANDLE ext_data_pool_handle;
GLOBAL UBYTE FrameEnv=0;
GLOBAL USHORT TestInterface = 0;
GLOBAL USHORT NextTimerEntry = 0;
int time_is_tdma_frame;
char error_ind_dst[RESOURCE_NAMELEN] = {0};
T_FRM_ERROR_IND *frm_error_ind = NULL;
char check_desclist = FALSE;
GLOBAL USHORT NumberOfStartedTasks = 0;
GLOBAL USHORT NumberOfRunningTasks = 0;
GLOBAL USHORT TooManyTasks = 0;

const T_PEI_INFO DummyInfo = 
  { 
    "",          /* Name */
    { 
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL
    },
    768,        /* stack size */
    10,         /* queue entries */
    1,          /* priority */
    0,          /* number of timers */
    COPY_BY_REF /* Flags */
 };

const T_NAME_ID Resource[] =
{
  { "TASK",       OS_OBJTASK},
  { "QUEUE",      OS_OBJQUEUE},
  { "TIMER",      OS_OBJTIMER },
  { "SEMAPHORE",  OS_OBJSEMAPHORE},
  { "PARTITION",  OS_OBJPARTITIONGROUP},
  { "MEMORY",     OS_OBJMEMORYPOOL},
  { NULL,         0 }
};

#ifdef _TOOLS_
LOCAL T_COMPONENT_ADDRESS *ComponentTables [NUM_OF_COMPONENT_TABLES+1]={0};
typedef void T_INIT_FUNC ( void );
T_INIT_FUNC *InitFunc;
ULONG init_stack_time = 0;
ULONG init_local_time = 0;
ULONG  MaxPrimPartSize = 65536;
USHORT TextTracePartitionSize = 260;
#endif

char TaskName [ RESOURCE_NAMELEN ];

#else /* RUN_INT_RAM */
extern USHORT TestInterface;
extern USHORT NextTimerEntry;
extern USHORT NumberOfStartedTasks;
extern USHORT NumberOfRunningTasks;
extern USHORT TooManyTasks;
extern char TaskName[];
extern T_HANDLE int_data_pool_handle;
extern T_HANDLE ext_data_pool_handle;
#endif /* RUN_INT_RAM */

#ifdef _TOOLS_
#pragma data_seg()
#endif

#ifdef _ESF_SUPPORT_
int esf_init_func2_ready = FALSE;
int firstTime = TRUE;
#endif

/* -------------- S H A R E D - END ---------------- */


/*==== PROTOTYPES =================================================*/

GLOBAL void pf_TaskEntry (T_HANDLE TaskHandle, ULONG Value );
LOCAL SHORT pf_HandleMessage (T_HANDLE TaskHandle, OS_QDATA *pMsg );
LOCAL LONG pf_CreateTask ( const T_COMPONENT_ADDRESS *Comp );
LOCAL void pf_ProcessProtocolPrim ( T_HANDLE TaskHandle, T_VOID_STRUCT *pPrim);
LOCAL void pf_Reset (T_HANDLE TaskHandle);
int is_entity_in_task (T_HANDLE t_handle, char *name );
int int_vsi_o_ttrace ( T_HANDLE Caller, ULONG TraceClass, const char * const format, va_list varpars );

#ifndef _TOOLS_
GLOBAL void InitializeApplication ( void );
#endif

/*==== LINT =======================================================*/

/*lint -e522 suppress Warning -- Expected void type, assignment, increment or decrement */

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

#ifdef _TOOLS_
/*
+------------------------------------------------------------------------------
|  Function     :  pf_get_frameenv
+------------------------------------------------------------------------------
|  Description  :  This function returns the current value of FrameEnv
|
|  Parameters   :  void
|
|  Return       :  FrameEnv
+------------------------------------------------------------------------------
*/
USHORT pf_get_frameenv (void)
{
  return (USHORT) FrameEnv;
}

#endif /* _TOOLS_ */

#ifndef _TOOLS_
#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : StartFrame          |
+--------------------------------------------------------------------+

  PURPOSE : Start the frame 

*/
SHORT StartFrame ( void )
{
  prf_init();
  pf_Init(NULL);
  pf_CreateAllEntities();
#ifdef _ESF_SUPPORT_
  esf_init();
  esf_init_func1(); 
#endif
  pf_StartAllTasks ();
  return ( PF_OK );
}
#endif
#endif /* ndef _TOOLS_ */

#if defined (_LINUX_) || (defined _SOLARIS_)
int main ()
{
  (void) StartFrame ();
  for (;;)
  {
    os_SuspendTask (0, 1500);
  }
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : is_entity_in_task   |
+--------------------------------------------------------------------+

  PURPOSE : Initialize the frame 

*/
int is_entity_in_task ( T_HANDLE t_handle, char *name )
{
int i;

  for ( i = MaxEntities; i > 0; i-- )
  {
    if ( pf_TaskTable[i].TaskHandle == t_handle )
    {
      if ( !strncmp (pf_TaskTable[i].Name, name, RESOURCE_NAMELEN-1) )
        return TRUE;
    }
  }
  return FALSE;
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : pf_Init             |
+--------------------------------------------------------------------+

  PURPOSE : Initialize the frame 

*/

/*lint -esym(715,ConfigAddress) only needed for _TOOLS_*/
GLOBAL void pf_Init ( T_CONFIGURATION_ADDRESS *ConfigAddress)
{
#ifndef _TOOLS_
const T_FRM_PARTITION_POOL_CONFIG * pool_config;
USHORT i = 1,j = 0;
#endif

#if defined _NUCLEUS_ && !defined _TARGET_ || defined (_LINUX_)
  printf ("FRAME VERSION: %s, %s\n",frame_version_date, frame_version_time);
  printf ("MISC VERSION:  %s, %s\n",misc_version_date,  misc_version_time);
  printf ("TIF VERSION:   %s, %s\n\n",tif_version_date, tif_version_time);
#endif
  if ( os_Initialize() == OS_ERROR )
  {
    vsi_o_assert ( 0, OS_SYST_ERR, __FILE__, __LINE__, "OS initialization error" );
  }
  
  time_is_tdma_frame = 0;
  TestInterface = 0;
  NextTimerEntry = 0;
#ifdef _TOOLS_
  ComponentTables[RCV_ADR] = ConfigAddress->RcvAdr; 
  ComponentTables[TST_ADR] = ConfigAddress->TstAdr; 
  ComponentTables[END_OF_COMP_TABLE] = NULL; 
  DriverConfigList = ConfigAddress->DrvListAdr;
  InitFunc = ConfigAddress->InitFuncAdr;
  FrameEnv = *ConfigAddress->FrameEnvAdr;
#else
  DriverConfigList = &DrvList[0];
#endif

#ifndef _TOOLS_

  
  j = 0;
  /*
   * create memory pools
   */
  while ( memory_pool_config[j].Name != NULL )
  {
    if ( memory_pool_config[j].Size > 1 )
      os_CreateMemoryPool ( NO_TASK, 
                          memory_pool_config[j].Name, 
                          memory_pool_config[j].PoolAddress, 
                          memory_pool_config[j].Size, 
                          (OS_HANDLE*)MemoryPoolHandle[j] );                    
    j++;
  }

#ifdef _NUCLEUS_
  os_SetPoolHandles (ext_data_pool_handle, int_data_pool_handle);
#endif

  /*
   * create partition pools
   */

  for ( i = 0; partition_grp_config[i].name != NULL; i++ )
  {
#ifdef MEMORY_SUPERVISION      
//    if ( strcmp ("TEST", partition_grp_config[i].name ) )
//    {
      /* currently all created groups are counted to ease offset calculation for
         partition supervision */
      NumOfPPMGroups++;
//    }
#endif
    pool_config = partition_grp_config[i].grp_config;
    while ( pool_config->part_size && pool_config->part_num )
    {
      os_CreatePartitionPool ( NO_TASK, 
                               partition_grp_config[i].name, 
                               pool_config->mem, 
                               (USHORT)pool_config->part_num,
                               pool_config->part_size, 
                               (OS_HANDLE*)PoolGroupHandle[i] );   
#ifdef MEMORY_SUPERVISION 
	  /* TEST pool not under partition supervision */
      if ( strcmp ("TEST", partition_grp_config[i].name ) )
      {
        NumOfPPMPools++;
        NumberOfPPMPartitions += pool_config->part_num;
      }
#endif
      if ( !strcmp ("PRIM", partition_grp_config[i].name ) )
      {
        if ( MaxPrimPartSize < pool_config->part_size )
        {
          MaxPrimPartSize = pool_config->part_size;
        }
#ifdef MEMORY_SUPERVISION
        NumOfPrimPools++;
#endif
      }
#ifdef MEMORY_SUPERVISION
      if ( !strcmp ("DMEM", partition_grp_config[i].name ) )
      {
        NumOfDmemPools++;
      }
#endif
      pool_config++;
    }
  }

#endif
  /* 
   * To allow CCD (TaskHandle = 0) the usage of dynamic Memory to create a semaphore
   * the MemPoolHandle for non-task users is initialized with the handle of the int_data_pool
   * pool.
   */
  pf_TaskTable[0].MemPoolHandle = int_data_pool_handle;
  strcpy ( pf_TaskTable[0].Name, "IRQ" );

  rt_Init();
#ifdef _TOOLS_
  (InitFunc)();
#else
  InitializeApplication();
#endif
#ifdef MEMORY_SUPERVISION
  InitializePPM();
#endif /* MEMORY_SUPERVISION */

  InitializeTimer();
  InitializeDriverConfig();
#if !defined _TARGET_ && !defined _TOOLS_
  vsi_pcheck_init(); 
#endif
#ifndef _TOOLS_
  fei_lemu_SendToQueue_init();
#endif
  /* 
  not needed -> temporarily removed 
  vsi_c_init_com_matrix (MaxEntities);
  */
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : pf_CreateAllEntities|
+--------------------------------------------------------------------+
*/
GLOBAL SHORT pf_CreateAllEntities (void)
{
int i = 0;

  while ( ComponentTables[i] != NULL )
  {
    pf_CreateTask ( ComponentTables[i] );
    i++;
  }
  InitializeTrace();
  return PF_OK;
}
#endif
#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : pf_CreateEntity     |
+--------------------------------------------------------------------+
*/
LOCAL LONG pf_CreateTask ( const T_COMPONENT_ADDRESS *Comp )
{
T_PEI_INFO const *Info;
T_HANDLE TaskHandle;
T_HANDLE mem_pool_handle = ext_data_pool_handle;
int Priority = 0;
ULONG StackSize = 0;
const T_PEI_FUNC *PeiTable;
USHORT     QueueEntries = 0;
USHORT   	 NumOfTimers = 0;
U32      Flags;
char *Name = NULL;
static int e_handle = 1;
int start_e_handle;
int i;

  start_e_handle = e_handle;
  while ( Comp->PeiCreate || Comp->Name )
  {
    if ( e_handle > MaxEntities )
    {
      vsi_o_assert ( 0, OS_SYST_ERR, __FILE__, __LINE__, "More than MAX_ENTITIES" );
    }
    if (  Comp->PeiCreate && Comp->PeiCreate ( &Info ) == PEI_OK )
    {
      if ( Comp->Priority != ASSIGNED_BY_TI )
      {
        if ( Priority < Comp->Priority )
          Priority = Comp->Priority;
      }
      else
      {
        if ( Priority < Info->Priority )
          Priority = Info->Priority;
      }
      Flags = Info->Flags;
      PeiTable = &Info->PeiTable;
      Name = (char*)Info->Name;
      if ( StackSize < Info->StackSize )
        StackSize = Info->StackSize;
      pf_TaskTable[e_handle].QueueEntries = Info->QueueEntries;
      NumOfTimers = Info->NumOfTimers;
    }
    else if ( Comp->Name && strlen (Comp->Name) <= RESOURCE_NAMELEN )
    {
      Flags = DummyInfo.Flags;
      PeiTable = &DummyInfo.PeiTable;
      Name = Comp->Name;
      if ( StackSize < DummyInfo.StackSize )
        StackSize = DummyInfo.StackSize;
      if ( Priority < DummyInfo.Priority )
        Priority = DummyInfo.Priority;
      pf_TaskTable[e_handle].QueueEntries = DummyInfo.QueueEntries;
      NumOfTimers = DummyInfo.NumOfTimers;
    }
    else
      return PF_ERROR;

    if ( QueueEntries < pf_TaskTable[e_handle].QueueEntries )
      QueueEntries = pf_TaskTable[e_handle].QueueEntries;

    pf_TaskTable[e_handle].Flags = Flags;
    pf_TaskTable[e_handle].PeiTable = PeiTable;
    pf_TaskTable[e_handle].NumOfTimers = NumOfTimers;
    strncpy (pf_TaskTable[e_handle].Name, Name, RESOURCE_NAMELEN);
    pf_TaskTable[e_handle].Name[RESOURCE_NAMELEN-1] = 0;
    if ( pf_TaskTable[e_handle].Flags & INT_DATA_TASK )
    {
      pf_TaskTable[e_handle].MemPoolHandle = int_data_pool_handle;
      mem_pool_handle = int_data_pool_handle;
    }
    else
    {
      pf_TaskTable[e_handle].MemPoolHandle = ext_data_pool_handle;
      mem_pool_handle = ext_data_pool_handle;
    }
    prf_log_entity_create ((void*)e_handle, Name);
    e_handle++;
    Comp++;
  }
  if ( e_handle > start_e_handle + 1 )
    Name = (char*)Comp->Priority;

#ifdef MEMORY_SUPERVISION
  StackSize = StackSize + (StackSize>>3);
#endif
  if ( os_CreateTask (NO_TASK, Name, pf_TaskEntry, StackSize, (USHORT)Priority, &TaskHandle, 
                      mem_pool_handle) == OS_OK )
  {
    for ( i = start_e_handle; i < e_handle; i++ )
    {
      pf_TaskTable[i].TaskHandle = TaskHandle;
    }
    return PF_OK;
  }
  else
    vsi_o_assert ( NO_TASK, OS_SYST_ERR, __FILE__, __LINE__, "Error at creating %s Task", Name );  
  /*lint +e771 */

  return PF_ERROR;
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : pf_StartAllTasks    |
+--------------------------------------------------------------------+
*/
GLOBAL SHORT pf_StartAllTasks ( void )
{
int e_handle;
int t_handle;
int started_t_handle = 0;

  for ( e_handle = 1; e_handle <= MaxEntities; e_handle++ )
  {
    if ( pf_TaskTable[e_handle].Name[0] != 0 )
    {
      if ( (t_handle = pf_TaskTable[e_handle].TaskHandle) != started_t_handle )
      {
        if ( os_StartTask ( NO_TASK, t_handle, 0 ) == OS_ERROR)
          return OS_ERROR;
        NumberOfStartedTasks++;
        started_t_handle = t_handle;
      }
    }
  }
  return OS_OK;
}
#endif


#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : pf_TaskEntry        |
+--------------------------------------------------------------------+
*/
/*lint -esym(715,Value) suppress Info -- Symbol 'Value' not referenced */
GLOBAL void pf_TaskEntry (T_HANDLE TaskHandle, ULONG Value )
{
OS_QDATA Msg;
OS_HANDLE mem_pool_handle = ext_data_pool_handle;
LONG sts;
int i;
int queue_entries;
int queue_handle;
int biggest_queue_size = 0;
int sum_queue_size = 0;
U32 entity_flags = 0;
#ifndef _TOOLS_
char queue_name [ RESOURCE_NAMELEN ];
#endif
static int entity_init_fail_cnt = 0;

#ifdef _ESF_SUPPORT_
  {
    /* OS timer should not be started at this point, otherwise risk of
       race condition.
       Furthermore, ESF THIF socket interface can't be used by task tst 
       before esf_init_func2() is completed. 
     */

    T_HANDLE esf_init_func2_sem;
    T_HANDLE caller;

    caller = e_running[os_MyHandle()];
    esf_init_func2_sem = vsi_s_open (caller, "esf_init_func2_sem", 1);

    vsi_s_get (caller, esf_init_func2_sem);      /* start of critical section */
    if (firstTime)
    {
      firstTime = FALSE;
      esf_init_func2();
      esf_init_func2_ready = TRUE; 
    }
    vsi_s_release(caller, esf_init_func2_sem); /* end of critical section */

    while (!esf_init_func2_ready)
    {
      os_SuspendTask(caller, 100);
    }
  }
#endif

  if ( is_entity_in_task ( TaskHandle, FRM_TST_NAME ) == FALSE
    && is_entity_in_task ( TaskHandle, FRM_RCV_NAME ) == FALSE )
  {
    while ( !(TestInterface & RUNNING) )
    {
      os_SuspendTask (TaskHandle, 100);
    }
  }

  for ( i = MaxEntities; i > 0; i-- )
  {
    if ( pf_TaskTable[i].TaskHandle == TaskHandle )
    {
      if ( pf_TaskTable[i].Flags & ADD_QUEUE_SIZES )
      {
        entity_flags |= ADD_QUEUE_SIZES;
      }
      sum_queue_size += pf_TaskTable[i].QueueEntries;
      if ( biggest_queue_size < pf_TaskTable[i].QueueEntries )
      {
        biggest_queue_size = pf_TaskTable[i].QueueEntries;
      }
      if ( pf_TaskTable[i].Flags & INT_DATA_TASK )
        mem_pool_handle = int_data_pool_handle;
    }
  }

  /* set queue size depending on the flag exported by the entities */
  if ( entity_flags & ADD_QUEUE_SIZES )
  {
    queue_entries = sum_queue_size;
  }
  else
  {
    queue_entries = biggest_queue_size;
  }

#ifdef _TOOLS_
  if ( os_CreateQueue ( TaskHandle, 0, pf_TaskTable[TaskHandle].Name, (USHORT)queue_entries, &queue_handle,
                        pf_TaskTable[TaskHandle].MemPoolHandle) == OS_ERROR )
  {
    vsi_o_assert ( NO_TASK, OS_SYST_ERR_QUEUE_CREATE, __FILE__, __LINE__, 
                   "Error at creating %s Queue", pf_TaskTable[TaskHandle].Name ); 
  }
#else
  os_GetTaskName ( TaskHandle, TaskHandle, queue_name );
  if ( os_CreateQueue ( TaskHandle, 0, queue_name, (USHORT)queue_entries, &queue_handle, mem_pool_handle) == OS_ERROR )
  {
    vsi_o_assert ( NO_TASK, OS_SYST_ERR_QUEUE_CREATE, __FILE__, __LINE__, "Error at creating %s Queue", queue_name ); 
  }
#endif

  for ( i = MaxEntities; i > 0; i-- )
  {
    if ( pf_TaskTable[i].TaskHandle == TaskHandle )
    {
      pf_TaskTable[i].QueueHandle = queue_handle;
      pf_TaskTable[i].FirstTimerEntry = &TimerHandleField [ NextTimerEntry ];
      if ( (NextTimerEntry += pf_TaskTable[i].NumOfTimers) >= MaxTimer )
        vsi_o_assert ( NO_TASK, OS_SYST_ERR_MAX_TIMER, __FILE__, __LINE__, 
                       "Number of Timers > MAX_TIMER" );  
    }
  }

  for ( i = MaxEntities; i > 0; i-- )
  {
    if ( pf_TaskTable[i].TaskHandle == TaskHandle )
    {
      if (pf_TaskTable[i].PeiTable->pei_init != NULL)
      {
        e_running[TaskHandle] = i;
        while (pf_TaskTable[i].PeiTable->pei_init (i) == PEI_ERROR)
        {
          if ( entity_init_fail_cnt++ > (NumberOfStartedTasks * 5) )
            vsi_o_ttrace(NO_TASK, TC_SYSTEM, "%s pei_init() failed",pf_TaskTable[i].Name );
		      os_SuspendTask (TaskHandle, 100);
        }
        e_running[TaskHandle] = 0;
      }
    }
  }

  if ( is_entity_in_task ( TaskHandle, FRM_TST_NAME ) == TRUE ) 
    TestInterface |= RUNNING;


  if ( ++NumberOfRunningTasks == NumberOfStartedTasks )
  {
    if ( TooManyTasks )
      vsi_o_assert (NO_TASK, OS_SYST_ERR_MAX_TASK, __FILE__, __LINE__, "Number of entities > MAX_ENTITIES" );  
    vsi_o_ttrace(NO_TASK, TC_SYSTEM, "All tasks entered main loop" );
#if defined _NUCLEUS_ && !defined _TARGET_
    printf ("%s\n","All tasks entered main loop");
#endif
#ifdef _TARGET_
    TraceMask[0] = TC_SYSTEM;	/* FreeCalypso change */
    os_dar_set_filter();
#endif
  }
  for ( i = MaxEntities; i > 0; i-- )
  {
    if ( pf_TaskTable[i].TaskHandle == TaskHandle )
    {
      if (pf_TaskTable[i].PeiTable->pei_run != NULL)
      {
        if ( !(pf_TaskTable[i].Flags & PASSIVE_BODY) )
        {
            /*
             * in the active body variant call pei_run
             */
            e_running[TaskHandle] = i;
            pf_TaskTable[i].PeiTable->pei_run (TaskHandle, pf_TaskTable[i].QueueHandle );
#ifdef _TOOLS_
            pf_TaskTable[i].PeiTable->pei_exit();
            NextTimerEntry -= pf_TaskTable[i].NumOfTimers;
            rt_RoutingModify ( TaskHandle, (char*)SYSPRIM_REDIRECT_TOKEN, (char*)SYSPRIM_CLEAR_TOKEN );
            os_DestroyQueue ( TaskHandle, pf_TaskTable[i].QueueHandle );
            e_running[TaskHandle] = 0;
            os_DestroyTask ( TaskHandle, TaskHandle );
#endif
            e_running[TaskHandle] = 0;
            for (;;)
              os_SuspendTask(TaskHandle,10000);
        }
      }
    }
  }

  /*
   * in the passive body variant wait for a message and
   * handle it
   */
  for ( i = MaxEntities; i > 0; i-- )
  {
    if ( pf_TaskTable[i].TaskHandle == TaskHandle )
    {
      break;
    }
  }
  for (;;)
  {
    sts = os_ReceiveFromQueue ( TaskHandle, pf_TaskTable[i].QueueHandle,
                                &Msg, OS_SUSPEND );
    switch ( sts )
    {
      case OS_OK:
#if defined (_TOOLS_) || defined (_LINUX_)
           e_running[TaskHandle] = TaskHandle;
           pf_HandleMessage (TaskHandle, &Msg);
#else
           e_running[TaskHandle] = Msg.e_id;
           prf_log_entity_activate ((void*)Msg.e_id);
           pf_HandleMessage (Msg.e_id, &Msg);
#endif
           e_running[TaskHandle] = 0;
#ifdef _NUCLEUS_ 
           if ( os_CheckTaskStack ( TaskHandle ) == OS_ERROR )
           {
             os_GetTaskName ( TaskHandle, TaskHandle, TaskName );
             vsi_o_assert ( TaskHandle, OS_SYST_ERR_STACK_OVERFLOW, __FILE__, __LINE__, 
                            "%s Stack overflow", TaskName );
           }
#endif
      break;
      case OS_TIMEOUT:
      break;
      case OS_ERROR:
           for(;;)
             os_SuspendTask(TaskHandle,10000);
      /*lint -e527, suppress Warning -- Unreachable */
      break;
      default:
           for(;;)
             os_SuspendTask(TaskHandle,10000);
      break;
      /*lint +e527 */

    }
  }
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : pf_Timeout          |
+--------------------------------------------------------------------+
*/
GLOBAL void pf_Timeout (T_HANDLE TaskHandle, T_HANDLE EntityHandle, USHORT TimerIndex )
{
OS_QDATA TimeoutMsg;

  TimeoutMsg.data16 = MSG_TIMEOUT;
  TimeoutMsg.data32 = (ULONG)TimerIndex;
#ifdef _TOOLS_
  TimeoutMsg.len = 0;
#endif
  TimeoutMsg.e_id = EntityHandle;
  os_GetTime ( 0, &TimeoutMsg.time );
    
  *(pf_TaskTable[EntityHandle].FirstTimerEntry + TimerIndex) |= TIMEOUT_OCCURRED;

#ifdef _TOOLS_
  if ( rt_Route (TaskHandle, pf_TaskTable[EntityHandle].QueueHandle, OS_NORMAL, OS_SUSPEND, 
    &TimeoutMsg ) == OS_TIMEOUT )
#else
  if ( rt_Route (TaskHandle, EntityHandle, OS_NORMAL, OS_SUSPEND, 
    &TimeoutMsg ) == OS_TIMEOUT )
#endif
      vsi_o_assert ( 0, OS_SYST_ERR_QUEUE_FULL, __FILE__, __LINE__, 
                     "Timeout write attempt to %s queue failed", pf_TaskTable[EntityHandle].Name );
}
#endif

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : pf_HandleMessage    |
+--------------------------------------------------------------------+
*/
LOCAL SHORT pf_HandleMessage (T_HANDLE TaskHandle, OS_QDATA *pMsg )
{
ULONG PrimId = 0; 

  switch (pMsg->data16)
  {
    case MSG_PRIMITIVE:
      if ( pMsg->ptr != NULL )
      {
        PrimId = ((T_PRIM_HEADER*)(pMsg->ptr))->opc;

        if ( PrimId & SYS_MASK )
        {
          pf_ProcessSystemPrim ( TaskHandle, pMsg->ptr );
        }
        else
        {
          pf_ProcessProtocolPrim ( TaskHandle, pMsg->ptr );
        }
      }
    break;
    case MSG_SIGNAL:
      if ( pf_TaskTable[TaskHandle].PeiTable->pei_signal != NULL )
      {
        pf_TaskTable[TaskHandle].PeiTable->pei_signal ( pMsg->data32, pMsg->ptr ); 
      }
    break;
    case MSG_TIMEOUT:
      if ( *(pf_TaskTable[TaskHandle].FirstTimerEntry + pMsg->data32) & TIMEOUT_OCCURRED )
      {
        if ( !(*(pf_TaskTable[TaskHandle].FirstTimerEntry + pMsg->data32) & PERIODIC_TIMER) )
        {
          os_DestroyTimer ( TaskHandle, (OS_HANDLE)(*(pf_TaskTable[TaskHandle].FirstTimerEntry + pMsg->data32) & TIMER_HANDLE_MASK) );
          *(pf_TaskTable[TaskHandle].FirstTimerEntry + pMsg->data32) = 0;
        }
        else
        {
          *(pf_TaskTable[TaskHandle].FirstTimerEntry + pMsg->data32) &= ~TIMEOUT_OCCURRED;
        }
        vsi_o_ttrace ( TaskHandle, TC_TIMER, "Timeout   : Index %d",pMsg->data32) ;
        if ( pf_TaskTable[TaskHandle].PeiTable->pei_timeout != NULL )
          pf_TaskTable[TaskHandle].PeiTable->pei_timeout ( (USHORT)pMsg->data32 ); 
      }
    break;
    default:
      VSI_PPM_FREE(pMsg->ptr);
      os_DeallocatePartition (TaskHandle, pMsg->ptr-PPM_OFFSET );
      return PF_ERROR;
    /*lint -e527, suppress Warning -- Unreachable */
    break;
    /*lint +e527 */
  }
  return PF_OK;
}
#endif

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)           MODULE  : FRAME                 |
| STATE   : code                     ROUTINE : pf_ProcessProtocolPrim|
+--------------------------------------------------------------------+
*/
LOCAL void pf_ProcessProtocolPrim ( T_HANDLE TaskHandle, T_VOID_STRUCT *pPrim)
{

  if ( TaskHandle != NO_TASK )
  {
    if (pf_TaskTable[TaskHandle].PeiTable->pei_primitive != NULL)
    {
#ifdef PRIM_AUTO_FREE
      if ( pf_TaskTable[TaskHandle].Flags & PARTITION_AUTO_FREE )
      {
        /* 
         * TST uses its own partition pool and is handled differently 
         */
        if ( TaskHandle != TST_Handle )
        {
          processed_prim[TaskHandle] = pPrim;
          freed_prim[TaskHandle] = NULL;
        }
      }
#endif /* PRIM_AUTO_FREE */
#ifdef MEMORY_SUPERVISION
      if ( TaskHandle != TST_Handle ) /* Trace pools are not monitored by PPM */ 
        VSI_PPM_RCV(pPrim);
#endif
      pf_TaskTable[TaskHandle].PeiTable->pei_primitive (pPrim);

#ifdef PRIM_AUTO_FREE
      if ( pf_TaskTable[TaskHandle].Flags & PARTITION_AUTO_FREE )
      {
        /*
         * if PSTORE was called during the primitive processing, PFREE was no longer
         * blocked inside the entity and it could have happened that a primitive  
         * was freed and then newly allocated either by the same or by a different
         * entity (IRQ). To avoid auto free it is checked if an effective free was
         * done with the pointer passed to pei_primitive(). In this case the 
         * partition is not freed.
         */
        if ( freed_prim[TaskHandle] == pPrim )
        {
          freed_prim[TaskHandle] = NULL;
          return;
        }
        else
        {
          processed_prim[TaskHandle] = NULL;

          if ( pPrim != NULL ) 
          {
            FREE ( P2D(pPrim) );
          }
          return;
        }
      }
      else
#endif /* PRIM_AUTO_FREE */
        return;
    }
  }
  if ( pPrim != NULL)
  {
#ifndef _TARGET_
    vsi_o_ttrace ( NO_TASK, TC_SYSTEM, "Primitive discarded in dummy entity %s, opc 0x%x",
                   pf_TaskTable[TaskHandle].Name, ((T_PRIM_HEADER*)pPrim)->opc );
#endif
    VSI_PPM_RCV(pPrim);
    FREE ( P2D(pPrim) );
  }
}
#endif
 
#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)           MODULE  : FRAME                 |
| STATE   : code                     ROUTINE : pf_ProcessSystemPrim  |
+--------------------------------------------------------------------+
*/ 
GLOBAL void pf_ProcessSystemPrim ( T_HANDLE TaskHandle, T_VOID_STRUCT *pPrim)
{
char * data;
/*lint -e813, suppress Info 813: auto variable 'token' has size '132' -> uncritical in this context */
char token[TRACE_TEXT_SIZE];
/*lint +e813 */
BOOL Error = FALSE;
LONG i;
unsigned int Length;
T_HANDLE min, max;
char TraceMaskBuffer[9];
ULONG trace_mask;
LONG state;
#ifdef _TOOLS_
T_S_HEADER *s_hdr;
#endif

  VSI_PPM_RCV(pPrim);

  data = (char *)P2D( pPrim );

  Length = GetNextToken (data, token, " #");

  if (!strcmp (token, SYSPRIM_REDIRECT_TOKEN)
   OR !strcmp (token, SYSPRIM_DUPLICATE_TOKEN))
  {

    if (TaskHandle NEQ NO_TASK)
    {
      /*
       * Redirect or Duplicate primitives
       */
      if ( (state = rt_RoutingModify (TaskHandle, token, data+strlen(token)+1)) != RT_OK )
      {
#ifdef NU_DEBUG
        switch ( state )
        {
          case RT_NO_MEM:
            vsi_o_ttrace(NO_TASK, TC_SYSTEM, "SYSTEM WARNING: Out of Memory - routing command rejected");
            VSI_PPM_FREE(pPrim);
            os_DeallocatePartition (TaskHandle, pPrim-PPM_OFFSET );
            return;
            /*lint -e527, suppress Warning -- Unreachable */
            break;
            /*lint +e527 */
		      case RT_ERROR: Error = TRUE;
            break;
        }
#else
        Error = TRUE;
#endif
      }
    }
  }
  else if ( !strcmp ( token, SYSPRIM_TRACECLASS_TOKEN) )
  {
    if ( Length < strlen(data)-1 )
    {
      GetNextToken (data+Length+1, token, " #");
      trace_mask = ASCIIToHex(token, CHARS_FOR_32BIT);
      if ( TaskHandle == TST_Handle )
      {
        min = 1;
        max = MaxEntities;
      }
      else
      {
        min = TaskHandle;
        max = TaskHandle;
      }
      for ( i = min; i <= max; i++ )
      {
        if ( vsi_settracemask ( TaskHandle, i, trace_mask) == VSI_ERROR )
          break;
      }
    }
    else
    {
      vsi_gettracemask ( TaskHandle, TaskHandle, &trace_mask);
      HexToASCII ( trace_mask, TraceMaskBuffer, CHARS_FOR_32BIT );
      TraceMaskBuffer[8] = 0;
      sprintf ( data, "%s %s %s", pf_TaskTable[TaskHandle].Name, SYSPRIM_TRACECLASS_TOKEN, TraceMaskBuffer );
      vsi_o_ttrace ( NO_TASK, TC_SYSTEM, data );
    }
  }
  else if (!strcmp (token, SYSPRIM_CONFIG_TOKEN))
  {
    /*
     * Dynamic Configuration
     */
    if (TaskHandle != NO_TASK)
    {
      /*
       * call the pei_config function of the entity
       */
      if (pf_TaskTable[TaskHandle].PeiTable->pei_config NEQ NULL)
        if ( pf_TaskTable[TaskHandle].PeiTable->pei_config ( data+strlen (token)+1 ) == PEI_ERROR )
          Error = TRUE;
    }
  }
#if 0
  /* not needed -> temporarily removed */
  else if (!strcmp (token, SYSPRIM_ISOLATE_TOKEN))
  {
    if ( rt_isolate_entity (TaskHandle, data+strlen(token)+1) == RT_ERROR )
      Error = TRUE;
  }
#endif
  else if (!strcmp (token, SYSPRIM_REGISTER_ERR_IND))
  {
    strncpy ( error_ind_dst, data+strlen(token)+1, RESOURCE_NAMELEN );
    error_ind_dst[RESOURCE_NAMELEN-1] = 0;
    if ( frm_error_ind == NULL )
    {
      frm_error_ind = (T_FRM_ERROR_IND*)vsi_c_pnew (sizeof(T_FRM_ERROR_IND), FRM_ERROR_IND FILE_LINE_MACRO );
    }
  }
  else if (!strcmp (token, SYSPRIM_WITHDRAW_ERR_IND))
  {
    if ( frm_error_ind != NULL )
    {
      error_ind_dst[0] = 0;
      vsi_c_pfree( (T_VOID_STRUCT**)&frm_error_ind FILE_LINE_MACRO );
      frm_error_ind = NULL;
    }
  }
  else if (!strcmp (token, SYSPRIM_STATUS_TOKEN))
  {
    GetNextToken (data+strlen(token)+1, token, " #");
    VSI_PPM_FREE(pPrim);
    os_DeallocatePartition (TaskHandle, pPrim-PPM_OFFSET );
    i = 0;
    while ( Resource[i].Name && strcmp ( Resource[i].Name, token ) )
      i++;
    if ( vsi_object_info (TaskHandle, Resource[i].Id, FIRST_ENTRY, token, sizeof(token)) == VSI_OK )       
    {
      vsi_o_ttrace ( NO_TASK, TC_SYSTEM, token ); 
      while ( vsi_object_info (TaskHandle, Resource[i].Id, NEXT_ENTRY, token, sizeof(token)) == VSI_OK )
      {
        vsi_o_ttrace ( NO_TASK, TC_SYSTEM, token ); 
      }
    }
    return;
  }
#if 0
  else if (!strcmp (token, SYSPRIM_READ_COM_MATRIX))
  {
    state = vsi_c_get_com_matrix_entry ( FIRST_ENTRY, token );
    if ( state == VSI_OK )
    {
      vsi_o_ttrace ( NO_TASK, TC_SYSTEM, token ); 
      do
      {
        if ( (state = vsi_c_get_com_matrix_entry ( NEXT_ENTRY, token)) == VSI_OK )
          vsi_o_ttrace ( NO_TASK, TC_SYSTEM, token ); 
      } while ( state == VSI_OK );
    }
  }
#endif
#ifdef _TARGET_
  else if (!strcmp (token, SYSPRIM_READ_FFS_DAR))
  {
    state = os_read_dar_ffs_data ( FIRST_ENTRY, token, TextTracePartitionSize - sizeof(T_S_HEADER) - sizeof(T_PRIM_HEADER) - 1 );
    if ( state == OS_OK )
    {
      vsi_o_ttrace ( NO_TASK, TC_SYSTEM, token ); 
      do
      {
        if ( (state = os_read_dar_ffs_data ( NEXT_ENTRY, token, TextTracePartitionSize - sizeof(T_S_HEADER) - sizeof(T_PRIM_HEADER) - 1)) == OS_OK )
          vsi_o_ttrace ( NO_TASK, TC_SYSTEM, token ); 
      } while ( state == OS_OK );
    }
    else
      vsi_o_ttrace ( NO_TASK, TC_SYSTEM, "No DAR entry stored" ); 

  }
#endif
#if !defined _TARGET_ && !defined _TOOLS_
  else if (!strcmp (token, SYSPRIM_PCHECK))
  {
    pcheck_active[TaskHandle] = TRUE;
  }
#endif
  else if (!strcmp (token, SYSPRIM_ROUTE_DESCLIST))
  {
    route_desclist[TaskHandle] = TRUE;
  }
  else if (!strcmp (token, SYSPRIM_CHECK_DESCLIST))
  {
    check_desclist = TRUE;
  }
#ifdef _NUCLEUS_
  else if (!strcmp (token, SYSPRIM_VERSION_TOKEN))
  {
    vsi_o_ttrace (NO_TASK, TC_SYSTEM,"FRAME VERSION: %s, %s",frame_version_date, frame_version_time);
    vsi_o_ttrace (NO_TASK, TC_SYSTEM,"MISC VERSION:  %s, %s",misc_version_date,  misc_version_time);
    vsi_o_ttrace (NO_TASK, TC_SYSTEM,"TIF VERSION:   %s, %s",tif_version_date,   tif_version_time);
  }
#endif
  else if (!strcmp (token, SYSPRIM_RESET_TOKEN))
  {
    /*
     * Reset
     */
    pf_Reset (TaskHandle);
  }
#ifdef _TOOLS_
  else if (!strcmp (token, SYSPRIM_EXIT_TOKEN))
  {
    /*
     * Exit and delete
     */
    if (pf_TaskTable[TaskHandle].PeiTable->pei_exit != NULL)
    {
      pf_TaskTable[TaskHandle].PeiTable->pei_exit();
    }
    VSI_PPM_FREE(pPrim);
    os_DeallocatePartition (TaskHandle, pPrim-PPM_OFFSET );
    vsi_p_delete(0,TaskHandle);
  }
#endif /* _TOOLS_ */
#ifdef MEMORY_SUPERVISION
  else if (!strcmp (token, SYSPRIM_CHECK_OWNER))
  {
    ppm_check_partition_owner = 1;
  }
  else if (!strcmp (token, SYSPRIM_SHOW_MEMORY))
  {
    /*
     * Show state of the partition pool monitor
     */
    VSI_PPM_FREE(pPrim);
    os_DeallocatePartition (TaskHandle, pPrim-PPM_OFFSET );
    TracePoolstatus (TaskHandle);
    return;
  }
#endif /* MEMORY_SUPERVISION */    
#ifndef _TOOLS_  
  else if (!strcmp (token, SYSPRIM_SELECT_TIME_TDMA))
  {
    time_is_tdma_frame = 1;
  }
#endif
#ifdef _TOOLS_
  else if (!strcmp (token, SYSPRIM_IS_STACK_TIME))
  {
    s_hdr = P_SHDR(pPrim);
    set_stack_time (s_hdr->time);
  }
  else if (!strcmp (token, SYSPRIM_REGISTER_TOKEN))
  {
    OS_HANDLE comhandle;
    GetNextToken (data+strlen(token)+1, token, " #");
    if (os_create_extq (token, &comhandle) == OS_OK)
    {
      if (!strcmp (token, FRM_PCO_NAME))
      {
        vsi_o_set_htrace (comhandle);
      }
    }
    else
      Error = TRUE;
  }
  else if (!strcmp (token, SYSPRIM_WITHDRAW_TOKEN))
  {
    GetNextToken (data+strlen(token)+1, token, " #");
    if (os_destroy_extq (token) == OS_OK)
    {
      if (!strcmp (token, FRM_PCO_NAME))
      {
        vsi_o_set_htrace (0);
      }
    }
    else
      Error = TRUE;
  }
#endif /* _TOOLS_ */
  else
    Error = TRUE;

  if ( Error )
  {
    vsi_o_ttrace ( NO_TASK, TC_SYSTEM, "SYSTEM WARNING:Invalid system primitive '%s'",data );
  }
  else
  {
    if ( !SuppressOK )
    {
      vsi_o_ttrace ( NO_TASK, TC_SYSTEM, "OK (%s %s)", pf_TaskTable[TaskHandle].Name, data );
    }
  }
  VSI_PPM_FREE(pPrim);
  os_DeallocatePartition (TaskHandle, pPrim-PPM_OFFSET );
}
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-GPF (8415)             MODULE  : FRAME               |
| STATE   : code                       ROUTINE : pf_Reset            |
+--------------------------------------------------------------------+
*/
LOCAL void pf_Reset (T_HANDLE TaskHandle)
{
  if (TaskHandle != NO_TASK)
  {
    if (pf_TaskTable[TaskHandle].PeiTable->pei_exit != NULL)
      pf_TaskTable[TaskHandle].PeiTable->pei_exit();
    /* 
     * reset a single entity
     */
    if (pf_TaskTable[TaskHandle].PeiTable->pei_init != NULL)
      while (pf_TaskTable[TaskHandle].PeiTable->pei_init(TaskHandle) == PEI_ERROR)
        os_SuspendTask ( TaskHandle, 5);
  }
  else
  {
    USHORT Handle;
    /*
     * reset all entities
     */
    for (Handle = 1; Handle <= MaxEntities; Handle++)
    {
      if (pf_TaskTable[TaskHandle].PeiTable->pei_exit != NULL)
        pf_TaskTable[TaskHandle].PeiTable->pei_exit();

      if (pf_TaskTable[Handle].PeiTable->pei_init != NULL)
        while (pf_TaskTable[TaskHandle].PeiTable->pei_init(TaskHandle) == PEI_ERROR)
          os_SuspendTask ( TaskHandle, 5);
    }
  }
}
#endif

#ifdef _TOOLS_
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : FRAME               |
| STATE   : code                       ROUTINE : set_stack_time      |
+--------------------------------------------------------------------+

  PURPOSE : stores the local time of stack under test. Used to align 
            timestamps while tracing.

*/
void set_stack_time ( ULONG time )
{
  init_stack_time = time;
  os_GetTime ( NO_TASK, &init_local_time );
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-Frame (8415)           MODULE  : FRAME               |
| STATE   : code                       ROUTINE : get_stack_time      |
+--------------------------------------------------------------------+

  PURPOSE : returns the local time of stack under test. Used to align 
            timestamps while tracing.

*/
void get_local_time ( ULONG *time )
{
OS_TIME current_local_time;

 os_GetTime ( NO_TASK, &current_local_time );
 *time = init_stack_time + current_local_time - init_local_time;
}

#endif

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

  PURPOSE : frame error and warning handling

*/
/*lint -e506, suppress Warning 506: Constant value Boolean */
/*lint -e718, suppress nfo 718: Symbol '_va_argref' undeclared, assumed to return int */
int pf_handle_warning ( USHORT cause, const char * const format,...)
{
T_HANDLE caller;
va_list varpars;
static int recursion_count = 0;
USHORT free;
USHORT alloc;

  /* recursion counter is needed to avoid endless loop when generating warning during processing of warning */
  if ( recursion_count == 0 )
  {
    recursion_count++;
    caller = e_running[os_MyHandle()];
    va_start (varpars, format);              
    int_vsi_o_ttrace ( NO_TASK, TC_SYSTEM, format, varpars );

    if ( error_ind_dst[0] != 0 )
    {
      /* drop the warning, if there are fewer than 3 partitions available to avoid deadlock */
      vsi_m_status ( caller, sizeof(T_FRM_WARNING_IND)+sizeof(T_PRIM_HEADER), PrimGroupHandle, &free, &alloc );
      if ( free >= 3 )
      {
        PALLOC(frm_warning_ind,FRM_WARNING_IND);
        frm_warning_ind->warning_code = cause;
#ifdef _TARGET_
        /* We will destroy the partition guard pattern if the warning is longer than the warning string in FRM_WARNING_IND */
        vsprintf ((char*)frm_warning_ind->warning_string, format, varpars);
#else
#if defined(_LINUX_) || defined(_SOLARIS_)
        vsnprintf ((char*)frm_warning_ind->warning_string,
                     sizeof(frm_warning_ind->warning_string), format, varpars);
#else
        _vsnprintf ((char*)frm_warning_ind->warning_string, sizeof(frm_warning_ind->warning_string), format, varpars);
#endif
#endif
        vsi_o_primsend ( caller, TC_SYSTEM, 0, error_ind_dst, (unsigned int)FRM_WARNING_IND, frm_warning_ind, sizeof(T_FRM_WARNING_IND) FILE_LINE_MACRO );
      }
      else
      {
        vsi_o_ttrace ( NO_TASK, TC_SYSTEM, "FRM_WARNING_IND dropped" );
      }
    }
#if defined _NUCLEUS_ && !defined _TARGET_
    vsprintf (TraceBuffer, format, varpars);
    printf ("%s\n",TraceBuffer);
#endif
#ifdef _NUCLEUS_
    os_SystemError ( os_MyHandle(), cause, NULL );
#endif
    recursion_count--;
  }
  return VSI_OK;
}
/*lint +e718 */
/*lint +e506 */

#endif