libshmem/lib/libshmem.c

5588 lines
159 KiB
C
Raw Blame History

/*----------------------------------------------------------------------------*/
/* libshmem.c */
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* This file is part of LibShMem. */
/* */
/* LibShMem is free software: you can redistribute it and/or modify it */
/* under the terms of the GNU Lesser General Public License as published */
/* by the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* LibShMem is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU Lesser General Public License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public */
/* License along with LibShMem. If not, see */
/* <https://www.gnu.org/licenses/>. */
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* Includes */
/*----------------------------------------------------------------------------*/
#define _LIBSHMEM_C_
#include <libshmem.h>
//#ifdef _LIBVER_SUPPORT
//VER_INFO_EXPORT(libshmem,"$Revision: 2.4 $", "$Name: $",__FILE__,"$Author: agibert $")
//#endif
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* FONCTIONS PUBLIQUES */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* FONCTIONS OPTIMISEES (SM_MODE = 1) */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Ouverture d'une instance de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Instance : num<75>ro de l'instance de la librairie */
/* (I) Context : nom du nouveau contexte */
/* (I) Open_Mode : indicateur cr<63>ation/ouverture + mode d'affichage des erreurs */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Open_I( int Instance, const char *Context, SMT_Flags Open_Mode)
{
SMT_Status rc;
LGT_Status lg_status;
int ND_Debug = FALSE;
int To_Open_Instance;
NDT_Index_Type index_type = ( NDD_INDEX_STATUS_OPENED | NDD_INDEX_TYPE_TREE | NDD_INDEX_SUBTYPE_BALANCED);
/* D<>finition du mode d'affichage des messages d'erreur */
if( SMD_DEBUG_MSK( Open_Mode)) SM_stderr = stderr;
if( Open_Mode & SMD_DEBUG_ALL) ND_Debug = TRUE;
if( ( lg_status = LG_Library_Open( LGD_LOG_WRITER_DEFAULT, false)) != LGS_OK)
{
fprintf( stderr, "Can't open LibLog library: (%d)\n", lg_status);
return( -1);
}
/* D<>finition de l'instance <20> ouvrir */
if( Instance) To_Open_Instance = Instance;
else
{
if( !getenv( INSTANCE_ENV_VAR) || ( To_Open_Instance = atoi( getenv( INSTANCE_ENV_VAR))) <= 0)
{
To_Open_Instance = DEFAULT_INSTANCE;
}
}
if( Open_Mode & SMD_CREATE) /* Cr<43>ation d'une nouvelle instance */
{
/* On v<>rifie que le processus courant n'acc<63>de pas d<>j<EFBFBD> <20> une instance */
if( SM_Open_Counter > 0)
{
LG_LOG_ERROR( "SM_Library_Open : the current process has already opened an instance: (%d) of the LIBSHMEM base", SM_Instance);
return( SMS_ERRAPI);
}
/* Ouverture de la librairie LIBNODE */
rc = ND_Library_Open( ND_Debug);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "SM_Library_Open : unable to open the LIBNODE library");
return( rc);
}
/* Ouverture de la liste des heaps ouverts (locale) */
rc = ND_DataStruct_Open( &Opened_Heap_List, "SM Opened Heap", ND_OPEN_FLAG_CREATE, 1, &index_type, "SM_Opened_Heap_List_Manager", NULL, NULL, TRUE, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "SM_Library_Open : unable to create the local opened heap cache");
goto Error1;
}
/* Cr<43>ation de la base de m<>moire partag<61>e */
SM_Instance = To_Open_Instance;
rc = SM_Base_Init();
if( rc != SMS_OK )
{
LG_LOG_ERROR( "SM_Library_Open : unable to initialize the shared memory base");
goto Error2;
}
}
else if( Open_Mode & SMD_OPEN) /* Ouverture d'une instance existante */
{
/* On v<>rifie que le processus courant n'a pas d<>j<EFBFBD> ouvert une autre instance */
if( SM_Open_Counter > 0 && To_Open_Instance != SM_Instance)
{
LG_LOG_ERROR( "SM_Library_Open : the current process cannot open instance: (%d) because it is already accessing instance: (%d)", To_Open_Instance, SM_Instance);
return( SMS_ERRAPI);
}
SM_Instance = To_Open_Instance;
/* Ouverture effective si c'est la premi<6D>re fois */
if( SM_Open_Counter == 0)
{
/* Ouverture de la librairie LIBNODE */
rc = ND_Library_Open( ND_Debug);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to open the LIBNODE library");
return( rc);
}
/* Ouverture de la liste des heaps ouverts (locale) */
rc = ND_DataStruct_Open( &Opened_Heap_List, "SM Opened Heap", ND_OPEN_FLAG_CREATE, 1, &index_type, "SM_Opened_Heap_List_Manager", NULL, NULL, TRUE, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to create the local opened heap cache");
goto Error1;
}
/* Ouverture de la base de m<>moire partag<61>e */
rc = SM_Base_Open();
if( rc != SMS_OK )
{
LG_LOG_ERROR( "Unable to open the shared memory base");
goto Error2;
}
}
}
/* D<>finition du contexte */
SM_Library_Context_Set_I( Context);
/* On incr<63>mente le compteur d'ouverture de la librairie */
SM_Open_Counter++;
return( SMS_OK);
/* Gestion d'erreur */
Error2:
ND_DataStruct_Close( Opened_Heap_List);
Error1:
ND_Library_Close();
return( rc);
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>ration du num<75>ro de l'instance utilis<69>e */
/*------------------------------------------------------------------------------*/
/* (O) Instance : adresse du num<75>ro de l'instance utilis<69>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Instance_Get_I( int *Instance)
{
*Instance = SM_Instance;
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>ration du nom du contexte utilis<69> */
/*------------------------------------------------------------------------------*/
/* (O) Context : adresse du nom du contexte utilis<69> */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Context_Get_I( char **Context)
{
*Context = SM_Context;
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Changement de contexte d'utilisation de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Context : nom du nouveau contexte */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Context_Set_I( const char *Context )
{
if( SM_Context) free( SM_Context);
if( Context && strlen( Context))
{
SM_Context = strdup( Context);
}
else
{
if( getenv( CONTEXT_ENV_VAR) && strlen( getenv( CONTEXT_ENV_VAR)))
{
SM_Context = strdup( getenv( CONTEXT_ENV_VAR));
}
else
{
SM_Context = strdup( DEFAULT_CONTEXT);
}
}
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Fermeture de l'instance de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Close_Mode : mode de fermeture (destruction ou fermeture simple) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Close_I( SMT_Flags Close_Mode)
{
SMT_Status rc;
LGT_Status lg_status;
if( Close_Mode & SMD_DESTROY) /* Destruction de l'instance */
{
/* Destruction de la base de m<>moire partag<61>e */
rc = SM_Base_End();
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to destroy the shared memory base");
return( rc);
}
if( SM_Context)
{
free( SM_Context);
SM_Context = NULL;
}
/* Fermeture de la liste des heaps ouverts */
ND_DataStruct_Close( Opened_Heap_List);
/* Fermeture de la librairie LIBNODE */
ND_Library_Close();
/* R<>initialisation du compteur d'ouverture */
SM_Open_Counter = 0;
}
else if( Close_Mode & SMD_CLOSE) /* Fermeture de l'instance */
{
/*
La fermeture n'est effective que si la librairie
n'a <20>t<EFBFBD> ouverte qu'une seule fois.
*/
if( SM_Open_Counter == 1)
{
/* Fermeture de la base de m<>moire partag<61>e */
rc = SM_Base_Close();
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to close the shared memory base");
return( rc);
}
if( SM_Context)
{
free( SM_Context);
SM_Context = NULL;
}
/* Fermeture de la liste des heaps ouverts */
ND_DataStruct_Close( Opened_Heap_List);
/* Fermeture de la librairie LIBNODE */
ND_Library_Close();
}
/* On met <20> jour le compteur d'ouverture de la librairie */
SM_Open_Counter--;
}
if( ( lg_status = LG_Library_Close( false)) != LGS_OK)
{
fprintf( stderr, "Can't close LibLog library: (%d)\n", lg_status);
return( SMS_KO);
}
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Affichage des informations de la base de m<>moires partag<61>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Dump_I( FILE *Out)
{
/* Affichage des informations sur la base */
/*
fprintf( Out, "Base: (%d):[%s]\tSize: (%d)\tCreator PId: (%ld)\tLast write access PId: (%ld)\nId Mem: (%d):(%d)\tId Sem: (%d)\tStatus: [%s]\n\n",
SM_Instance, SM_Context, SM_Base->Size, SM_Base->Creator, SM_Base->Writer, SM_Base->SysMemId, SM_Base->DataMemId, SM_Base->SemId, SM_Lock_Status_Get( "base", SM_Base));
*/
LG_LOG_INFO( "Base: (%d):[%s]\tSize: (%d)\tCreator PId: (%ld)\tLast write access PId: (%ld)",
SM_Instance, SM_Context, SM_Base->Size, SM_Base->Creator, SM_Base->Writer);
LG_LOG_INFO( "Id Mem: (%d):(%d)\tId Sem: (%d)\tStatus: [%s]",
SM_Base->SysMemId, SM_Base->DataMemId, SM_Base->SemId, SM_Lock_Status_Get( "base", SM_Base));
LG_LOG_INFO( "");
/* Affichage des informations du MHR */
ND_DataStruct_Info_Print( Out, SM_Base->MHR, NDD_RECURSIVE_MODE_PARENT_CHILD, 0, 0);
// fprintf( Out, "\n");
LG_LOG_INFO( "");
/* Affichage des informations de chaque heap */
return( ND_DataStruct_Value_Print( Out, SM_Base->MHR, NDD_RECURSIVE_MODE_PARENT_CHILD, 0, 0));
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration de tous les verrous (base, heap) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Unlock_I( void)
{
NDT_Node *Node;
union semun Sem_Ctl;
/* Lib<69>ration des verrous sur la base */
Sem_Ctl.val = 1;
if( semctl( SM_Base->SemId, 0, SETVAL, Sem_Ctl))
{
LG_LOG_ERROR( "Unable to unlock the shared memory base");
return( SMS_ERRSEM);
}
/* Lib<69>ration des verrous sur les heaps */
ND_Index_Node_First_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
while( Node)
{
SMT_MHH *MHH;
MHH = (SMT_MHH *)( Node->Value);
if( semctl( MHH->SemId, 0, SETVAL, Sem_Ctl))
{
LG_LOG_ERROR( "Unable to unlock heap: [%s]", MHH->Name);
return( SMS_ERRSEM);
}
ND_Index_Node_Next_Get( &Node, Node);
}
ND_Index_Node_First_Get( &Node, Opened_Heap_List, NDD_INDEX_PRIMARY);
while( Node)
{
( (SMT_Heap *)(Node->Value))->Lock_Mode = SMD_NO_LOCK;
ND_Index_Node_Next_Get( &Node, Node);
}
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* D<>finition de la sortie standard des messages d'erreur de la librairie */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Stderr_Set_I( FILE *Out)
{
SM_stderr = Out;
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Test d'existence d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : Nom du heap */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Exist_I( const char *Heap_Name)
{
NDT_Node *Node;
SMT_MHH *MHH;
char prefixed_name[ SMD_NAME_SIZE];
int Locked = FALSE;
SM_Name_Prefix( prefixed_name, Heap_Name);
if( strcmp( Heap_Name, HEAP_SYSTEM))
{
/* Verrouillage du heap syst<73>me en lecture */
SM_Heap_Lock_I( System_Heap, SMD_READ, &Locked);
}
/* Recherche dans le MHR */
ND_Index_Node_First_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
while( Node)
{
MHH = (SMT_MHH *)( Node->Value);
if( !strcmp( prefixed_name, MHH->Name))
{
return( SMS_YES);
}
ND_Index_Node_Next_Get( &Node, Node);
}
/* D<>verrouillage <20>ventuel du heap syst<73>me */
if( Locked == TRUE)
{
SM_Heap_Unlock_I( System_Heap);
}
return( SMS_NO);
}
/*------------------------------------------------------------------------------*/
/* Ouverture/cr<63>ation d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name: nom du heap */
/* (O) Heap_Ptr_Ptr: pointeur sur le heap ouvert / cr<63><72> */
/* (I) Seg_Size: taille des segments du heap */
/* (I) Open_Mode: mode d'ouverture du heap */
/* (O) Locked: verrou effectif (TRUE ou FALSE) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Open_I( const char *Heap_Name, SMT_Heap **Heap_Ptr_Ptr, size_t Seg_Size, SMT_Flags Open_Mode, int *Locked)
{
SMT_MHH *MHH;
NDT_Node *Node_Ptr;
SMT_DSH *New_DSH;
char prefixed_name[ SMD_NAME_SIZE];
union semun Sem_Ctl;
int SemId;
SMT_Status rc;
NDT_Index_Type index_type = ( NDD_INDEX_STATUS_OPENED | NDD_INDEX_TYPE_LIST | NDD_INDEX_SUBTYPE_FIFO);
*Locked = FALSE;
/* On regarde si le heap est d<>j<EFBFBD> ouvert par le processus courant */
if( SM_Heap_IsOpen_I( Heap_Name, Heap_Ptr_Ptr) == SMS_YES)
{
if( Open_Mode & SMD_OPEN)
{
/* Verrouillage du heap dans le mode demand<6E> */
rc = SM_Heap_Lock_I( *Heap_Ptr_Ptr, SMD_LOCK_MSK( Open_Mode), Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock heap: [%s] for: [%s]", Heap_Name, Open_Mode & SMD_READ ? "reading" : "writing");
return( rc);
}
return( SMS_OK);
}
else
{
LG_LOG_ERROR( "The heap already exists but (Flags & SMD_OPEN) is false");
return( SMS_ERRAPI);
}
}
SM_Name_Prefix( prefixed_name, Heap_Name);
/* On regarde si le heap existe d<>j<EFBFBD> dans la base */
if( SM_Heap_Exist_I( Heap_Name) == SMS_YES)
{
if( Open_Mode & SMD_OPEN)
{
SMT_MHH To_Find;
/* Ouverture d'un heap existant */
strcpy( To_Find.Name, prefixed_name);
ND_Index_Node_Find( &Node_Ptr, SM_Base->MHR, NDD_INDEX_PRIMARY, &To_Find, NULL);
MHH = (SMT_MHH *)( Node_Ptr->Value);
*Heap_Ptr_Ptr = (SMT_Heap *) malloc( sizeof( SMT_Heap));
if( !*Heap_Ptr_Ptr)
{
LG_LOG_ERROR( "Unable to allocate memory for the opened heap: [%s]", prefixed_name);
return( SMS_ERRMEM);
}
( *Heap_Ptr_Ptr)->Name = strdup( prefixed_name);
( *Heap_Ptr_Ptr)->MHH = MHH;
( *Heap_Ptr_Ptr)->Lock_Mode = SMD_NO_LOCK;
/* On ouvre tous les segments du heap */
ND_Index_Node_First_Get( &Node_Ptr, ( *Heap_Ptr_Ptr)->MHH->DSR, NDD_INDEX_PRIMARY);
while( Node_Ptr)
{
rc = SM_DataSegment_Open( Node_Ptr->Value);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to open one of the data segments of heap: [%s]", prefixed_name);
goto Error1;
}
ND_Index_Node_Next_Get( &Node_Ptr, Node_Ptr);
}
( *Heap_Ptr_Ptr)->Nb_Seg = ( *Heap_Ptr_Ptr)->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
/* Verrouillage du heap dans le mode demand<6E> */
rc = SM_Heap_Lock_I( *Heap_Ptr_Ptr, SMD_LOCK_MSK( Open_Mode), Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock heap: [%s] for: [%s]", prefixed_name, Open_Mode & SMD_READ ? "reading" : "writing");
goto Error1;
}
/* Ajout au cache des heaps ouverts */
rc = ND_DataStruct_Value_Add (Opened_Heap_List, *Heap_Ptr_Ptr);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add heap: [%s] to the opened heap cache", prefixed_name);
goto Error2;
}
return( SMS_OK);
}
else
{
LG_LOG_ERROR( "The heap already exists but (Open_Mode & SMD_OPEN) is false");
return( SMS_ERRAPI);
}
}
if( !( Open_Mode & SMD_CREATE))
{
LG_LOG_ERROR( "The heap: [%s] does no exist and (Open_Mode & SMD_CREATE) is false", prefixed_name);
return( SMS_ERRAPI);
}
/*Alloc du MHH qui fait l'alloccation du premier segment de donnees*/
rc = ND_Value_Alloc( (void **)&MHH, SM_Base->MHR, prefixed_name, Seg_Size);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to alloc a new MHH structure");
return(SMS_ERRAPI);
}
/* Ajout du nouveau heap <20> la structure MHR */
rc = ND_DataStruct_Value_Add( SM_Base->MHR, MHH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add the new heap to the MHR structure");
goto Error9;
}
/* Verrouillage du nouveau MHH dans le mode demand<6E> */
rc = SM_Heap_Lock_Set( MHH, SMD_LOCK_MSK( Open_Mode));
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock heap: [%s] for: [%s]", prefixed_name, Open_Mode & SMD_READ ? "reading" : "writing");
goto Error10;
}
*Locked = TRUE;
/* Ajout du nouveau heap au cache des heaps ouverts */
*Heap_Ptr_Ptr = (SMT_Heap *)malloc( sizeof( SMT_Heap));
if( !*Heap_Ptr_Ptr)
{
LG_LOG_ERROR( "Unable to allocate memory for a new opened heap: [%s]", prefixed_name);
rc = SMS_ERRMEM;
goto Error10;
}
( *Heap_Ptr_Ptr)->Name = strdup( prefixed_name);
( *Heap_Ptr_Ptr)->MHH = MHH;
( *Heap_Ptr_Ptr)->Lock_Mode = SMD_LOCK_MSK( Open_Mode);
( *Heap_Ptr_Ptr)->Nb_Seg = 1;
rc = ND_DataStruct_Value_Add( Opened_Heap_List, *Heap_Ptr_Ptr);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add heap: [%s] to the opened heap cache", prefixed_name);
goto Error11;
}
return( SMS_OK);
/* Gestion d'erreur sur cr<63>ation */
Error11:
free( ( *Heap_Ptr_Ptr)->Name);
free( *Heap_Ptr_Ptr);
*Heap_Ptr_Ptr = NULL;
Error10:
ND_DataStruct_Value_Remove( SM_Base->MHR, MHH);
Error9:
ND_DataStruct_Value_Remove( MHH->DSR, New_DSH);
Error8:
ND_Value_Free( MHH->DSR, New_DSH);
Error7:
ND_Deallocator_Exec( MHH->FCR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
Error6:
ND_Deallocator_Exec( MHH->ACR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
Error5:
ND_Deallocator_Exec( MHH->DSR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
Error4:
ND_Deallocator_Exec( MHH, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
Error3:
semctl( SemId, 0, IPC_RMID, Sem_Ctl);
return( rc);
/* Gestion d'erreur sur ouverture */
Error2:
SM_Heap_Unlock_I( *Heap_Ptr_Ptr);
Error1:
free( ( *Heap_Ptr_Ptr)->Name);
free( *Heap_Ptr_Ptr);
*Heap_Ptr_Ptr = NULL;
return( rc);
}
/*------------------------------------------------------------------------------*/
/* Teste si un heap a d<>j<EFBFBD> <20>t<EFBFBD> ouvert par le processus courant */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name: Nom du heap */
/* (O) Heap_Ptr_Ptr: pointeur sur le heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_IsOpen_I( const char *Heap_Name, SMT_Heap **Heap_Ptr_Ptr)
{
SMT_Status rc;
char prefixed_name[ SMD_NAME_SIZE];
SMT_Heap To_Find;
NDT_Node *Node_Ptr;
*Heap_Ptr_Ptr = NULL;
To_Find.Name = prefixed_name;
SM_Name_Prefix( prefixed_name, Heap_Name);
rc = ND_Index_Node_Find( &Node_Ptr, Opened_Heap_List, NDD_INDEX_PRIMARY, &To_Find, NULL);
if( ND_ERROR(rc))
{
return( SMS_KO);
}
else
{
if( Node_Ptr == NULL)
{
*Heap_Ptr_Ptr = NULL;
return( SMS_NO);
}
else
{
*Heap_Ptr_Ptr = (SMT_Heap *)( Node_Ptr->Value);
return( SMS_YES);
}
}
}
/*------------------------------------------------------------------------------*/
/* Destruction d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_End_I( const char *Heap_Name )
{
SMT_Status rc;
SMT_Heap * Heap;
int Locked;
rc = SM_Heap_Exist_I( Heap_Name);
if( SM_ERROR(rc)) return rc;
if( rc == SMS_NO)
{
LG_LOG_ERROR( "SM_Heap_End: heap: [%s] does not exist", Heap_Name);
return SMS_KO;
}
rc = SM_Heap_IsOpen_I( Heap_Name, &Heap);
if( SM_ERROR(rc)) return rc;
if( rc == SMS_YES)
{
/* Verrouillage en <20>criture */
rc = SM_Heap_Lock_I( Heap, SMD_WRITE, &Locked);
}
else
{
/* Ouverture du heap en <20>criture */
rc = SM_Heap_Open_I( Heap_Name, &Heap, 0, SMD_OPEN | SMD_WRITE, &Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to open the heap to remove for writing");
return( rc);
}
}
/* Suppression du heap */
rc = ND_DataStruct_Value_Remove( SM_Base->MHR, Heap->MHH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to remove heap: [%s] from the MHR structure", Heap_Name);
return( rc);
}
rc = ND_Value_Free( SM_Base->MHR, Heap->MHH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "SM_Heap_End: unable to free heap: [%s]", Heap_Name);
return( rc);
}
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Fermeture d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Close_I( SMT_Heap *Heap)
{
SMT_Status rc;
NDT_Node * Node;
/*
Fermeture des segments de donn<6E>es composant le heap
en commencant par le dernier (important pour le heap syst<73>me)
*/
ND_Index_Node_Last_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
while( Node)
{
rc = SM_DataSegment_Close( Node->Value);
if( SM_ERROR(rc)) return rc;
ND_Index_Node_Previous_Get( &Node, Node);
}
/* D<>verrouillage du heap */
SM_Heap_Unlock_I( Heap);
/* Suppression du heap de la liste des heaps ouverts */
rc = ND_DataStruct_Value_Remove( Opened_Heap_List, Heap);
if( SM_ERROR(rc)) return rc;
rc = ND_Value_Free( Opened_Heap_List, Heap);
return rc;
}
/*------------------------------------------------------------------------------*/
/* Pose d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Lock_Mode : mode de verrouillage (SMD_READ ou SMD_WRITE) */
/* (O) Locked : verrouillage effectu<74> (TRUE ou FALSE) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_I( SMT_Heap *Heap, SMT_Flags Lock_Mode, int *Locked )
{
SMT_Status rc;
int Nb_Detected, Nb_Corrected;
if( Lock_Mode == Heap->Lock_Mode)
{
/* Rien <20> faire : le heap est d<>j<EFBFBD> verrouill<6C> dans ce mode */
/*
fprintf( stderr, "SM_Heap_Lock: heap [%s] already locked in mode: (%d)!\n", Heap->Name, Lock_Mode);
fflush( stderr);
*/
LG_LOG_WARNING( "Heap: [%s] already locked in mode: (%d)", Heap->Name, Lock_Mode);
// LG_STACK_TRACE( LGD_LOG_LEVEL_DEFAULT);
*Locked = FALSE;
// *Locked = TRUE;
}
else if( Heap->Lock_Mode == SMD_NO_LOCK)
{
/*
Verrouillage d'un heap qui ne l'<27>tait pas : le heap ayant pu <20>tre modifi<66>
depuis la derni<6E>re fois qu'on y a acc<63>d<EFBFBD>, il faut proc<6F>der <20> un certain
nombre de v<>rifications.
*/
/* V<>rification de l'<27>tat du heap */
if( Heap->MHH->State == SMD_STATE_CORRUPTED)
{
LG_LOG_ERROR( "Heap: [%s] is flagged as being corrupted", Heap->Name);
return( SMS_KO);
}
/* Verrouillage du heap dans le mode demand<6E> */
rc = SM_Heap_Lock_Set( Heap->MHH, Lock_Mode);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock heap [%s] for: [%s]", Heap->Name, Lock_Mode & SMD_READ ? "reading" : "writing");
return rc;
}
/* V<>rification de l'<27>tat du heap */
if( Heap->MHH->State == SMD_STATE_UNVALIDATED)
{
/* Verrouillage du heap en <20>criture pour le v<>rifier */
if( Lock_Mode == SMD_READ)
{
rc = SM_Heap_Lock_Change( Heap->MHH, SMD_WRITE);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock heap: [%s] for writing before checking", Heap->Name);
SM_Heap_Unlock_I( Heap);
return rc;
}
}
/* V<>rification du heap */
Nb_Detected = Nb_Corrected = 0;
rc = SM_Heap_Check_I( Heap, &Nb_Detected, &Nb_Corrected, SM_stderr);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to check heap: [%s]", Heap->Name);
SM_Heap_Unlock_I( Heap);
return rc;
}
/* On reverrouille <20>ventuellement le heap dans le mode demand<6E> */
if( Lock_Mode == SMD_READ)
{
rc = SM_Heap_Lock_Change( Heap->MHH, SMD_READ);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock heap: [%s] for reading", Heap->Name);
SM_Heap_Unlock_I( Heap);
return rc;
}
}
}
/* TEST !!!! */
{
NDT_Node *node_ptr = NULL;
SMT_Heap *heap_ptr;
if( SM_Heap_IsOpen_I( "system", &heap_ptr) != SMS_OK)
{
LG_LOG_ERROR( "Internal Error 1 !");
}
else
{
if( Heap->Nb_Seg != Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number)
{
ND_Index_Node_First_Get( &node_ptr, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
if( node_ptr == NULL)
{
LG_LOG_ERROR( "Internal Error 2 !");
}
else
{
while( node_ptr)
{
if( ( rc = SM_DataSegment_Open( node_ptr->Value)) != SMS_OK)
{
LG_LOG_ERROR( "Unable to open one of the data segments of heap: [%s]",
( (SMT_MHH *)(node_ptr->Value))->Name);
}
else
{
// LG_LOG_ERROR( "SM_Heap_Lock : Opening Segment (%x)", node_ptr->Value);
//
}
ND_Index_Node_Next_Get( &node_ptr, node_ptr);
}
}
}
}
}
/* On v<>rifie qu'aucun nouveau segment n'a <20>t<EFBFBD> ajout<75> depuis la derni<6E>re ouverture */
if( Heap->Nb_Seg != Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number)
{
NDT_Node * Node;
/* On ouvre tous les segments du heap */
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
while( Node)
{
rc = SM_DataSegment_Open (Node->Value);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to open one of the data segments of heap: [%s]", Heap->Name);
SM_Heap_Unlock_I( Heap);
return rc;
}
ND_Index_Node_Next_Get( &Node, Node);
}
Heap->Nb_Seg = Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
}
Heap->Lock_Mode = Lock_Mode;
*Locked = TRUE;
}
else
{
/* Verrouillage du heap qui est d<>j<EFBFBD> verrouill<6C> dans un autre mode */
rc = SM_Heap_Lock_Change( Heap->MHH, Lock_Mode);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to change lock of heap: [%s] for [%s]", Heap->Name, Lock_Mode & SMD_READ ? "reading" : "writing");
return rc;
}
Heap->Lock_Mode = Lock_Mode;
*Locked = TRUE;
}
LG_LOG_TRACE( LGD_LOG_LEVEL_DEFAULT, "Locked: heap: [%s] lock_mode: (%d)", Heap->Name, Heap->Lock_Mode);
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur unheap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Unlock_I( SMT_Heap *Heap)
{
SMT_Status rc;
rc = SM_Heap_Lock_Release( Heap->MHH, Heap->Lock_Mode);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to unlock heap: [%s] for: [%s]",
Heap->Name, Heap->Lock_Mode & SMD_READ ? "reading" : "writing");
return( rc);
}
Heap->Lock_Mode = SMD_NO_LOCK;
LG_LOG_TRACE( LGD_LOG_LEVEL_DEFAULT, "Unlocked: heap: [%s] lock_mode: (%d)", Heap->Name, Heap->Lock_Mode);
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Configuration d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Tag : type de configuration */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Config_I( SMT_Heap *Heap, SMT_Config Tag, ... )
{
va_list Arguments;
size_t Size, Current_Size;
SMT_Status rc;
va_start (Arguments, Tag);
switch( Tag)
{
case SMD_AUTO_COMPRESS:
{
Size = va_arg (Arguments, size_t);
Heap->MHH->Auto_Compress = Size;
break;
}
case SMD_SEGMENT_SIZE:
{
Size = va_arg (Arguments, size_t);
Heap->MHH->Segment_Size = Size;
break;
}
case SMD_HEAP_LIMIT:
{
Size = va_arg (Arguments, size_t);
Current_Size = 0;
if( Size != SMD_UNLIMITED)
{
/* On contr<74>le que la limite fix<69>e est inf<6E>rieure <20> la taille actuelle du heap */
rc = ND_DataStruct_Traverse( Heap->MHH->DSR, NDD_CMD_VALUE_SUM, (void *)&Current_Size);
if( rc != NDS_OK) return rc;
if( Current_Size > Size)
{
LG_LOG_ERROR( "The heap has already exceeded the limit size: (%d) bytes", Current_Size);
va_end( Arguments);
return SMS_ERRAPI;
}
}
Heap->MHH->Limit_Size = Size;
break;
}
default:
{
LG_LOG_ERROR( "Unknown config tag: (%d)", Tag);
va_end( Arguments);
return SMS_ERRAPI;
}
}
va_end( Arguments);
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Compression d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (O) Compress : pointeur sur la taille m<>moire gagn<67>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Compress_I( SMT_Heap *Heap, size_t *Compress)
{
SMT_Status rc;
NDT_Node *Node;
*Compress = 0;
/*
Pour permettre la compression, il faut que les
chunks libres soient tri<72>s par adresse.
*/
rc = ND_DataStruct_Reorg (Heap->MHH->FCR);
if( rc != NDS_OK) return( rc);
/* Compression de chaque segment de donn<6E>es du heap */
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
while( Node)
{
*Compress += SM_DataSegment_Compress( (SMT_DSH *)(Node->Value), Heap->MHH->FCR);
ND_Index_Node_Next_Get( &Node, Node);
}
Heap->MHH->Compress_Nb++;
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* V<>rification/correction des structures d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (O) Nb_Detected : pointeur sur le nombre d'erreurs d<>tect<63>es */
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrig<69>es */
/* (I) Out : pointeur sur le flux de sortie du rapport */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Check_I( SMT_Heap *Heap, int *Nb_Detected, int *Nb_Corrected, FILE *Out)
{
SMT_Status rc;
NDT_Node * Node;
LG_LOG_INFO( "Checking heap: [%s]", Heap->Name);
if( Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number == 0)
{
LG_LOG_ERROR( "Unable to check heap: [%s] which has no data segment", Heap->Name);
( *Nb_Detected) ++;
LG_LOG_INFO( "(%d) error(s) could not be corrected in heap: [%s] which will be declared as corrupted", *Nb_Detected - *Nb_Corrected, Heap->Name);
LG_LOG_INFO( "Please contact an administrator about it");
Heap->MHH->State = SMD_STATE_CORRUPTED;
return SMS_ERRAPI;
}
else
{
/* V<>rification de la structure DSR du heap */
LG_LOG_INFO( "Checking the DSR node structure");
rc = ND_DataStruct_Check (Heap->MHH->DSR, Nb_Detected, Nb_Corrected, Out);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to check the DSR structure");
LG_LOG_INFO( "(%d) error(s) could not be corrected in heap: [%s] which will be declared as corrupted", *Nb_Detected - *Nb_Corrected, Heap->Name);
LG_LOG_INFO( "Please contact an administrator about it");
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
}
LG_LOG_INFO( "Trying to open every data segment of the heap");
/* Ouverture des segments du heap au cas <20>a n'aurait pas <20>t<EFBFBD> fait */
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
while( Node)
{
rc = SM_DataSegment_Open (Node->Value);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to open one of the data segments of heap: [%s]", Heap->Name);
( *Nb_Detected) ++;
LG_LOG_INFO( "(%d) error(s) could not be corrected in heap: [%s] which will be declared as corrupted.",
*Nb_Detected - *Nb_Corrected, Heap->Name);
LG_LOG_INFO( "Please contact an administrator about it");
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
ND_Index_Node_Next_Get( &Node, Node);
}
/* V<>rification de la structure ACR du heap */
LG_LOG_INFO( "Checking the ACR node structure");
rc = ND_DataStruct_Check (Heap->MHH->ACR, Nb_Detected, Nb_Corrected, Out);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "SM_Heap_Check : unable to check the ACR node structure");
LG_LOG_INFO( "(%d) error(s) could not be corrected in heap: [%s] which will be declared as corrupted.",
*Nb_Detected - *Nb_Corrected, Heap->Name);
LG_LOG_INFO( "Please contact an administrator about it");
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
/* V<>rification de la structure FCR du heap */
LG_LOG_INFO( "Checking the FCR node structure");
rc = ND_DataStruct_Check (Heap->MHH->FCR, Nb_Detected, Nb_Corrected, Out);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to check the ACR node structure");
LG_LOG_INFO( "(%d) error(s) could not be corrected in heap: [%s] which will be declared as corrupted", *Nb_Detected - *Nb_Corrected, Heap->Name);
LG_LOG_INFO( "Please contact an administrator about it");
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
/* Conclusion de la proc<6F>dure de v<>rification */
if( *Nb_Detected > *Nb_Corrected)
{
/* On d<>clare le heap corrompu afin que plus personne n'y acc<63>de */
LG_LOG_INFO( "(%d) error(s) could not be corrected in heap: [%s] which will be declared as corrupted",
*Nb_Detected - *Nb_Corrected, Heap->Name);
LG_LOG_INFO( "Please contact an administrator about it");
Heap->MHH->State = SMD_STATE_CORRUPTED;
return SMS_KO;
}
/* On rend le heap valide */
if( *Nb_Detected == 0)
{
LG_LOG_INFO( "No error detected on heap: [%s] which will be declared as a valid heap", Heap->Name);
}
else
{
LG_LOG_WARNING( "Every (%d) error(s) have beeen corrected on heap: [%s] which will be declared as a valid heap", *Nb_Corrected, Heap->Name);
}
Heap->MHH->State = SMD_STATE_VALID;
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Allocation d'un chunk dans un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Size : taille du chunk */
/* (O) Ptr : adresse d'un pointeur sur la zone de donn<6E>es allou<6F>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Chunk_Alloc_I( SMT_Heap *Heap, size_t Alloc_Size, void **Ptr )
{
NDT_Node * Node;
SMT_Chunk * Chunk;
SMT_DSH * DSH;
int Found;
size_t Round_Size;
SMT_Status rc;
*Ptr = NULL;
/*
On invalide le heap jusqu'<27> ce que la proc<6F>dure d'allocation soit enti<74>rement termin<69>e.
Ainsi, si celle-ci est interrompue, le heap restera invalide jusqu'<27> ce qu'il soit
"r<>par<61>" (appel de la fonction SM_Heap_Check par la fonction SM_Heap_Open).
*/
Heap->MHH->State = SMD_STATE_UNVALIDATED;
/*
Pour le heap syst<73>me, tous les chunks allou<6F>s ont la m<>me taille (DEFAULT_CHUNK_SIZE).
Ceci facilite notamment la r<>cup<75>ration des errors (Recovery) dans le heap syst<73>me.
Ceci a aussi pour but de simplifier (et donc d'optimiser) l'allocation de nouveaux chunks
dans ce heap syst<73>me dont la m<>moire n'a pas besoin d'<27>tre optimis<69>e.
*/
if( Heap == System_Heap) Alloc_Size = DEFAULT_CHUNK_SIZE;
/*
Attention : pour les autres heaps, la taille allou<6F>e doit <20>tre arrondie <20> un multiple
de 4 octets (en 32 bits) afin que les adresses des chunks soient align<67>es (sinon SIGBUS !).
*/
Round_Size = Alloc_Size % sizeof (void *);
if( Round_Size) Alloc_Size += sizeof (void *) - Round_Size;
/* Recherche d'un chunk suffisamment grand dans la liste des chunks libres */
Found = FALSE;
ND_Index_Node_First_Get( &Node, Heap->MHH->FCR, NDD_INDEX_PRIMARY);
while( Found == FALSE && Node)
{
Chunk = (SMT_Chunk *)(Node->Value);
if( Chunk->Size >= Alloc_Size) Found = TRUE;
else ND_Index_Node_Next_Get( &Node, Node);
}
if( Found == FALSE)
{
/*
Si aucun chunk libre suffisamment grand n'a <20>t<EFBFBD> trouv<75>,
alors on cr<63>e un nouveau segment de donn<6E>es.
*/
size_t Seg_Size;
if( Alloc_Size + sizeof (NDT_Node) + sizeof (SMT_Chunk) > Heap->MHH->Segment_Size)
Seg_Size = Alloc_Size + sizeof (NDT_Node) + sizeof (SMT_Chunk);
else
Seg_Size = Heap->MHH->Segment_Size;
rc = ND_Value_Alloc( (void**)&DSH, Heap->MHH->DSR, Heap->MHH, Seg_Size);
if( rc != NDS_OK )
{
LG_LOG_ERROR( "Unable to create a new data segment for heap: [%s]", Heap->Name);
return SMS_ERRSHM;
}
rc = ND_DataStruct_Value_Add (Heap->MHH->DSR, DSH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add a data segment to the DSR structure of heap: [%s]", Heap->Name);
ND_Value_Free(Heap->MHH->DSR, DSH);
return rc;
}
/*
Maintenant que l'on a ajout<75> un segment de donn<6E>es, il existe
un chunk libre suffisamment grand au d<>but de ce segment.
*/
Node = (NDT_Node *)DSH->Start;
Chunk = (SMT_Chunk *)(Node->Value);
}
/* Suppression du chunk de la liste des chunks libres */
rc = ND_Index_Node_Remove( Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to remove a chunk from the FCR structure of heap: [%s]", Heap->Name);
return rc;
}
/* Ajout du chunk <20> la liste des chunks allou<6F>s */
rc = ND_Index_Node_Add( Heap->MHH->ACR, NDD_INDEX_PRIMARY, Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add a chunk to the ACR structure of heap: [%s]", Heap->Name);
/* On tente de revenir en arri<72>re */
ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, Node);
return rc;
}
/*
Si le chunk trouv<75> est plus grand que ce dont on a besoin, alors
on peut cr<63>er un nouveau chunk libre avec le reliquat de m<>moire.
*/
if( Chunk->Size - Alloc_Size > 0)
{
size_t Remaining_Size = Chunk->Size - Alloc_Size;
/*
La cr<63>ation d'un nouveau chunk libre requiert de la place pour les
donn<6E>es syst<73>me (SMT_Chunk + NDT_Node) : on ne cr<63>e donc un nouveau
chunk libre que si le reliquat est suffisamment important.
*/
if( Remaining_Size > sizeof (SMT_Chunk) + sizeof (NDT_Node))
{
NDT_Node * New_Node;
SMT_Chunk * New_Chunk;
size_t New_Chunk_Size;
/* Cr<43>ation d'un nouveau chunk libre (noeud puis valeur) juste derri<72>re le chunk trouv<75> */
New_Node = (NDT_Node *)( (size_t)(Chunk->Data) + Alloc_Size);
New_Chunk = (SMT_Chunk *)( (size_t)New_Node + sizeof (NDT_Node) );
New_Chunk_Size = Remaining_Size - sizeof (SMT_Chunk) - sizeof (NDT_Node);
New_Chunk->Size = New_Chunk_Size;
New_Chunk->Data = (void *)( (size_t)(New_Chunk) + sizeof (SMT_Chunk) );
New_Node->Root = NULL;
New_Node->Parent = NULL;
New_Node->Left = NULL;
New_Node->Right = NULL;
New_Node->Value = New_Chunk;
rc = ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, New_Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add a chunk to the FCR structure of heap: [%s]", Heap->Name);
return rc;
}
/* Ajustement du chunk allou<6F> */
Chunk->Size = Alloc_Size;
}
}
/*
Pour une allocation dans le heap syst<73>me, on anticipe l'ajout
d'un nouveau segment pour <20>viter de se retrouver bloqu<71>.
Bien entendu, cette op<6F>ration n'est faite que si l'on n'est
pas d<>j<EFBFBD> en train d'<27>tendre le heap syst<73>me (Adding_Segment=TRUE).
*/
if( Heap == System_Heap && Adding_Segment == FALSE)
{
SMT_Chunk * Free_Chunk;
unsigned int Free_Usable_Chunk = 0;
size_t Free_Usable_Size = 0;
int New_Seg_Needed = FALSE;
/* On compte le nombre de chunks libres "utilisables" dans la structure FCR */
ND_Index_Node_First_Get( &Node, Heap->MHH->FCR, NDD_INDEX_PRIMARY);
while( Node)
{
Free_Chunk = Node->Value;
if( Free_Chunk->Size >= DEFAULT_CHUNK_SIZE)
{
Free_Usable_Chunk++;
Free_Usable_Size += Free_Chunk->Size;
}
ND_Index_Node_Next_Get( &Node, Node);
}
/*
S'il reste au moins FREE_CHUNK_LIMIT chunks libres "utilisables"
ou bien si ces chunks libres "utilisables" repr<70>sentent suffisament de
place pour allouer FREE_CHUNK_LIMIT nouveaux chunks, alors tout est OK.
Dans le cas contraire, il est urgent d'<27>tendre le heap syst<73>me.
*/
if( Free_Usable_Chunk < FREE_CHUNK_LIMIT)
{
size_t Needed_Size;
Needed_Size = (size_t)(FREE_CHUNK_LIMIT * DEFAULT_CHUNK_SIZE) + (size_t)(FREE_CHUNK_LIMIT - Free_Usable_Chunk) * (sizeof (NDT_Node) + sizeof (SMT_Chunk));
if( Free_Usable_Size < Needed_Size) New_Seg_Needed = TRUE;
}
if( New_Seg_Needed == TRUE)
{
NDT_Node * New_Node;
/*
Puisque l'ajout d'un nouveau segment va appeler cette m<>me fonction,
on positionne une variable globale pour ne pas recommencer cette op<6F>ration.
*/
Adding_Segment = TRUE;
/*
On alloue le noeud du nouveau segment avant de faire appel <20> la fonction
ND_Value_Alloc pour <20>viter que ce noeud soit allou<6F> dans le nouveau segment.
*/
SM_System_Alloc( (void **)(&New_Node), NULL, sizeof (NDT_Node), NULL);
New_Node->Root = NULL;
New_Node->Parent = NULL;
New_Node->Left = NULL;
New_Node->Right = NULL;
/* On cr<63>e le nouveau segment */
rc = ND_Value_Alloc( (void**)&DSH, Heap->MHH->DSR, Heap->MHH, Heap->MHH->Segment_Size);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to create un new data segment for the system heap (anticipation)");
return SMS_ERRSHM;
}
New_Node->Value = DSH;
/* On ajoute le nouveau segment au heap syst<73>me */
rc = ND_Index_Node_Add( Heap->MHH->DSR, NDD_INDEX_PRIMARY, New_Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add a data segment to the DSR structure of the system heap (anticipation)");
ND_Value_Free( Heap->MHH->DSR, DSH);
return rc;
}
Adding_Segment = FALSE;
}
}
/*
Puisque la proc<6F>dure d'allocation d'un chunk s'est correctement
termin<69>e, on peut rendre le heap <20> nouveau valide.
*/
Heap->MHH->State = SMD_STATE_VALID;
*Ptr = Chunk->Data;
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* D<>sallocation d'un chunk */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Ptr : pointeur sur la zone de donn<6E>es du chunk <20> d<>sallouer */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Chunk_Free_I( SMT_Heap *Heap, void *Ptr)
{
NDT_Node * Node;
SMT_Chunk * Chunk;
SMT_Status rc;
/*
On invalide le heap jusqu'<27> ce que la proc<6F>dure de d<>sallocation soit enti<74>rement termin<69>e.
Ainsi, si celle-ci est interrompue, le heap restera invalide jusqu'<27> ce qu'il soit
"r<>par<61>" (appel de la fonction SM_Heap_Check par la fonction SM_Heap_Open).
*/
Heap->MHH->State = SMD_STATE_UNVALIDATED;
/*
Le noeud du chunk <20>tant adjoint <20> celui-ci, on n'a pas besoin
de le rechercher dans la liste des chunks allou<6F>s.
*/
Node = (NDT_Node *)( (size_t)Ptr - sizeof (SMT_Chunk) - sizeof (NDT_Node));
Chunk = Node->Value;
/* Suppression du chunk de la liste des chunks allou<6F>s */
rc = ND_Index_Node_Remove( Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to remove the allocated chunk from the ACR structure of heap: [%s]", Heap->Name);
return rc;
}
/* Ajout du chunk <20> la liste des chunks libres */
rc = ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add the free chunk to the FCR structure of heap: [%s]", Heap->Name);
/* Retour arri<72>re */
ND_Index_Node_Add( Heap->MHH->ACR, NDD_INDEX_PRIMARY, Node);
return rc;
}
/*
Puisque la proc<6F>dure de d<>sallocation d'un chunk s'est correctement
termin<69>, on peut rendre le heap <20> nouveau valide.
*/
Heap->MHH->State = SMD_STATE_VALID;
/* Activation de la compression automatique */
if( Heap->MHH->Auto_Compress != SMD_NO_AUTO_COMPRESS &&
Heap->MHH->FCR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number > Heap->MHH->Auto_Compress)
{
size_t Compress_Size;
rc = SM_Heap_Compress (Heap, &Compress_Size);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to compress FCR structure of heap: [%s] which contains: (%ld) free chunks", Heap->Name, Heap->MHH->FCR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number);
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* FONCTIONS SECURISEES (SM_MODE = 0) */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Ouverture d'une instance de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Instance : instance de la librairie */
/* (I) Context : nom du nouveau contexte */
/* (I) Open_Mode : indicateur cr<63>ation/ouverture + mode d'affichage des erreurs */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Open_C( int Instance, const char *Context, SMT_Flags Open_Mode)
{
return SM_Library_Open_I( Instance, Context, Open_Mode);
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>ration du num<75>ro de l'instance utilis<69>e */
/*------------------------------------------------------------------------------*/
/* (O) Instance : adresse du num<75>ro de l'instance utilis<69>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Instance_Get_C( int *Instance)
{
return SM_Library_Instance_Get_I( Instance);
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>ration du nom du contexte utilis<69> */
/*------------------------------------------------------------------------------*/
/* (O) Context : adresse du nom du contexte utilis<69> */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Context_Get_C( char **Context)
{
return SM_Library_Context_Get_I( Context);
}
/*------------------------------------------------------------------------------*/
/* Changement de contexte d'utilisation de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Context : nom du nouveau contexte */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Context_Set_C( const char *Context)
{
return SM_Library_Context_Set_I( Context);
}
/*------------------------------------------------------------------------------*/
/* Fermeture de l'instance de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Close_Mode : mode de fermeture (destruction ou fermeture simple) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Close_C( SMT_Flags Close_Mode)
{
SM_LIBSHMEM_OPEN_CHECK();
return SM_Library_Close_I( Close_Mode);
}
/*------------------------------------------------------------------------------*/
/* Affichage des informations de la base de m<>moires partag<61>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Dump_C( FILE *Out)
{
SM_LIBSHMEM_OPEN_CHECK();
return SM_Library_Dump_I( Out);
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration de tous les verrous (base, heap) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Unlock_C( void)
{
SM_LIBSHMEM_OPEN_CHECK();
return SM_Library_Unlock_I( );
}
/*------------------------------------------------------------------------------*/
/* D<>finition de la sortie standard des messages d'erreur de la librairie */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Stderr_Set_C( FILE *Out)
{
return SM_Library_Stderr_Set_I( Out);
}
/*------------------------------------------------------------------------------*/
/* Test d'existence d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : Nom du heap */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Exist_C( const char *Heap_Name)
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_NAME_CHECK( Heap_Name);
return SM_Heap_Exist_I( Heap_Name);
}
/*------------------------------------------------------------------------------*/
/* Ouverture/cr<63>ation d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : nom du heap */
/* (O) Heap : pointeur sur le heap ouvert / cr<63><72> */
/* (I) Seg_Size : taille des segments du heap */
/* (I) Open_Mode : mode d'ouverture du heap */
/* (O) Locked : verrou effectif (TRUE ou FALSE) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Open_C( const char * Heap_Name, SMT_Heap **Heap_Ptr_Ptr, size_t Seg_Size, SMT_Flags Open_Mode, int *Locked)
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_NAME_CHECK( Heap_Name);
return SM_Heap_Open_I( Heap_Name, Heap_Ptr_Ptr, Seg_Size, Open_Mode, Locked);
}
/*------------------------------------------------------------------------------*/
/* Teste si un heap a d<>j<EFBFBD> <20>t<EFBFBD> ouvert par le processus courant */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : Nom du heap */
/* (O) Heap : pointeur sur le heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_IsOpen_C( const char * Heap_Name, SMT_Heap ** Heap )
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_NAME_CHECK( Heap_Name);
return SM_Heap_IsOpen_I( Heap_Name, Heap);
}
/*------------------------------------------------------------------------------*/
/* Destruction d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_End_C( const char * Heap_Name )
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_NAME_CHECK( Heap_Name);
return SM_Heap_End_I( Heap_Name);
}
/*------------------------------------------------------------------------------*/
/* Fermeture d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Close_C( SMT_Heap *Heap_Ptr)
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_CHECK( Heap_Ptr);
return SM_Heap_Close_I( Heap_Ptr);
}
/*------------------------------------------------------------------------------*/
/* Pose d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Lock_Mode : mode de verrouillage (SMD_READ ou SMD_WRITE) */
/* (O) Locked : verrouillage effectu<74> (TRUE ou FALSE) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_C( SMT_Heap *Heap_Ptr, SMT_Flags Lock_Mode, int * Locked )
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_CHECK( Heap_Ptr);
return SM_Heap_Lock_I( Heap_Ptr, Lock_Mode, Locked);
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur unheap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Unlock_C( SMT_Heap *Heap_Ptr)
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_CHECK( Heap_Ptr);
return SM_Heap_Unlock_I( Heap_Ptr);
}
/*------------------------------------------------------------------------------*/
/* Configuration d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Tag : type de configuration */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Config_C( SMT_Heap *Heap_Ptr, SMT_Config Tag, ... )
{
va_list Arguments;
size_t Segment_Size, Limit_Size, Current_Size;
SMT_Status rc;
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_CHECK( Heap_Ptr);
va_start (Arguments, Tag);
switch( Tag)
{
case SMD_SEGMENT_SIZE:
{
Segment_Size = va_arg (Arguments, size_t);
Heap_Ptr->MHH->Segment_Size = Segment_Size;
break;
}
case SMD_HEAP_LIMIT:
{
Limit_Size = va_arg (Arguments, size_t);
Current_Size = 0;
if( Limit_Size != SMD_UNLIMITED)
{
/* On contr<74>le que la limite fix<69>e est inf<6E>rieure <20> la taille actuelle du heap */
rc = ND_DataStruct_Traverse( Heap_Ptr->MHH->DSR, NDD_CMD_VALUE_SUM, (void *)&Current_Size);
if( rc != NDS_OK) return rc;
if( Current_Size > Limit_Size)
{
LG_LOG_ERROR( "The heap has already exceeded the limit size: (%d) bytes", Current_Size);
va_end( Arguments);
return SMS_ERRAPI;
}
}
Heap_Ptr->MHH->Limit_Size = Limit_Size;
break;
}
default:
{
LG_LOG_ERROR( "Unknown config tag: (%d)", Tag);
va_end( Arguments);
return SMS_ERRAPI;
}
}
va_end( Arguments);
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Compression d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (O) Compress : pointeur sur la taille m<>moire gagn<67>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Compress_C( SMT_Heap *Heap_Ptr, size_t *Compress)
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_CHECK( Heap_Ptr);
if( !Compress)
{
LG_LOG_ERROR( "The compress size pointer is null");
return SMS_ERRAPI;
}
return SM_Heap_Compress_I( Heap_Ptr, Compress);
}
/*------------------------------------------------------------------------------*/
/* V<>rification/correction des structures d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (O) Nb_Detected : pointeur sur le nombre d'erreurs d<>tect<63>es */
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrig<69>es */
/* (I) Out : pointeur sur le flux de sortie du rapport */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Check_C( SMT_Heap *Heap_Ptr, int *Nb_Detected, int *Nb_Corrected, FILE *Out)
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_CHECK( Heap_Ptr);
if( !Nb_Detected || !Nb_Corrected)
{
LG_LOG_ERROR( "The error number pointer is null");
return SMS_ERRAPI;
}
if( !Out)
{
LG_LOG_ERROR( "The out stream is null");
return SMS_ERRAPI;
}
return SM_Heap_Check_I( Heap_Ptr, Nb_Detected, Nb_Corrected, Out);
}
/*------------------------------------------------------------------------------*/
/* Allocation d'un chunk dans un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Size : taille du chunk */
/* (O) Ptr : adresse d'un pointeur sur la zone de donn<6E>es allou<6F>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Chunk_Alloc_C( SMT_Heap *Heap_Ptr, size_t Alloc_Size, void **Ptr)
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_CHECK( Heap_Ptr);
if( !Ptr)
{
LG_LOG_ERROR( "The chunk address is null");
return SMS_ERRAPI;
}
return SM_Chunk_Alloc_I( Heap_Ptr, Alloc_Size, Ptr);
}
/*------------------------------------------------------------------------------*/
/* D<>sallocation d'un chunk */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Ptr : pointeur sur la zone de donn<6E>es du chunk <20> d<>sallouer */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Chunk_Free_C( SMT_Heap *Heap_Ptr, void *Ptr)
{
SM_LIBSHMEM_OPEN_CHECK();
SM_HEAP_CHECK( Heap_Ptr);
if( !Ptr)
{
LG_LOG_ERROR( "The chunk pointer is null");
return SMS_ERRAPI;
}
return SM_Chunk_Free_I( Heap_Ptr, Ptr);
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* FONCTIONS PRIVEES */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Allocation de m<>moire dans la base */
/*------------------------------------------------------------------------------*/
NDT_Status SM_Base_Alloc( void **Ptr, NDT_Root *ND_Root_Ptr, size_t Size, void *Data_Ptr)
{
*Ptr = SM_Base->Free;
SM_Base->Free = (void *)( (size_t)(SM_Base->Free) + Size);
return( NDS_OK);
}
/*------------------------------------------------------------------------------*/
/* D<>sallocation de m<>moire dans la base */
/*------------------------------------------------------------------------------*/
NDT_Status SM_Base_Free( void *Ptr, NDT_Root *ND_Root_Ptr, void *Data_Ptr)
{
if( !Ptr) return( SMS_ERRAPI);
return( NDS_OK);
}
/*------------------------------------------------------------------------------*/
/* Allocation de m<>moire dans le heap syst<73>me */
/*------------------------------------------------------------------------------*/
NDT_Status SM_System_Alloc( void **Ptr, NDT_Root *ND_Root_Ptr, size_t Size, void *Data_Ptr)
{
return( SM_Chunk_Alloc_I( System_Heap, Size, Ptr));
}
/*------------------------------------------------------------------------------*/
/* D<>sallocation de m<>moire dans le heap syst<73>me */
/*------------------------------------------------------------------------------*/
NDT_Status SM_System_Free( void *Ptr, NDT_Root *ND_Root_Ptr, void *Data_Ptr)
{
return( SM_Chunk_Free_I( System_Heap, Ptr));
}
/*------------------------------------------------------------------------------*/
/* Initialisation de la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Init ( void )
{
SMT_Status rc;
int SemId;
int SysMemId;
int DataMemId;
union semun Sem_Ctl;
size_t Size;
int Locked;
NDT_Index_Type index_type = ( NDD_INDEX_STATUS_OPENED | NDD_INDEX_TYPE_LIST | NDD_INDEX_SUBTYPE_FIFO);
/* Cr<43>ation du s<>maphore pour la gestion des verrous sur la base */
SemId = semget (IPC_PRIVATE, 1, 0777|IPC_CREAT|IPC_EXCL);
if( SemId == -1)
{
switch( errno)
{
case ENOMEM:
{
LG_LOG_ERROR( "The amount of memory is not sufficient to create a new semaphore");
break;
}
case ENOSPC:
{
break;
}
default:
{
LG_LOG_ERROR( "Unknown error: (%d) while creating a semaphore", errno);
break;
}
}
return SMS_ERRSEM;
}
/* Initialisation du s<>maphore <20> 1 (aucun verrou) */
Sem_Ctl.val = 1;
if( semctl( SemId, 0, SETVAL, Sem_Ctl ))
{
LG_LOG_ERROR( "Unable to initialize the value of semaphore: (%d)", SemId);
rc = SMS_ERRSEM;
goto Error1;
}
/*
Cr<43>ation d'un segment de m<>moire partag<61>e qui contiendra la structure SMT_Base.
Ce segment peut <20>tre attach<63> <20> n'importe quelle adresse.
*/
SysMemId = shmget( SM_Instance, (int) sizeof( SMT_Base), ( 0777 | IPC_CREAT | IPC_EXCL));
if( SysMemId == -1)
{
switch( errno)
{
case EEXIST:
{
LG_LOG_ERROR( "The shared memory segment identifier: (%d) already exists", SM_Instance);
break;
}
case EINVAL:
{
LG_LOG_ERROR( "The size of the shared memory segment: (%d) is out of the system-imposed bounds", sizeof( SMT_Base));
break;
}
case ENOMEM:
{
LG_LOG_ERROR( "The amount of memory is not sufficient to create the shared memory segment");
break;
}
case ENOSPC:
{
LG_LOG_ERROR( "The number of shared memory segments exceeds the system-imposed limit");
break;
}
default:
{
LG_LOG_ERROR( "Unknown error: (%d) while creating the shared memory segment", errno);
break;
}
}
rc = SMS_ERRSHM;
goto Error1;
}
/* On attache le segment de m<>moire partag<61>e au processus courant */
errno = 0;
SM_Base = shmat( SysMemId, 0, 0);
if( errno)
{
LG_LOG_ERROR( "Unable to attach the first shared memory segment to the current process, error: (%d)", errno);
rc = SMS_ERRSHM;
goto Error2;
}
/*
Attention : tant que le heap syst<73>me n'est pas cr<63><72>, on est oblig<69> d'allouer de
la m<>moire dans le segment de m<>moire partag<61>e de la base (fonction SM_Base_Alloc).
Les ressources <20> allouer (structure MHR + ressources du heap syst<73>me) sont r<>f<EFBFBD>renc<6E>es
par des pointeurs et doivent par cons<6E>quent <20>tre contenues dans un segment attach<63> <20>
une adresse commune <20> tous les processus.
On cr<63>e donc ce segment de m<>moire partag<61> sp<73>cifique dont l'adresse d'attachement
sera m<>moris<69>e dans la structure SMT_Base.
Pour ce segment de m<>moire partag<61>, on r<>serve de la place pour :
- la structure du MHR (NDT_Root)
- les ressources du heap syst<73>me, i.e :
- son noeud (NDT_Node)
- sa structure d'ent<6E>te ( SMT_MHH)
- sa structure DSR (NDT_Root)
- sa structure ACR (NDT_Root)
- sa structure FCR (NDT_Root)
- son premier segment de donn<6E>es (noeud + ent<6E>te)
*/
Size = sizeof (NDT_Root) + sizeof (NDT_Node) + sizeof (SMT_MHH) + 3 * sizeof (NDT_Root) + sizeof (NDT_Node) + sizeof (SMT_DSH);
DataMemId = shmget( IPC_PRIVATE, Size, ( 0777 | IPC_CREAT | IPC_EXCL));
if( DataMemId == -1)
{
switch( errno)
{
case EINVAL:
LG_LOG_ERROR( "The size of the shared memory segment: (%d) is out of the system-imposed bounds", Size);
break;
case ENOMEM:
LG_LOG_ERROR( "The amount of memory is not sufficient to create the shared memory segment");
break;
case ENOSPC:
LG_LOG_ERROR( "The number of shared memory segments exceeds the system-imposed limit");
break;
default :
LG_LOG_ERROR( "Unknown error: (%d) while creating a shared memory segment", errno);
break;
}
rc = SMS_ERRSHM;
goto Error3;
}
/* Initialisation des informations rattach<63>es <20> la base */
SM_Base->SemId = SemId;
SM_Base->SysMemId = SysMemId;
SM_Base->DataMemId = DataMemId;
SM_Base->Size = Size;
SM_Base->Creator = getpid ();
SM_Base->Writer = SM_Base->Creator;
SM_Base->Attach = (void *)MEM_LIMIT;
SM_Base->MHR = NULL;
/*
On attache le segment de m<>moire partag<61>e au processus courant
<20> une adresse la plus haute possible (MEM_LIMIT) afin d'<27>viter
de d<>border sur la plage d'adressage des symboles.
*/
errno = 0;
#ifndef __hpux
SM_Base->Free = shmat( DataMemId, (void *)( (size_t)(SM_Base->Attach) - Size), SHM_RND);
#else
SM_Base->Free = shmat( DataMemId, 0, 0);
#endif
if( errno)
{
LG_LOG_ERROR( "Unable to attach the second shared memory segment to the current process: (%d)", errno);
rc = SMS_ERRSHM;
goto Error4;
}
SM_Base->Attach = SM_Base->Free;
/* Cr<43>ation du MHR dans la base */
// rc = ND_DataStruct_Open( &( SM_Base->MHR), 1, &index_type, "MHR_Manager", NULL, "SM_Base_Alloc", NULL, "SM_Base_Free", NULL, TRUE, NULL);
if( ( rc = ND_DataStruct_Open( &( SM_Base->MHR), "SHM-MHR", ND_OPEN_FLAG_CREATE, 1, &index_type, "MHR_Manager", NULL, SMG_DataStruct_Handlers, TRUE, NULL)) != NDS_OK)
{
LG_LOG_ERROR( "Unable to create the MHR structure");
goto Error4;
}
/*
Cr<43>ation d'un premier heap qui constituera le heap syst<73>me
(l'allocation du MHN, du MHH et des structures DSR, ACR et FCR
sont effectu<74>es dans la base)
*/
rc = SM_Heap_Open_I( HEAP_SYSTEM, &System_Heap, 0, SMD_CREATE, &Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to create the system heap");
goto Error5;
}
/*
On change les fonctions d'allocation et de d<>sallocation du MHR afin que d<>sormais,
les allocations des nouveaux heaps soient faites dans le heap syst<73>me.
*/
strcpy( SM_Base->MHR->Allocator_Name, "SM_System_Alloc");
strcpy( SM_Base->MHR->Deallocator_Name, "SM_System_Free");
/*
On change les fonctions Allocator et Deallocator du DSR, ACR
et FCR du heap syst<73>me afin que d<>sormais, les allocations des
nouveaux segments et chunks soient faites dans le segment de
donn<6E>es du heap syst<73>me.
*/
strcpy( System_Heap->MHH->DSR->Allocator_Name, "SM_System_Alloc");
strcpy( System_Heap->MHH->DSR->Deallocator_Name, "SM_System_Free");
strcpy( System_Heap->MHH->ACR->Allocator_Name, "SM_System_Alloc");
strcpy( System_Heap->MHH->ACR->Deallocator_Name, "SM_System_Free");
strcpy( System_Heap->MHH->FCR->Allocator_Name, "SM_System_Alloc");
strcpy( System_Heap->MHH->FCR->Deallocator_Name, "SM_System_Free");
/* Verrouillage de la base en lecture */
rc = SM_Base_Lock( SMD_READ);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock the shared memory base for reading");
goto Error5;
}
return SMS_OK;
/* Gestion d'erreur */
Error5:
ND_DataStruct_Close( SM_Base->MHR);
Error4:
shmdt ( (void *)(SM_Base->Free));
Error3:
shmctl (DataMemId, IPC_RMID, 0);
Error2:
shmdt ( (void *)SM_Base);
shmctl (SysMemId, IPC_RMID, 0);
SM_Base = NULL;
Error1:
semctl( SemId, 0, IPC_RMID, Sem_Ctl);
return rc;
}
/*------------------------------------------------------------------------------*/
/* Destruction de la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_End ( void )
{
int SemId;
int SysMemId, DataMemId;
SMT_Status rc;
union semun Sem_Ctl;
NDT_Node * Node, * Previous_Node;
/* Retrait du verrou en lecture sur la base */
rc = SM_Base_Unlock( SMD_READ);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to unlock the shared memory base");
return rc;
}
/* Verrouillage de la base en <20>criture */
rc = SM_Base_Lock( SMD_WRITE);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock the shared memory base for writing");
SM_Base_Lock( SMD_READ);
return rc;
}
/*
Destruction de tous les heaps (parcours du MHR en
sens inverse pour d<>truire le heap syst<73>me en dernier).
NB : <20> chaque destruction de heap, la base est verrouill<6C>e en <20>criture
*/
ND_Index_Node_Last_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
while( Node)
{
SMT_MHH * MHH = (SMT_MHH *)(Node->Value);
ND_Index_Node_Previous_Get( &Previous_Node, Node);
/*
Pour la suppression du heap syst<73>me, il faut red<65>finir la fonction de
d<>sallocation du MHR, car il a <20>t<EFBFBD> allou<6F> dans la base (voir SM_Base_Init)
*/
if( !Previous_Node)
{
strcpy( SM_Base->MHR->Deallocator_Name, "SM_Base_Free");
}
/* Retrait du heap de la structure du MHR */
rc = ND_DataStruct_Value_Remove( SM_Base->MHR, MHH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to remove heap: [%s] from the MHR", MHH->Name);
SM_Base_Unlock( SMD_WRITE);
SM_Base_Lock( SMD_READ);
return rc;
}
/* Suppression du heap */
rc = ND_Value_Free( SM_Base->MHR, MHH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to free heap: [%s]", MHH->Name);
SM_Base_Unlock( SMD_WRITE);
SM_Base_Lock( SMD_READ);
return rc;
}
Node = Previous_Node;
}
SemId = SM_Base->SemId;
SysMemId = SM_Base->SysMemId;
DataMemId = SM_Base->DataMemId;
/* Destruction des segments de m<>moire partag<61>e de la base */
if( shmctl( DataMemId, IPC_RMID, 0) == -1 || shmctl( SysMemId, IPC_RMID, 0) == -1)
{
switch( errno)
{
case EPERM:
{
LG_LOG_ERROR( "Current process: (%d) is not allowed to destroy the shared memory segment: (%d) or (%d)", (int)getpid(), SysMemId, DataMemId);
break;
}
case EINVAL:
{
LG_LOG_ERROR( "No shared memory segment exists for identifier: (%d) or (%d)", SysMemId, DataMemId);
break;
}
default :
{
LG_LOG_ERROR( "Unknown error: (%d) while destroying the shared memory segment: (%d) or (%d)", errno, SysMemId, DataMemId);
break;
}
}
SM_Base = NULL;
return SMS_ERRSHM;
}
SM_Base = NULL;
/* Destruction du s<>maphore de gestion des verrous sur la base */
if( semctl( SemId, 0, IPC_RMID, Sem_Ctl) == -1)
{
switch( errno)
{
case EPERM:
{
LG_LOG_ERROR( "Current process: (%d) is not allowed to destroy semaphore: (%d)", (int)getpid (), SemId);
break;
}
case EINVAL:
{
LG_LOG_ERROR( "No semaphore corresponds to the identifier: (%d)", SemId);
break;
}
default:
{
LG_LOG_ERROR( "Unknown error: (%d) while destroying semaphore: (%d)", errno, SemId);
break;
}
}
return SMS_ERRSEM;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Ouverture de la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Open ( void )
{
SMT_Status rc;
void * Ptr;
int MemId;
int Locked;
if( SM_Base) return SMS_OK;
/* R<>cup<75>ration de l'identifiant du segment de m<>moire partag<61>e de la base */
MemId = shmget( SM_Instance, 0, 0);
if( MemId == -1)
{
switch( errno)
{
case EACCES:
{
LG_LOG_ERROR( "The shared memory segment: (%d) is not accessible to the current process", SM_Instance);
break;
}
case EIDRM:
{
LG_LOG_ERROR( "The shared memory segment: (%d) has been deleted", SM_Instance);
break;
}
case ENOENT:
{
LG_LOG_ERROR( "No shared memory segment corresponds to the identifier: (%d)", SM_Instance);
break;
}
default:
{
LG_LOG_ERROR( "Unknown error: (%d) while retrieving a shared memory segment", errno);
break;
}
}
return SMS_ERRSHM;
}
/* On attache les segments de m<>moire partag<61>e de la base */
errno = 0;
SM_Base = shmat( MemId, 0, 0);
if( errno)
{
LG_LOG_ERROR( "Unable to attach the shared memory segment to the current process, error: (%d)", errno);
SM_Base = NULL;
return SMS_ERRSHM;
}
errno = 0;
Ptr = shmat (SM_Base->DataMemId, SM_Base->MHR, 0);
if( errno)
{
LG_LOG_ERROR( "Unable to attach the shared memory segment to the current process at the specified address: (%p) error: (%d)", SM_Base->MHR, errno);
shmdt( (void *)SM_Base);
SM_Base = NULL;
return SMS_ERRSHM;
}
/* Verrouillage de la base en lecture */
rc = SM_Base_Lock( SMD_READ);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock the shared memory base for reading");
shmdt( (void *)SM_Base);
SM_Base = NULL;
return rc;
}
/* Ouverture du heap syst<73>me (sans le verrouiller) */
rc = SM_Heap_Open_I( HEAP_SYSTEM, &System_Heap, 0, SMD_OPEN, &Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to open the system heap");
shmdt ( (void *)SM_Base);
SM_Base = NULL;
return rc;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Fermeture de la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Close( void )
{
NDT_Node * Node;
SM_LIBSHMEM_OPEN_CHECK();
/*
Fermeture de tous les heaps (sans d<>verrouillage) ouverts.
Attention : il faut fermer le heap syst<73>me en dernier.
*/
ND_Index_Node_First_Get( &Node, Opened_Heap_List, NDD_INDEX_PRIMARY);
while( Node)
{
NDT_Node *Next_Node;
ND_Index_Node_Next_Get( &Next_Node, Node);
SM_Heap_Close_I( (SMT_Heap *)(Node->Value));
Node = Next_Node;
}
/* D<>verrouillage de la base en lecture */
SM_Base_Unlock( SMD_READ);
/* D<>tachement des segments de m<>moire partag<61>e de la base */
shmdt ( (void *)SM_Base->MHR);
shmdt ( (void *)SM_Base);
SM_Base = NULL;
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Pose d'un verrou sur la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Lock( SMT_Flags Lock_Mode )
{
SMT_Status rc;
if( Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate( SM_Base->SemId, SM_SemOp_SSL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock the library base for reading");
return rc;
}
}
if( Lock_Mode & SMD_WRITE)
{
rc = SM_Semaphore_Operate( SM_Base->SemId, SM_SemOp_SEL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock the library base for writing");
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration d'un verrou sur la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Unlock( SMT_Flags Lock_Mode )
{
SMT_Status rc;
if( Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate( SM_Base->SemId, SM_SemOp_RSL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to unlock the library base which had been locked for reading");
return rc;
}
}
if( Lock_Mode & SMD_WRITE)
{
rc = SM_Semaphore_Operate( SM_Base->SemId, SM_SemOp_REL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to unlock the library base which had been locked for writing");
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Fonction manager de la liste des heaps ouverts */
/*------------------------------------------------------------------------------*/
NDT_Status SM_Opened_Heap_List_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list *Args_Ptr)
{
NDT_Command_Name Command_Name;
switch( Command)
{
case NDD_CMD_MANAGER_VERSION:
{
ND_VA_ARG_GET( Version_Name_Ptr, *Args_Ptr, NDT_Version_Name *);
Command_Name = "NDD_CMD_MANAGER_VERSION";
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
return( NDS_OK);
}
case NDD_CMD_INDEX_GET:
{
/*
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
*/
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
Command_Name = "NDD_CMD_INDEX_GET";
switch( Cmd)
{
/*
case NDT_CMD_SOME_USER_CMD:
{
*Reply_Index_Id_Ptr = 0;
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
break;
}
...
*/
default:
{
*Reply_Index_Id_Ptr = Index_Id;
*Reply_Command_Ptr = Cmd;
break;
}
}
return( NDS_OK);
}
case NDD_CMD_VALUE_ALLOC:
{
/*
ND_VA_ARG_GET( Value_Ptr_Ptr, *Args_Ptr, void **);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_ALLOC";
return( NDS_OK);
}
case NDD_CMD_VALUE_FREE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( Heap_Ptr, *Args_Ptr, SMT_Heap *);
Command_Name = "NDD_CMD_VALUE_FREE";
free( Heap_Ptr->Name);
free( Heap_Ptr);
return( NDS_OK);
}
case NDD_CMD_VALUE_COMP:
{
/*
ND_VA_ARG_GET( Value1_Ptr, *Args_Ptr, void *);
ND_VA_ARG_GET( Value2_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( Heap1_Ptr, *Args_Ptr, SMT_Heap *);
ND_VA_ARG_GET( Heap2_Ptr, *Args_Ptr, SMT_Heap *);
long comp;
Command_Name = "NDD_CMD_VALUE_COMP";
comp = strcmp( Heap1_Ptr->Name, Heap2_Ptr->Name);
if( comp < 0) return( NDS_LOWER);
if( comp > 0) return( NDS_GREATER);
return( NDS_EQUAL);
}
case NDD_CMD_VALUE_ADD:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_ADD";
return( NDS_OK);
}
case NDD_CMD_VALUE_REMOVE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_REMOVE";
return( NDS_OK);
}
case NDD_CMD_VALUE_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
void *Value_Ptr = Node_Ptr->Value;
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_CLOSE( lib_args);
SMT_Heap *Heap_Ptr = ( SMT_Heap *)( Node_Ptr->Value);
Command_Name = "NDD_CMD_VALUE_PRINT";
/*
fprintf( Out, "Heap_Name: [%s]/[%s] Heap_Addr: (%p) MHH_Ptr: (%p) Lock_Mode: (%d) Seg_Nb: (%d)\n",
SM_Context, Heap_Ptr->Name, Heap_Ptr, Heap_Ptr->MHH, Heap_Ptr->Lock_Mode, Heap_Ptr->Nb_Seg);
*/
LG_LOG_INFO( "Heap_Name: [%s]/[%s] Heap_Addr: (%p) MHH_Ptr: (%p) Lock_Mode: (%d) Seg_Nb: (%d)",
SM_Context, Heap_Ptr->Name, Heap_Ptr, Heap_Ptr->MHH, Heap_Ptr->Lock_Mode, Heap_Ptr->Nb_Seg);
return( NDS_OK);
}
case NDD_CMD_INFO_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
void *Value_Ptr = Node_Ptr->Value;
*/
Command_Name = "NDD_CMD_INFO_PRINT";
return( NDS_OK);
}
default:
{
LG_LOG_ERROR( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR( "Manager internal error in command: (%d)", Command);
return( NDS_ERRAPI);
}
/*------------------------------------------------------------------------------*/
/* Fonction manager du MHR (Memory Heap Root) */
/*------------------------------------------------------------------------------*/
NDT_Status MHR_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list *Args_Ptr)
{
NDT_Command_Name Command_Name;
switch( Command)
{
case NDD_CMD_MANAGER_VERSION:
{
ND_VA_ARG_GET( Version_Name_Ptr, *Args_Ptr, NDT_Version_Name *);
Command_Name = "NDD_CMD_MANAGER_VERSION";
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
return( NDS_OK);
}
case NDD_CMD_INDEX_GET:
{
/*
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
*/
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
Command_Name = "NDD_CMD_INDEX_GET";
switch( Cmd)
{
/*
case NDT_CMD_SOME_USER_CMD:
{
*Reply_Index_Id_Ptr = 0;
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
break;
}
...
*/
default:
{
*Reply_Index_Id_Ptr = Index_Id;
*Reply_Command_Ptr = Cmd;
break;
}
}
return( NDS_OK);
}
case NDD_CMD_VALUE_ALLOC:
{
/*
ND_VA_ARG_GET( Value_Ptr_Ptr, *Args_Ptr, void **);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( MHH_Ptr_Ptr, *Args_Ptr, SMT_MHH **);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( Prefixed_Name, user_args, char *);
ND_VA_ARG_GET( Seg_Size, user_args, size_t);
ND_VA_LIST_CLOSE( user_args);
union semun Sem_Ctl;
int SemId;
NDT_Status rc;
NDT_Index_Type index_type = ( NDD_INDEX_STATUS_OPENED | NDD_INDEX_TYPE_LIST | NDD_INDEX_SUBTYPE_FIFO);
SMT_DSH *DSH_Ptr;
Command_Name = "NDD_CMD_VALUE_ALLOC";
/* Cr<43>ation du s<>maphore pour g<>rer les verrous sur le nouveau MHH */
SemId = semget( IPC_PRIVATE, 1, 0777 | IPC_CREAT | IPC_EXCL);
if( SemId == -1)
{
switch( errno)
{
case ENOMEM:
{
LG_LOG_ERROR( "The amount of memory is not sufficient to create a new semaphore");
break;
}
case ENOSPC:
{
LG_LOG_ERROR( "The number of semaphores exceeds the system-imposed limit");
break;
}
default:
{
LG_LOG_ERROR( "Unknown error: (%d) while creating a semaphore", errno);
break;
}
}
return( NDS_ERRMEM);
}
/* Initialisation du s<>maphore <20> 1 (<28>quivaut <20> aucun verrou pos<6F>) */
Sem_Ctl.val = 1;
if( semctl( SemId, 0, SETVAL, Sem_Ctl))
{
LG_LOG_ERROR( "Unable to initialize the value of the semaphore: (%d)", SemId);
rc = SMS_ERRSEM;
goto Error3;
}
/* R<>servation du MHH (dans la base pour le heap syst<73>me, dans le heap syst<73>me pour les autres heaps) */
if( ND_Allocator_Exec( (void **)(MHH_Ptr_Ptr), SM_Base->MHR, sizeof( SMT_MHH), SM_Base->MHR->Allocator_Name, SM_Base->MHR->Allocator_Ptr, NULL) != NDS_OK)
{
LG_LOG_ERROR( "Unable to allocate memory for the heap header");
rc = SMS_ERRSHM;
goto Error3;
}
/* Initialisation de la structure du nouveau MHH */
strcpy( ( *MHH_Ptr_Ptr)->Name, Prefixed_Name);
( *MHH_Ptr_Ptr)->Writer = getpid();
( *MHH_Ptr_Ptr)->SemId = SemId;
( *MHH_Ptr_Ptr)->State = SMD_STATE_UNVALIDATED;
( *MHH_Ptr_Ptr)->Segment_Size = ( ( Seg_Size > 0) ? Seg_Size : SEGMENT_DEFAULT_SIZE);
( *MHH_Ptr_Ptr)->Limit_Size = SMD_UNLIMITED;
( *MHH_Ptr_Ptr)->Auto_Compress = SMD_DEFAULT_COMPRESS;
( *MHH_Ptr_Ptr)->Compress_Nb = 0L;
/*
Cr<43>ation de la structure DSR :
- dans la base pour le heap syst<73>me
- dans le heap syst<73>me pour les autres heaps
*/
// rc = ND_DataStruct_Open( &( ( *MHH_Ptr_Ptr)->DSR), 1, &index_type, "SM_DSR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->Deallocator_Name, NULL, TRUE, NULL);
if( ( rc = ND_DataStruct_Open( &( ( *MHH_Ptr_Ptr)->DSR), "SHM-DSR", ND_OPEN_FLAG_CREATE, 1, &index_type, "SM_DSR_Manager", NULL, SMG_DataStruct_Handlers, TRUE, NULL)) != NDS_OK)
{
LG_LOG_ERROR( "Unable to create the DSR structure");
goto Error4;
}
/*
Cr<43>ation de la structure ACR :
- dans la base pour le heap syst<73>me
- dans le heap syst<73>me pour les autres heaps
*/
// rc = ND_DataStruct_Open( &( ( *MHH_Ptr_Ptr)->ACR), 1, &index_type, "SM_ACR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->Deallocator_Name, NULL, TRUE, NULL);
if( ( rc = ND_DataStruct_Open( &( ( *MHH_Ptr_Ptr)->ACR), "SHM-ACR", ND_OPEN_FLAG_CREATE, 1, &index_type, "SM_ACR_Manager", NULL, SMG_DataStruct_Handlers, TRUE, NULL)) != NDS_OK)
{
LG_LOG_ERROR( "Unable to create the ACR structure");
goto Error5;
}
/*
Cr<43>ation de la structure FCR :
- dans la base pour le heap syst<73>me
- dans le heap syst<73>me pour les autres heaps
*/
// rc = ND_DataStruct_Open( &( ( *MHH_Ptr_Ptr)->FCR), 1, &index_type, "SM_FCR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->Deallocator_Name, NULL, TRUE, NULL);
if( ( rc = ND_DataStruct_Open( &( ( *MHH_Ptr_Ptr)->FCR), "SHM-FCR", ND_OPEN_FLAG_CREATE, 1, &index_type, "SM_FCR_Manager", NULL, SMG_DataStruct_Handlers, TRUE, NULL)) != NDS_OK)
{
LG_LOG_ERROR( "Unable to create the FCR structure");
goto Error6;
}
/*alloction du premier segement de donnee pour le heap*/
rc = ND_Value_Alloc( (void **)&DSH_Ptr, ( *MHH_Ptr_Ptr)->DSR, *MHH_Ptr_Ptr, ( *MHH_Ptr_Ptr)->Segment_Size);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to create the DSH structure");
rc = SMS_ERRSHM;
goto Error7;
}
rc = ND_DataStruct_Value_Add( ( *MHH_Ptr_Ptr)->DSR, DSH_Ptr);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to add a data segment to the DSR structure");
goto Error8;
}
( *MHH_Ptr_Ptr)->State = SMD_STATE_VALID;
return( NDS_OK);
/* Gestion d'erreur sur cr<63>ation */
Error9:
ND_DataStruct_Value_Remove( ( *MHH_Ptr_Ptr)->DSR, DSH_Ptr);
Error8:
ND_Value_Free( ( *MHH_Ptr_Ptr)->DSR, DSH_Ptr);
Error7:
ND_Deallocator_Exec( ( *MHH_Ptr_Ptr)->FCR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
Error6:
ND_Deallocator_Exec( ( *MHH_Ptr_Ptr)->ACR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
Error5:
ND_Deallocator_Exec( ( *MHH_Ptr_Ptr)->DSR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
Error4:
ND_Deallocator_Exec( *MHH_Ptr_Ptr, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
Error3:
semctl( SemId, 0, IPC_RMID, Sem_Ctl);
return( rc);
}
case NDD_CMD_VALUE_FREE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( MHH_Ptr, *Args_Ptr, SMT_MHH *);
SMT_Status rc;
SMT_Heap To_Find;
union semun Sem_Ctl;
SMT_Heap * Opened_Heap;
Command_Name = "NDD_CMD_VALUE_FREE";
/* Destruction de la structure DSR (et de toutes ses valeurs) */
if( !strcmp( MHH_Ptr->Name, HEAP_SYSTEM))
{
NDT_Node * Node, * Previous_Node;
SMT_DSH * DSH;
/*
Pour le heap syst<73>me, on doit proc<6F>der de mani<6E>re sp<73>cifique
car le premier segment contient des r<>f<EFBFBD>rences sur les autres
segments. Il faut donc supprimer celui-ci en dernier.
Par ailleurs, ce premier segment a <20>t<EFBFBD> allou<6F> dans la base.
Il faudra donc aussi red<65>finir la fonction de d<>sallocation
du DSR pour celui-ci.
*/
ND_Index_Node_Last_Get( &Node, MHH_Ptr->DSR, NDD_INDEX_PRIMARY);
while( Node)
{
DSH = (SMT_DSH *)(Node->Value);
ND_Index_Node_Previous_Get( &Previous_Node, Node);
/* S'agit-il du heap syst<73>me ? */
if( !Previous_Node)
{
strcpy( MHH_Ptr->DSR->Deallocator_Name, "SM_Base_Free");
}
/* Retrait du segment du DSR */
rc = ND_DataStruct_Value_Remove( MHH_Ptr->DSR, DSH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to remove the shared memory segment at address: (%p) from the DSR structure", DSH->Start);
if( SM_ERROR(rc)) return rc;
}
/* Destruction du segment */
rc = ND_Value_Free( MHH_Ptr->DSR, DSH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to free the shared memory segment at address: (%p)", DSH->Start);
if( SM_ERROR(rc)) return rc;
}
Node = Previous_Node;
}
}
else
{
rc = ND_DataStruct_Close( MHH_Ptr->DSR);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to destroy the DSR structure of heap: [%s]", MHH_Ptr->Name);
}
}
/*
Destruction des structures ACR et FCR.
NB : puisque tous les chunks r<>f<EFBFBD>nrenc<6E>s par les ACR et FCR <20>taient allou<6F>s
dans les segments qui viennent d'<27>tre supprim<69>s, on se contente de d<>tuire
leur racine.
*/
rc = ND_Deallocator_Exec( MHH_Ptr->ACR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to free the ACR root of heap: [%s]", MHH_Ptr->Name);
}
rc = ND_Deallocator_Exec( MHH_Ptr->FCR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to free the FCR root of heap: [%s]", MHH_Ptr->Name);
}
/* Suppression du heap de la liste des heaps ouverts */
To_Find.Name = MHH_Ptr->Name;
rc = ND_DataStruct_Value_Find( (void **)&Opened_Heap, Opened_Heap_List, &To_Find);
if( ( rc == NDS_OK) && ( Opened_Heap != NULL))
{
rc = ND_DataStruct_Value_Remove( Opened_Heap_List, Opened_Heap);
if( rc != NDS_OK)
{
return( rc);
}
else
{
rc = ND_Value_Free( Opened_Heap_List, Opened_Heap);
if( rc != NDS_OK)
{
return( rc);
}
}
}
/* Destruction du s<>maphore attach<63> au heap */
semctl( MHH_Ptr->SemId, 0, IPC_RMID, Sem_Ctl);
/* D<>sallocation de la structure du MHH */
rc = ND_Deallocator_Exec( MHH_Ptr, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to free the header of heap: [%s]", MHH_Ptr->Name);
}
return( NDS_OK);
}
case NDD_CMD_VALUE_COMP:
{
/*
ND_VA_ARG_GET( Value1_Ptr, *Args_Ptr, void *);
ND_VA_ARG_GET( Value2_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( MHH1_Ptr, *Args_Ptr, SMT_MHH *);
ND_VA_ARG_GET( MHH2_Ptr, *Args_Ptr, SMT_MHH *);
long comp;
Command_Name = "NDD_CMD_VALUE_COMP";
comp = strcmp( MHH1_Ptr->Name, MHH2_Ptr->Name);
if( comp < 0) return( NDS_LOWER);
if( comp > 0) return( NDS_GREATER);
return( NDS_EQUAL);
}
case NDD_CMD_VALUE_ADD:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_ADD";
return( NDS_OK);
}
case NDD_CMD_VALUE_REMOVE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_REMOVE";
return( NDS_OK);
}
case NDD_CMD_VALUE_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
void *Value_Ptr = Node_Ptr->Value;
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_CLOSE( lib_args);
SMT_MHH *MHH_Ptr = (SMT_MHH *)( Node_Ptr->Value);
SMT_Status status;
size_t segment_size=0, alloc_size=0, free_size=0;
int segment_nb, alloc_chunk_nb, free_chunk_nb;
SMT_Heap *heap_ptr;
char *heap_name;
int locked;
Command_Name = "NDD_CMD_VALUE_PRINT";
/* On n'affiche le heap que s'il fait partie du contexte courant */
if( ( heap_name = strstr( MHH_Ptr->Name, SM_Context)) != 0)
{
heap_name += strlen( SM_Context) + 1;
}
else
{
if( strcmp( HEAP_SYSTEM, MHH_Ptr->Name) == 0)
{
heap_name = MHH_Ptr->Name;
}
else
{
return( NDS_OK);
}
}
if( MHH_Ptr->State == SMD_STATE_CORRUPTED)
{
/*
fprintf( Out, "Heap_Name: [%s]/[%s] Heap_Addr: (%lx) *** CORRUPTED *** Checker_PId: (%ld)\n",
SM_Context, MHH_Ptr->Name, MHH_Ptr, MHH_Ptr->Writer);
*/
LG_LOG_INFO( "Heap_Name: [%s]/[%s] Heap_Addr: (%lx) *** CORRUPTED *** Checker_PId: (%ld)",
SM_Context, MHH_Ptr->Name, MHH_Ptr, MHH_Ptr->Writer);
return( NDS_OK);
}
if( status = ( SM_Heap_Open_I( heap_name, &heap_ptr, 0, ( SMD_OPEN | SMD_READ), &locked)) != SMS_OK)
{
LG_LOG_ERROR( "Unable to open Heap_Name: [%s] for reading", MHH_Ptr->Name);
return( status);
}
/* TEST !!! */
if( locked != TRUE)
{
LG_LOG_ERROR( "Unable to lock Heap_Name: [%s] for reading", MHH_Ptr->Name);
// return( SMS_KO);
}
segment_nb = MHH_Ptr->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
ND_DataStruct_Traverse( MHH_Ptr->DSR, NDD_CMD_VALUE_SUM, (void *)&segment_size);
alloc_chunk_nb = MHH_Ptr->ACR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
ND_DataStruct_Traverse( MHH_Ptr->ACR, NDD_CMD_VALUE_SUM, (void *)&alloc_size);
free_chunk_nb = MHH_Ptr->FCR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
ND_DataStruct_Traverse( MHH_Ptr->FCR, NDD_CMD_VALUE_SUM, (void *)&free_size);
/*
fprintf( Out, "Heap_Name: [%s]/[%s] Heap_Addr: (%p) Sem_Id: (%d) Lock_Status: [%s]\nWriter_PId: (%ld) Seg_Nb: (%d) Heap_Size: (%lu) Size_Limit: (%ld) Auto_Compress: (%d) Compress_Nb: (%ld)\nAlloc_Chunk_Nb: (%d) Alloc_Size: (%lu) Free_Chunk_Nb: (%d) Free_Size: (%lu)\n\n",
SM_Context, heap_name, MHH_Ptr, MHH_Ptr->SemId, SM_Lock_Status_Get( "heap", MHH_Ptr),
MHH_Ptr->Writer, segment_nb, segment_size, MHH_Ptr->Limit_Size, MHH_Ptr->Auto_Compress, MHH_Ptr->Compress_Nb,
alloc_chunk_nb, alloc_size, free_chunk_nb, free_size);
*/
LG_LOG_INFO( "Heap_Name: [%s]/[%s] Heap_Addr: (%p) Sem_Id: (%d) Lock_Status: [%s]",
SM_Context, heap_name, MHH_Ptr, MHH_Ptr->SemId, SM_Lock_Status_Get( "heap", MHH_Ptr));
LG_LOG_INFO( "Writer_PId: (%ld) Seg_Nb: (%d) Heap_Size: (%lu) Size_Limit: (%ld) Auto_Compress: (%d) Compress_Nb: (%ld)",
MHH_Ptr->Writer, segment_nb, segment_size, MHH_Ptr->Limit_Size, MHH_Ptr->Auto_Compress, MHH_Ptr->Compress_Nb);
LG_LOG_INFO( "Alloc_Chunk_Nb: (%d) Alloc_Size: (%lu) Free_Chunk_Nb: (%d) Free_Size: (%lu)",
alloc_chunk_nb, alloc_size, free_chunk_nb, free_size);
LG_LOG_INFO( "");
if( locked == TRUE)
{
SM_Heap_Unlock_I( heap_ptr);
}
return( NDS_OK);
}
case NDD_CMD_INFO_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_CLOSE( lib_args);
Command_Name = "NDD_CMD_INFO_PRINT";
return( NDS_OK);
}
default:
{
LG_LOG_ERROR( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR( "Manager internal error in command: (%d)", Command);
return( NDS_ERRAPI);
}
/*------------------------------------------------------------------------------*/
/* Destruction d'un MHH (Memory Heap Header) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_MHH_End( SMT_MHH *MHH)
{
SMT_Status rc;
SMT_Heap To_Find;
union semun Sem_Ctl;
SMT_Heap * Opened_Heap;
/* Destruction de la structure DSR (et de toutes ses valeurs) */
if( !strcmp( MHH->Name, HEAP_SYSTEM))
{
NDT_Node * Node, * Previous_Node;
SMT_DSH * DSH;
/*
Pour le heap syst<73>me, on doit proc<6F>der de mani<6E>re sp<73>cifique
car le premier segment contient des r<>f<EFBFBD>rences sur les autres
segments. Il faut donc supprimer celui-ci en dernier.
Par ailleurs, ce premier segment a <20>t<EFBFBD> allou<6F> dans la base.
Il faudra donc aussi red<65>finir la fonction de d<>sallocation
du DSR pour celui-ci.
*/
ND_Index_Node_Last_Get( &Node, MHH->DSR, NDD_INDEX_PRIMARY);
while( Node)
{
DSH = (SMT_DSH *)(Node->Value);
ND_Index_Node_Previous_Get( &Previous_Node, Node);
/* S'agit-il du heap syst<73>me ? */
if( !Previous_Node)
{
strcpy( MHH->DSR->Deallocator_Name, "SM_Base_Free");
}
/* Retrait du segment du DSR */
rc = ND_DataStruct_Value_Remove( MHH->DSR, DSH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to remove the shared memory segment at address: (%p) from the DSR structure", DSH->Start);
if( SM_ERROR(rc)) return rc;
}
/* Destruction du segment */
rc = ND_Value_Free( MHH->DSR, DSH);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to free the shared memory segment at address: (%p)", DSH->Start);
if( SM_ERROR(rc)) return rc;
}
Node = Previous_Node;
}
}
else
{
rc = ND_DataStruct_Close( MHH->DSR);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to destroy the DSR structure of heap: [%s]", MHH->Name);
}
}
/*
Destruction des structures ACR et FCR.
NB : puisque tous les chunks r<>f<EFBFBD>nrenc<6E>s par les ACR et FCR <20>taient allou<6F>s
dans les segments qui viennent d'<27>tre supprim<69>s, on se contente de d<>tuire
leur racine.
*/
rc = ND_Deallocator_Exec( MHH->ACR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to free the ACR root of heap: [%s]", MHH->Name);
}
rc = ND_Deallocator_Exec( MHH->FCR, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "Unable to free the FCR root of heap: [%s]", MHH->Name);
}
/* Suppression du heap de la liste des heaps ouverts */
To_Find.Name = MHH->Name;
rc = ND_DataStruct_Value_Find( (void **)&Opened_Heap, Opened_Heap_List, &To_Find);
if( ( rc == NDS_OK) && ( Opened_Heap != NULL))
{
rc = ND_DataStruct_Value_Remove( Opened_Heap_List, Opened_Heap);
if( rc != NDS_OK)
{
return( rc);
}
else
{
rc = ND_Value_Free( Opened_Heap_List, Opened_Heap);
if( rc != NDS_OK)
{
return( rc);
}
}
}
/* Destruction du s<>maphore attach<63> au heap */
semctl( MHH->SemId, 0, IPC_RMID, Sem_Ctl);
/* D<>sallocation de la structure du MHH */
rc = ND_Deallocator_Exec( MHH, SM_Base->MHR, SM_Base->MHR->Deallocator_Name, SM_Base->MHR->Deallocator_Ptr, NULL);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to free the header of heap: [%s]", MHH->Name);
}
return rc;
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Gestion des segments de donn<6E>es */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Fonction manager pour un DSR (Data Segment Root) */
/*------------------------------------------------------------------------------*/
NDT_Status SM_DSR_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list *Args_Ptr)
{
NDT_Command_Name Command_Name;
NDT_Node * Chunk_Node;
SMT_Chunk * Chunk;
switch( Command)
{
case NDD_CMD_MANAGER_VERSION:
{
ND_VA_ARG_GET( Version_Name_Ptr, *Args_Ptr, NDT_Version_Name *);
Command_Name = "NDD_CMD_MANAGER_VERSION";
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
return( NDS_OK);
}
case NDD_CMD_INDEX_GET:
{
/*
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
*/
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
Command_Name = "NDD_CMD_INDEX_GET";
switch( Cmd)
{
/*
case NDT_CMD_SOME_USER_CMD:
{
*Reply_Index_Id_Ptr = 0;
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
break;
}
...
*/
default:
{
*Reply_Index_Id_Ptr = Index_Id;
*Reply_Command_Ptr = Cmd;
break;
}
}
return( NDS_OK);
}
case NDD_CMD_VALUE_ALLOC:
{
/*
ND_VA_ARG_GET( Value_Ptr_Ptr, *Args_Ptr, void **);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( DSH_Ptr_Ptr, *Args_Ptr, SMT_DSH **);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( MHH_Ptr, user_args, SMT_MHH *);
ND_VA_ARG_GET( Segment_Size, user_args, size_t);
ND_VA_LIST_CLOSE( user_args);
Command_Name = "NDD_CMD_VALUE_ALLOC";
/* On v<>rifie que le heap n'atteint pas sa limite */
if( MHH_Ptr->Limit_Size != SMD_UNLIMITED)
{
size_t Current_Size;
ND_DataStruct_Traverse( MHH_Ptr->DSR, NDD_CMD_VALUE_SUM, (void *)&Current_Size);
if( Current_Size + Segment_Size > MHH_Ptr->Limit_Size)
{
LG_LOG_ERROR( "The heap limit size would be exceeded");
*DSH_Ptr_Ptr = NULL;
return( NDS_KO);
}
}
/* Cr<43>ation de l'ent<6E>te */
if( ND_Allocator_Exec( (void **)DSH_Ptr_Ptr, MHH_Ptr->DSR, sizeof (SMT_DSH), MHH_Ptr->DSR->Allocator_Name, MHH_Ptr->DSR->Allocator_Ptr, NULL) != NDS_OK)
{
LG_LOG_ERROR( "Unable to allocate memory for the new data segment header");
return( NDS_KO);
}
/* Cr<43>ation d'un segment de m<>moire partag<61>e */
if( ( ( *DSH_Ptr_Ptr)->MemId = shmget (IPC_PRIVATE, Segment_Size, 0777|IPC_CREAT|IPC_EXCL)) == -1)
{
switch( errno)
{
case EINVAL:
{
LG_LOG_ERROR( "The size of the shared memory segment: (%d) is out of the system-imposed bounds", Segment_Size);
break;
}
case ENOMEM:
{
LG_LOG_ERROR( "The amount of memory is not sufficient to create the shared memory segment");
break;
}
case ENOSPC:
{
LG_LOG_ERROR( "The number of shared memory segments exceeds the system-imposed limit");
break;
}
default:
{
LG_LOG_ERROR( "Unknown error: (%d) while creating a shared memory segment", errno);
break;
}
}
ND_Deallocator_Exec( ( *DSH_Ptr_Ptr), MHH_Ptr->DSR, MHH_Ptr->DSR->Deallocator_Name, MHH_Ptr->DSR->Deallocator_Ptr, NULL);
return( NDS_KO);
}
/* On attache le segment de m<>moire partag<61>e au processus courant */
errno = 0;
#ifndef __hpux
( *DSH_Ptr_Ptr)->Start = shmat( ( *DSH_Ptr_Ptr)->MemId, (void *)( (size_t)(SM_Base->Attach) - Segment_Size), SHM_RND);
#else
( *DSH_Ptr_Ptr)->Start = shmat( ( *DSH_Ptr_Ptr)->MemId, 0, 0);
#endif
if( errno)
{
LG_LOG_ERROR( "Unable to attach the shared memory segment to the current process, error: (%d)", errno);
shmctl( ( *DSH_Ptr_Ptr)->MemId, IPC_RMID, 0);
ND_Deallocator_Exec( *DSH_Ptr_Ptr, MHH_Ptr->DSR, MHH_Ptr->DSR->Deallocator_Name, MHH_Ptr->DSR->Deallocator_Ptr, NULL);
return( NDS_KO);
}
SM_Base->Attach = ( *DSH_Ptr_Ptr)->Start;
/* Initialisation des informations de l'ent<6E>te */
( *DSH_Ptr_Ptr)->Size = Segment_Size;
/* Cr<43>ation d'un chunk libre au d<>but du segment de donn<6E>es */
Chunk_Node = (NDT_Node *)( *DSH_Ptr_Ptr)->Start;
Chunk = (SMT_Chunk *)( (size_t)Chunk_Node + sizeof (NDT_Node) );
Chunk_Node->Value = Chunk;
Chunk->Data = (void *)( (size_t)Chunk + sizeof (SMT_Chunk) );
Chunk->Size = ( *DSH_Ptr_Ptr)->Size - sizeof (NDT_Node) - sizeof (SMT_Chunk);
/* Ajout du chunk libre <20> la liste des chunks libres du heap */
if( ND_Index_Node_Add( MHH_Ptr->FCR, NDD_INDEX_PRIMARY, Chunk_Node) != NDS_OK)
{
LG_LOG_ERROR( "Unable to add a first chunk to the FCR structure of heap: [%s]", MHH_Ptr->Name);
shmctl ( ( *DSH_Ptr_Ptr)->MemId, IPC_RMID, 0);
ND_Deallocator_Exec( ( *DSH_Ptr_Ptr), MHH_Ptr->DSR, MHH_Ptr->DSR->Deallocator_Name, MHH_Ptr->DSR->Deallocator_Ptr, NULL);
return( NDS_KO);
}
return( NDS_OK);
}
case NDD_CMD_VALUE_FREE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( DSH_Ptr, *Args_Ptr, SMT_DSH *);
SMT_Status rc;
Command_Name = "NDD_CMD_VALUE_FREE";
/* Destruction du segment de m<>moire partag<61>e du segment de donn<6E>es */
if( shmctl (DSH_Ptr->MemId, IPC_RMID, 0) == -1)
{
switch( errno)
{
case EPERM:
{
LG_LOG_ERROR( "Current process: (%d) is not allowed to destroy the shared memory segment: (%d)", (int)getpid (), DSH_Ptr->MemId);
break;
}
case EINVAL:
{
LG_LOG_ERROR( "No shared memory segment exists for identifier: (%d)", DSH_Ptr->MemId);
break;
}
default:
{
LG_LOG_ERROR( "Unknown error: (%d) while destroying the shared memory segment: (%d)", errno, DSH_Ptr->MemId);
break;
}
}
return SMS_ERRSHM;
}
/* D<>sallocation de l'ent<6E>te */
rc = ND_Deallocator_Exec( DSH_Ptr, Root_Ptr, Root_Ptr->Deallocator_Name, Root_Ptr->Deallocator_Ptr, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR( "The data segment header is nul");
return rc;
}
return NDS_OK;
}
case NDD_CMD_VALUE_COMP:
{
/*
ND_VA_ARG_GET( Value1_Ptr, *Args_Ptr, void *);
ND_VA_ARG_GET( Value2_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( DSH1_Ptr, *Args_Ptr, SMT_DSH *);
ND_VA_ARG_GET( DSH2_Ptr, *Args_Ptr, SMT_DSH *);
Command_Name = "NDD_CMD_VALUE_COMP";
if( DSH1_Ptr->MemId < DSH2_Ptr->MemId) return( NDS_LOWER);
if( DSH1_Ptr->MemId > DSH2_Ptr->MemId) return( NDS_GREATER);
return( NDS_EQUAL);
}
case NDD_CMD_VALUE_ADD:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_ADD";
return( NDS_OK);
}
case NDD_CMD_VALUE_REMOVE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_REMOVE";
return( NDS_OK);
}
case NDD_CMD_VALUE_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
void *Value_Ptr = Node_Ptr->Value;
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_CLOSE( lib_args);
SMT_DSH *DSH_Ptr = (SMT_DSH *)( Node_Ptr->Value);
Command_Name = "NDD_CMD_VALUE_PRINT";
/*
fprintf( Out, "Data Segment Header: Mem_Id: (%d) Start: (%p) Size: (%ld)\n",
DSH_Ptr->MemId, DSH_Ptr->Start, DSH_Ptr->Size);
*/
LG_LOG_INFO( "Data Segment Header: Mem_Id: (%d) Start: (%p) Size: (%ld)",
DSH_Ptr->MemId, DSH_Ptr->Start, DSH_Ptr->Size);
return( NDS_OK);
}
case NDD_CMD_INFO_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_CLOSE( lib_args);
Command_Name = "NDD_CMD_INFO_PRINT";
return( NDS_OK);
}
case NDD_CMD_VALUE_SUM:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
void *Value_Ptr = Node_Ptr->Value;
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( Total_Size, user_args, size_t *);
ND_VA_LIST_CLOSE( user_args);
SMT_DSH *DSH_Ptr = (SMT_DSH *)( Node_Ptr->Value);
Command_Name = "NDD_CMD_VALUE_SUM";
*Total_Size += DSH_Ptr->Size;
return( NDS_OK);
}
default:
{
LG_LOG_ERROR( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR( "Manager internal error in command: (%d)", Command);
return( NDS_ERRAPI);
}
/*------------------------------------------------------------------------------*/
/* Ouverture d'un segment de donn<6E>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_DataSegment_Open ( SMT_DSH *DSH)
{
void *Ptr;
/*
On attache le segment de m<>moire partag<61>e au processus courant.
Attention : il faut que ce segment soit attach<63> <20> la m<>me adresse
que lorsqu'il a <20>t<EFBFBD> cr<63><72> afin que les pointeurs qui pointent dans
ce segment soient valides.
*/
shmdt ( (void *)DSH->Start);
errno = 0;
Ptr = shmat( DSH->MemId, DSH->Start, 0);
if( errno)
{
LG_LOG_ERROR( "Unable to attach the shared memory segment at the specified address: (%p) error: (%d)", DSH->Start, errno);
return SMS_ERRSHM;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Fermeture d'un segment de donn<6E>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_DataSegment_Close( SMT_DSH *DSH)
{
/* On d<>tache le segment de m<>moire partag<61>e du processus courant */
shmdt ( (void *)DSH->Start);
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Compression d'un segment de donn<6E>es */
/*------------------------------------------------------------------------------*/
size_t SM_DataSegment_Compress ( SMT_DSH *DSH, NDT_Root *FCR)
{
size_t Total_Compress = 0;
size_t Compress;
SMT_Chunk *Chunk, *Next_Chunk;
NDT_Node * Node, *Next_Node;
void *DSH_End;
int Found = FALSE;
DSH_End = (void *)( (size_t)(DSH->Start) + DSH->Size);
/* Recherche du premier chunk libre contenu dans le segment courant */
ND_Index_Node_First_Get( &Node, FCR, NDD_INDEX_PRIMARY);
while( Found == FALSE && Node)
{
if( Node > (NDT_Node *)DSH_End) Node = NULL;
else
{
if( Node >= (NDT_Node *)(DSH->Start)) Found = TRUE;
else ND_Index_Node_Next_Get( &Node, Node);
}
}
if( !Node) return 0;
/* Parcours de tous les chunks libres du segment courant */
ND_Index_Node_Next_Get( &Next_Node, Node);
while( Next_Node && (void *)Next_Node < DSH_End)
{
Chunk = (SMT_Chunk *)(Node->Value);
Next_Chunk = (SMT_Chunk *)(Next_Node->Value);
/* Si le chunk suivant est "coll<6C>" au chunk courant, alors on les fusionne */
if( Next_Node == (NDT_Node *)( (size_t)(Chunk->Data) + Chunk->Size))
{
ND_Index_Node_Remove( Next_Node);
Compress = sizeof (SMT_Chunk) + sizeof (NDT_Node);
Chunk->Size += Next_Chunk->Size + Compress;
Total_Compress += Compress;
ND_Index_Node_Next_Get( &Next_Node, Node);
}
else
{
Node = Next_Node;
ND_Index_Node_Next_Get( &Next_Node, Next_Node);
}
}
return Total_Compress;
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Fonction de gestion de chunks */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Fonction manager pour un ACR (Allocated Chunk Root) */
/*------------------------------------------------------------------------------*/
NDT_Status SM_ACR_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list *Args_Ptr)
{
NDT_Command_Name Command_Name;
switch( Command)
{
case NDD_CMD_MANAGER_VERSION:
{
ND_VA_ARG_GET( Version_Name_Ptr, *Args_Ptr, NDT_Version_Name *);
Command_Name = "NDD_CMD_MANAGER_VERSION";
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
return( NDS_OK);
}
case NDD_CMD_INDEX_GET:
{
/*
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
*/
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
Command_Name = "NDD_CMD_INDEX_GET";
switch( Cmd)
{
/*
case NDT_CMD_SOME_USER_CMD:
{
*Reply_Index_Id_Ptr = 0;
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
break;
}
...
*/
default:
{
*Reply_Index_Id_Ptr = Index_Id;
*Reply_Command_Ptr = Cmd;
break;
}
}
return( NDS_OK);
}
case NDD_CMD_VALUE_ALLOC:
{
/*
ND_VA_ARG_GET( Value_Ptr_Ptr, *Args_Ptr, void **);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_ALLOC";
return( NDS_OK);
}
case NDD_CMD_VALUE_FREE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_FREE";
return( NDS_OK);
}
case NDD_CMD_VALUE_COMP:
{
/*
ND_VA_ARG_GET( Value1_Ptr, *Args_Ptr, void *);
ND_VA_ARG_GET( Value2_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( Chunk1_Ptr, *Args_Ptr, SMT_Chunk *);
ND_VA_ARG_GET( Chunk2_Ptr, *Args_Ptr, SMT_Chunk *);
Command_Name = "NDD_CMD_VALUE_COMP";
/* Les chunks allou<6F>s sont tri<72>s sur le champ <Data> (adresse d'allocation) */
if( Chunk1_Ptr->Data < Chunk1_Ptr->Data) return( NDS_LOWER);
if( Chunk1_Ptr->Data > Chunk2_Ptr->Data) return( NDS_GREATER);
return( NDS_EQUAL);
}
case NDD_CMD_VALUE_ADD:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_ADD";
return( NDS_OK);
}
case NDD_CMD_VALUE_REMOVE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_REMOVE";
return( NDS_OK);
}
case NDD_CMD_VALUE_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
void *Value_Ptr = Node_Ptr->Value;
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
SMT_Chunk *Chunk_Ptr = (SMT_Chunk *)( Node_Ptr->Value);
Command_Name = "NDD_CMD_VALUE_PRINT";
/*
fprintf( Out, "Allocated Chunk: Chunk_Addr: (%p) Data_Addr: (%p) Data_Size: (%ld)\n",
Chunk_Ptr, Chunk_Ptr->Data, Chunk_Ptr->Size);
*/
LG_LOG_INFO( "Allocated Chunk: Chunk_Addr: (%p) Data_Addr: (%p) Data_Size: (%ld)",
Chunk_Ptr, Chunk_Ptr->Data, Chunk_Ptr->Size);
return( NDS_OK);
}
case NDD_CMD_INFO_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
Command_Name = "NDD_CMD_INFO_PRINT";
return( NDS_OK);
}
case NDD_CMD_VALUE_SUM:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
void *Value_Ptr = Node_Ptr->Value;
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( Total_Size_Ptr, user_args, size_t *);
ND_VA_LIST_CLOSE( user_args);
SMT_Chunk *Chunk_Ptr = (SMT_Chunk *)( Node_Ptr->Value);
Command_Name = "NDD_CMD_VALUE_SUM";
*Total_Size_Ptr += Chunk_Ptr->Size;
return( NDS_OK);
}
default:
{
LG_LOG_ERROR( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR( "Manager internal error in command: (%d)", Command);
return( NDS_ERRAPI);
}
/*------------------------------------------------------------------------------*/
/* Fonction manager pour un FCR (Free Chunk Root) */
/*------------------------------------------------------------------------------*/
NDT_Status SM_FCR_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list *Args_Ptr)
{
NDT_Command_Name Command_Name;
switch( Command)
{
case NDD_CMD_MANAGER_VERSION:
{
ND_VA_ARG_GET( Version_Name_Ptr, *Args_Ptr, NDT_Version_Name *);
Command_Name = "NDD_CMD_MANAGER_VERSION";
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
return( NDS_OK);
}
case NDD_CMD_INDEX_GET:
{
/*
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
*/
ND_VA_ARG_GET( Reply_Index_Id_Ptr, *Args_Ptr, NDT_Index_Id *);
ND_VA_ARG_GET( Reply_Command_Ptr, *Args_Ptr, NDT_Command *);
ND_VA_ARG_GET( Cmd, *Args_Ptr, NDT_Command);
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
Command_Name = "NDD_CMD_INDEX_GET";
switch( Cmd)
{
/*
case NDT_CMD_SOME_USER_CMD:
{
*Reply_Index_Id_Ptr = 0;
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
break;
}
...
*/
default:
{
*Reply_Index_Id_Ptr = Index_Id;
*Reply_Command_Ptr = Cmd;
break;
}
}
return( NDS_OK);
}
case NDD_CMD_VALUE_ALLOC:
{
/*
ND_VA_ARG_GET( Value_Ptr_Ptr, *Args_Ptr, void **);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_ALLOC";
return( NDS_OK);
}
case NDD_CMD_VALUE_FREE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_FREE";
return( NDS_OK);
}
case NDD_CMD_VALUE_COMP:
{
/*
ND_VA_ARG_GET( Value1_Ptr, *Args_Ptr, void *);
ND_VA_ARG_GET( Value2_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
ND_VA_ARG_GET( Chunk1_Ptr, *Args_Ptr, SMT_Chunk *);
ND_VA_ARG_GET( Chunk2_Ptr, *Args_Ptr, SMT_Chunk *);
Command_Name = "NDD_CMD_VALUE_COMP";
/*
La comparaison des chunks libres porte sur le champ <Data>
pour faciliter la compression des heaps.
*/
if( Chunk1_Ptr->Data < Chunk1_Ptr->Data) return( NDS_LOWER);
if( Chunk1_Ptr->Data > Chunk2_Ptr->Data) return( NDS_GREATER);
return( NDS_EQUAL);
}
case NDD_CMD_VALUE_ADD:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_ADD";
return( NDS_OK);
}
case NDD_CMD_VALUE_REMOVE:
{
/*
ND_VA_ARG_GET( Value_Ptr, *Args_Ptr, void *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
*/
Command_Name = "NDD_CMD_VALUE_REMOVE";
return( NDS_OK);
}
case NDD_CMD_VALUE_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
void *Value_Ptr = Node_Ptr->Value;
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
SMT_Chunk *Chunk_Ptr = (SMT_Chunk *)( Node_Ptr->Value);
Command_Name = "NDD_CMD_VALUE_PRINT";
// fprintf( Out, "Free Chunk: Chunk_Addr: (%p) Data_Ptr: (%p) Size: (%ld)\n", Chunk_Ptr, Chunk_Ptr->Data, Chunk_Ptr->Size);
LG_LOG_INFO( "Free Chunk: Chunk_Addr: (%p) Data_Ptr: (%p) Size: (%ld)", Chunk_Ptr, Chunk_Ptr->Data, Chunk_Ptr->Size);
return( NDS_OK);
}
case NDD_CMD_INFO_PRINT:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
ND_VA_LIST_OPEN( user_args, lib_args);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
ND_VA_LIST_CLOSE( lib_args);
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( lib_args, *Args_Ptr);
ND_VA_ARG_GET( Out, lib_args, FILE *);
ND_VA_ARG_GET( Recursive_Mode, lib_args, NDT_Recursive_Mode);
ND_VA_ARG_GET( Recursive_Depth, lib_args, NDT_Recursive_Depth);
ND_VA_ARG_GET( Recursive_Offset, lib_args, NDT_Recursive_Offset);
Command_Name = "NDD_CMD_INFO_PRINT";
return( NDS_OK);
}
case NDD_CMD_VALUE_SUM:
{
/*
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( user_data, user_args, user_type);
ND_VA_ARG_GET( ..., user_args, ...);
ND_VA_LIST_CLOSE( user_args);
void *Value_Ptr = Node_Ptr->Value;
*/
ND_VA_ARG_GET( Next_Node_Ptr, *Args_Ptr, NDT_Node *);
ND_VA_LIST_OPEN( user_args, *Args_Ptr);
ND_VA_ARG_GET( Total_Size_Ptr, user_args, size_t *);
ND_VA_LIST_CLOSE( user_args);
SMT_Chunk *Chunk_Ptr = (SMT_Chunk *)( Node_Ptr->Value);
Command_Name = "NDD_CMD_VALUE_SUM";
*Total_Size_Ptr += Chunk_Ptr->Size;
return( NDS_OK);
}
default:
{
LG_LOG_ERROR( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR( "Manager internal error in command: (%d)", Command);
return( NDS_ERRAPI);
}
/*------------------------------------------------------------------------------*/
/* Pose d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_Set ( SMT_MHH * MHH, SMT_Flags Lock_Mode )
{
SMT_Status rc;
if( Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate( MHH->SemId, SM_SemOp_SSL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock the heap: [%s] for reading", MHH->Name);
return rc;
}
}
if( Lock_Mode & SMD_WRITE)
{
rc = SM_Semaphore_Operate( MHH->SemId, SM_SemOp_SEL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to lock the heap: [%s] for writing", MHH->Name);
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Changement d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_Change( SMT_MHH * MHH, SMT_Flags Lock_Mode )
{
SMT_Status rc;
if( Lock_Mode & SMD_WRITE)
{
/*
Attention : il ne faut pas tenter de transformer directement un verrou en lecture en
un verrou en <20>criture car cela pourrait aboutir <20> un deadlock entre deux processus
qui voudraient r<>aliser cette op<6F>ration en m<>me temps.
=> On passe donc par un d<>verrouillage interm<72>diaire.
*/
if( (rc = SM_Semaphore_Operate( MHH->SemId, SM_SemOp_RSL, 2)) != SMS_OK)
{
LG_LOG_ERROR( "Unable to transform the heap: [%s] lock for writing", MHH->Name);
return rc;
}
if( (rc = SM_Semaphore_Operate( MHH->SemId, SM_SemOp_SEL, 2)) != SMS_OK)
{
LG_LOG_ERROR( "Unable to transform the heap: [%s] lock for writing", MHH->Name);
/* On tente de revenir <20> l'<27>tat de verrouillage pr<70>c<EFBFBD>dent */
SM_Semaphore_Operate( MHH->SemId, SM_SemOp_SSL, 2);
return rc;
}
}
else if( Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate( MHH->SemId, SM_SemOp_TSL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to transform the heap: [%s] lock for reading", MHH->Name);
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_Release( SMT_MHH * MHH, SMT_Flags Lock_Mode )
{
SMT_Status rc;
if( Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate( MHH->SemId, SM_SemOp_RSL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to unlock the heap: [%s] which had been locked for reading", MHH->Name);
return rc;
}
}
if( Lock_Mode & SMD_WRITE)
{
rc = SM_Semaphore_Operate( MHH->SemId, SM_SemOp_REL, 2);
if( rc != SMS_OK)
{
LG_LOG_ERROR( "Unable to unlock the heap: [%s] which had been locked for writing", MHH->Name);
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Op<4F>ration sur un s<>maphore */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Semaphore_Operate( int SemId, struct sembuf * Operations, unsigned int Nb_Oper)
{
if( semop( SemId, Operations, Nb_Oper) == -1)
{
switch( errno)
{
case EAGAIN:
{
LG_LOG_ERROR( "The operation would result in suspension of the calling process but the operations have been defined in no wait mode");
return SMS_NO_WAIT;
}
case EACCES:
{
LG_LOG_ERROR( "Current process is not allowed to operate on semaphore: (%d)", SemId);
break;
}
case EIDRM:
{
LG_LOG_ERROR( "Semaphore: (%d) does not exist", SemId);
break;
}
case EINTR:
{
LG_LOG_ERROR( "A signal was received while operating on semaphore: (%d)", SemId);
return SMS_ERRSIG;
}
case EINVAL:
{
LG_LOG_ERROR( "The semaphore identifier: (%d) is incorrect or the number of operations which can be done in UNDO mode exceeds the system-imposed limit", SemId);
break;
}
case ENOSPC:
{
LG_LOG_ERROR( "The maximum number of process which can operate on semaphore: (%d) in UNDO mode has been reached", SemId);
break;
}
case ERANGE:
{
LG_LOG_ERROR( "The value of semaphore: (%d) has reached the system-imposed limit", SemId);
break;
}
default:
{
LG_LOG_ERROR( "Unknown error: (%d) while operating on semaphore: (%d)", errno, SemId);
break;
}
}
return SMS_ERRSEM;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>re sous forme explicite l'<27>tat d'un verrou */
/*------------------------------------------------------------------------------*/
char *SM_Lock_Status_Get( const char *Type_Name, void *Struct_Ptr)
{
static char status[50];
int i, sem_id;
pid_t writer;
union semun sem_ctl;
if( !strcmp( Type_Name, "base"))
{
sem_id = SM_Base->SemId;
writer = SM_Base->Writer;
}
else
{
if( !strcmp( Type_Name, "heap"))
{
SMT_MHH *MHH_Ptr = (SMT_MHH *)Struct_Ptr;
sem_id = MHH_Ptr->SemId;
writer = MHH_Ptr->Writer;
}
else
{
strcpy( status, "Unknown");
return( status);
}
}
i = semctl( sem_id, 0, GETVAL, sem_ctl);
switch( i)
{
case 0:
{
sprintf( status, "Exclusive Lock for PId: (%ld)", writer);
break;
}
case 1:
{
sprintf( status, "Unlocked");
break;
}
default :
{
if( i < 0)
{
sprintf( status, "Abnormal Status: (%d)", i);
}
else
{
sprintf( status, "Shared Lock Process_Nb: (%d)", i - 1);
}
break;
}
}
return( status);
}
/*------------------------------------------------------------------------------*/
/* Add context prefix to heap name */
/*------------------------------------------------------------------------------*/
/* (O) Prefixed: Prefixed heap name */
/* (I) Unprefixed: Unprefixed heap name */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Name_Prefix( char *Prefixed, const char *Unprefixed)
{
if( !SM_Context || !strlen( SM_Context) || !strcmp( Unprefixed, HEAP_SYSTEM))
{
strcpy( Prefixed, Unprefixed);
}
else
{
snprintf( Prefixed, SMD_NAME_SIZE, "%s/%s", SM_Context, Unprefixed);
}
return( SMS_OK);
}