/*----------------------------------------------------------------------------*/
/* 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 */
/* . */
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* Includes */
/*----------------------------------------------------------------------------*/
#define _LIBSHMEM_C_
#include
//#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éro de l'instance de la librairie */
/* (I) Context : nom du nouveau contexte */
/* (I) Open_Mode : indicateur cré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 à 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éation d'une nouvelle instance */
{
/* On vérifie que le processus courant n'accède pas déjà à une instance */
if( SM_Open_Counter > 0)
{
LG_LOG_ERROR_1( "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_0( "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", 1, &index_type, "SM_Opened_Heap_List_Manager", NULL, NULL, TRUE, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR_0( "SM_Library_Open : unable to create the local opened heap cache");
goto Error1;
}
/* Création de la base de mémoire partagée */
SM_Instance = To_Open_Instance;
rc = SM_Base_Init();
if( rc != SMS_OK )
{
LG_LOG_ERROR_0( "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à ouvert une autre instance */
if( SM_Open_Counter > 0 && To_Open_Instance != SM_Instance)
{
LG_LOG_ERROR_2( "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è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_0( "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", 1, &index_type, "SM_Opened_Heap_List_Manager", NULL, NULL, TRUE, NULL);
if( rc != NDS_OK)
{
LG_LOG_ERROR_0( "Unable to create the local opened heap cache");
goto Error1;
}
/* Ouverture de la base de mémoire partagée */
rc = SM_Base_Open();
if( rc != SMS_OK )
{
LG_LOG_ERROR_0( "Unable to open the shared memory base");
goto Error2;
}
}
}
/* Définition du contexte */
SM_Library_Context_Set_I( Context);
/* On incré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ération du numéro de l'instance utilisée */
/*------------------------------------------------------------------------------*/
/* (O) Instance : adresse du numéro de l'instance utilisée */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Instance_Get_I( int *Instance)
{
*Instance = SM_Instance;
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Récupération du nom du contexte utilisé */
/*------------------------------------------------------------------------------*/
/* (O) Context : adresse du nom du contexte utilisé */
/*------------------------------------------------------------------------------*/
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ée */
rc = SM_Base_End();
if( rc != SMS_OK)
{
LG_LOG_ERROR_0( "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 été ouverte qu'une seule fois.
*/
if( SM_Open_Counter == 1)
{
/* Fermeture de la base de mémoire partagée */
rc = SM_Base_Close();
if( rc != SMS_OK)
{
LG_LOG_ERROR_0( "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 à 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é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_5( "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_4( "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_0( "");
/* 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_0( "");
/* Affichage des informations de chaque heap */
return( ND_DataStruct_Value_Print( Out, SM_Base->MHR, NDD_RECURSIVE_MODE_PARENT_CHILD, 0, 0));
}
/*------------------------------------------------------------------------------*/
/* Libération de tous les verrous (base, heap) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Unlock_I( void)
{
NDT_Node *Node;
union semun Sem_Ctl;
/* Libération des verrous sur la base */
Sem_Ctl.val = 1;
if( semctl( SM_Base->SemId, 0, SETVAL, Sem_Ctl))
{
LG_LOG_ERROR_0( "Unable to unlock the shared memory base");
return( SMS_ERRSEM);
}
/* Libé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_1( "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è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 éventuel du heap système */
if( Locked == TRUE)
{
SM_Heap_Unlock_I( System_Heap);
}
return( SMS_NO);
}
/*------------------------------------------------------------------------------*/
/* Ouverture/création d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name: nom du heap */
/* (O) Heap_Ptr_Ptr: pointeur sur le heap ouvert / créé */
/* (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à 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é */
rc = SM_Heap_Lock_I( *Heap_Ptr_Ptr, SMD_LOCK_MSK( Open_Mode), Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR_2( "Unable to lock heap: [%s] for: [%s]", Heap_Name, Open_Mode & SMD_READ ? "reading" : "writing");
return( rc);
}
return( SMS_OK);
}
else
{
LG_LOG_ERROR_0( "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à 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_1( "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_1( "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é */
rc = SM_Heap_Lock_I( *Heap_Ptr_Ptr, SMD_LOCK_MSK( Open_Mode), Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR_2( "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_1( "Unable to add heap: [%s] to the opened heap cache", prefixed_name);
goto Error2;
}
return( SMS_OK);
}
else
{
LG_LOG_ERROR_0( "The heap already exists but (Open_Mode & SMD_OPEN) is false");
return( SMS_ERRAPI);
}
}
if( !( Open_Mode & SMD_CREATE))
{
LG_LOG_ERROR_1( "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_0( "Unable to alloc a new MHH structure");
return(SMS_ERRAPI);
}
/* Ajout du nouveau heap à la structure MHR */
rc = ND_DataStruct_Value_Add( SM_Base->MHR, MHH);
if( rc != NDS_OK)
{
LG_LOG_ERROR_0( "Unable to add the new heap to the MHR structure");
goto Error9;
}
/* Verrouillage du nouveau MHH dans le mode demandé */
rc = SM_Heap_Lock_Set( MHH, SMD_LOCK_MSK( Open_Mode));
if( rc != SMS_OK)
{
LG_LOG_ERROR_2( "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_1( "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_1( "Unable to add heap: [%s] to the opened heap cache", prefixed_name);
goto Error11;
}
return( SMS_OK);
/* Gestion d'erreur sur cré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à été 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_1( "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 écriture */
rc = SM_Heap_Lock_I( Heap, SMD_WRITE, &Locked);
}
else
{
/* Ouverture du heap en écriture */
rc = SM_Heap_Open_I( Heap_Name, &Heap, 0, SMD_OPEN | SMD_WRITE, &Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR_0( "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_1( "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_1( "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ées composant le heap
en commencant par le dernier (important pour le heap systè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é (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 à faire : le heap est déjà verrouillé 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_2( "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'était pas : le heap ayant pu être modifié
depuis la dernière fois qu'on y a accédé, il faut procéder à un certain
nombre de vérifications.
*/
/* Vérification de l'état du heap */
if( Heap->MHH->State == SMD_STATE_CORRUPTED)
{
LG_LOG_ERROR_1( "Heap: [%s] is flagged as being corrupted", Heap->Name);
return( SMS_KO);
}
/* Verrouillage du heap dans le mode demandé */
rc = SM_Heap_Lock_Set( Heap->MHH, Lock_Mode);
if( rc != SMS_OK)
{
LG_LOG_ERROR_2( "Unable to lock heap [%s] for: [%s]", Heap->Name, Lock_Mode & SMD_READ ? "reading" : "writing");
return rc;
}
/* Vérification de l'état du heap */
if( Heap->MHH->State == SMD_STATE_UNVALIDATED)
{
/* Verrouillage du heap en é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_1( "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_1( "Unable to check heap: [%s]", Heap->Name);
SM_Heap_Unlock_I( Heap);
return rc;
}
/* On reverrouille éventuellement le heap dans le mode demandé */
if( Lock_Mode == SMD_READ)
{
rc = SM_Heap_Lock_Change( Heap->MHH, SMD_READ);
if( rc != SMS_OK)
{
LG_LOG_ERROR_1( "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_0( "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_0( "Internal Error 2 !");
}
else
{
while( node_ptr)
{
if( ( rc = SM_DataSegment_Open( node_ptr->Value)) != SMS_OK)
{
LG_LOG_ERROR_1( "Unable to open one of the data segments of heap: [%s]",
( (SMT_MHH *)(node_ptr->Value))->Name);
}
else
{
// LG_LOG_ERROR_1( "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 été ajouté depuis la derniè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_1( "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à verrouillé dans un autre mode */
rc = SM_Heap_Lock_Change( Heap->MHH, Lock_Mode);
if( rc != SMS_OK)
{
LG_LOG_ERROR_2( "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_2( LGD_LOG_LEVEL_DEFAULT, "Locked: heap: [%s] lock_mode: (%d)", Heap->Name, Heap->Lock_Mode);
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Libé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_2( "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_2( 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ôle que la limite fixée est inférieure à 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_1( "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_1( "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é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és par adresse.
*/
rc = ND_DataStruct_Reorg (Heap->MHH->FCR);
if( rc != NDS_OK) return( rc);
/* Compression de chaque segment de donné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ées */
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigé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_1( "Checking heap: [%s]", Heap->Name);
if( Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number == 0)
{
LG_LOG_ERROR_1( "Unable to check heap: [%s] which has no data segment", Heap->Name);
( *Nb_Detected) ++;
LG_LOG_INFO_2( "(%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_0( "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_0( "Checking the DSR node structure");
rc = ND_DataStruct_Check (Heap->MHH->DSR, Nb_Detected, Nb_Corrected, Out);
if( rc != NDS_OK)
{
LG_LOG_ERROR_0( "Unable to check the DSR structure");
LG_LOG_INFO_2( "(%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_0( "Please contact an administrator about it");
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
}
LG_LOG_INFO_0( "Trying to open every data segment of the heap");
/* Ouverture des segments du heap au cas ça n'aurait pas été 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_1( "Unable to open one of the data segments of heap: [%s]", Heap->Name);
( *Nb_Detected) ++;
LG_LOG_INFO_2( "(%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_0( "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_0( "Checking the ACR node structure");
rc = ND_DataStruct_Check (Heap->MHH->ACR, Nb_Detected, Nb_Corrected, Out);
if( rc != SMS_OK)
{
LG_LOG_ERROR_0( "SM_Heap_Check : unable to check the ACR node structure");
LG_LOG_INFO_2( "(%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_0( "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_0( "Checking the FCR node structure");
rc = ND_DataStruct_Check (Heap->MHH->FCR, Nb_Detected, Nb_Corrected, Out);
if( rc != SMS_OK)
{
LG_LOG_ERROR_0( "Unable to check the ACR node structure");
LG_LOG_INFO_2( "(%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_0( "Please contact an administrator about it");
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
/* Conclusion de la procédure de vérification */
if( *Nb_Detected > *Nb_Corrected)
{
/* On déclare le heap corrompu afin que plus personne n'y accède */
LG_LOG_INFO_2( "(%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_0( "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_1( "No error detected on heap: [%s] which will be declared as a valid heap", Heap->Name);
}
else
{
LG_LOG_WARNING_2( "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ées alloué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'à ce que la procédure d'allocation soit entièrement terminée.
Ainsi, si celle-ci est interrompue, le heap restera invalide jusqu'à ce qu'il soit
"réparé" (appel de la fonction SM_Heap_Check par la fonction SM_Heap_Open).
*/
Heap->MHH->State = SMD_STATE_UNVALIDATED;
/*
Pour le heap système, tous les chunks alloués ont la même taille (DEFAULT_CHUNK_SIZE).
Ceci facilite notamment la récupération des errors (Recovery) dans le heap système.
Ceci a aussi pour but de simplifier (et donc d'optimiser) l'allocation de nouveaux chunks
dans ce heap système dont la mémoire n'a pas besoin d'être optimisée.
*/
if( Heap == System_Heap) Alloc_Size = DEFAULT_CHUNK_SIZE;
/*
Attention : pour les autres heaps, la taille allouée doit être arrondie à un multiple
de 4 octets (en 32 bits) afin que les adresses des chunks soient aligné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 été trouvé,
alors on crée un nouveau segment de donné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_1( "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_1( "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é un segment de donné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_1( "Unable to remove a chunk from the FCR structure of heap: [%s]", Heap->Name);
return rc;
}
/* Ajout du chunk à la liste des chunks alloués */
rc = ND_Index_Node_Add( Heap->MHH->ACR, NDD_INDEX_PRIMARY, Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR_1( "Unable to add a chunk to the ACR structure of heap: [%s]", Heap->Name);
/* On tente de revenir en arrière */
ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, Node);
return rc;
}
/*
Si le chunk trouvé est plus grand que ce dont on a besoin, alors
on peut cré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éation d'un nouveau chunk libre requiert de la place pour les
données système (SMT_Chunk + NDT_Node) : on ne cré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éation d'un nouveau chunk libre (noeud puis valeur) juste derrière le chunk trouvé */
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_1( "Unable to add a chunk to the FCR structure of heap: [%s]", Heap->Name);
return rc;
}
/* Ajustement du chunk alloué */
Chunk->Size = Alloc_Size;
}
}
/*
Pour une allocation dans le heap système, on anticipe l'ajout
d'un nouveau segment pour éviter de se retrouver bloqué.
Bien entendu, cette opération n'est faite que si l'on n'est
pas déjà en train d'étendre le heap systè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ésentent suffisament de
place pour allouer FREE_CHUNK_LIMIT nouveaux chunks, alors tout est OK.
Dans le cas contraire, il est urgent d'étendre le heap systè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ération.
*/
Adding_Segment = TRUE;
/*
On alloue le noeud du nouveau segment avant de faire appel à la fonction
ND_Value_Alloc pour éviter que ce noeud soit alloué 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é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_0( "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ème */
rc = ND_Index_Node_Add( Heap->MHH->DSR, NDD_INDEX_PRIMARY, New_Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR_0( "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édure d'allocation d'un chunk s'est correctement
terminée, on peut rendre le heap à 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ées du chunk à 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'à ce que la procédure de désallocation soit entièrement terminée.
Ainsi, si celle-ci est interrompue, le heap restera invalide jusqu'à ce qu'il soit
"réparé" (appel de la fonction SM_Heap_Check par la fonction SM_Heap_Open).
*/
Heap->MHH->State = SMD_STATE_UNVALIDATED;
/*
Le noeud du chunk étant adjoint à celui-ci, on n'a pas besoin
de le rechercher dans la liste des chunks alloué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és */
rc = ND_Index_Node_Remove( Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR_1( "Unable to remove the allocated chunk from the ACR structure of heap: [%s]", Heap->Name);
return rc;
}
/* Ajout du chunk à la liste des chunks libres */
rc = ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, Node);
if( rc != NDS_OK)
{
LG_LOG_ERROR_1( "Unable to add the free chunk to the FCR structure of heap: [%s]", Heap->Name);
/* Retour arrière */
ND_Index_Node_Add( Heap->MHH->ACR, NDD_INDEX_PRIMARY, Node);
return rc;
}
/*
Puisque la procédure de désallocation d'un chunk s'est correctement
terminé, on peut rendre le heap à 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_2( "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é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ération du numéro de l'instance utilisée */
/*------------------------------------------------------------------------------*/
/* (O) Instance : adresse du numéro de l'instance utilisée */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Instance_Get_C( int *Instance)
{
return SM_Library_Instance_Get_I( Instance);
}
/*------------------------------------------------------------------------------*/
/* Récupération du nom du contexte utilisé */
/*------------------------------------------------------------------------------*/
/* (O) Context : adresse du nom du contexte utilisé */
/*------------------------------------------------------------------------------*/
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ées */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Dump_C( FILE *Out)
{
SM_LIBSHMEM_OPEN_CHECK();
return SM_Library_Dump_I( Out);
}
/*------------------------------------------------------------------------------*/
/* Libé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éation d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : nom du heap */
/* (O) Heap : pointeur sur le heap ouvert / créé */
/* (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à été 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é (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é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ôle que la limite fixée est inférieure à 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_1( "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_1( "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é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_0( "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ées */
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigé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_0( "The error number pointer is null");
return SMS_ERRAPI;
}
if( !Out)
{
LG_LOG_ERROR_0( "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ées alloué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_0( "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ées du chunk à 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_0( "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è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è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é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_0( "The amount of memory is not sufficient to create a new semaphore");
break;
}
case ENOSPC:
{
break;
}
default:
{
LG_LOG_ERROR_1( "Unknown error: (%d) while creating a semaphore", errno);
break;
}
}
return SMS_ERRSEM;
}
/* Initialisation du sémaphore à 1 (aucun verrou) */
Sem_Ctl.val = 1;
if( semctl( SemId, 0, SETVAL, Sem_Ctl ))
{
LG_LOG_ERROR_1( "Unable to initialize the value of semaphore: (%d)", SemId);
rc = SMS_ERRSEM;
goto Error1;
}
/*
Création d'un segment de mémoire partagée qui contiendra la structure SMT_Base.
Ce segment peut être attaché à 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_1( "The shared memory segment identifier: (%d) already exists", SM_Instance);
break;
}
case EINVAL:
{
LG_LOG_ERROR_1( "The size of the shared memory segment: (%d) is out of the system-imposed bounds", sizeof( SMT_Base));
break;
}
case ENOMEM:
{
LG_LOG_ERROR_0( "The amount of memory is not sufficient to create the shared memory segment");
break;
}
case ENOSPC:
{
LG_LOG_ERROR_0( "The number of shared memory segments exceeds the system-imposed limit");
break;
}
default:
{
LG_LOG_ERROR_1( "Unknown error: (%d) while creating the shared memory segment", errno);
break;
}
}
rc = SMS_ERRSHM;
goto Error1;
}
/* On attache le segment de mémoire partagée au processus courant */
errno = 0;
SM_Base = shmat( SysMemId, 0, 0);
if( errno)
{
LG_LOG_ERROR_1( "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ème n'est pas créé, on est obligé d'allouer de
la mémoire dans le segment de mémoire partagée de la base (fonction SM_Base_Alloc).
Les ressources à allouer (structure MHR + ressources du heap système) sont référencées
par des pointeurs et doivent par conséquent être contenues dans un segment attaché à
une adresse commune à tous les processus.
On crée donc ce segment de mémoire partagé spécifique dont l'adresse d'attachement
sera mémorisée dans la structure SMT_Base.
Pour ce segment de mémoire partagé, on réserve de la place pour :
- la structure du MHR (NDT_Root)
- les ressources du heap système, i.e :
- son noeud (NDT_Node)
- sa structure d'entête ( SMT_MHH)
- sa structure DSR (NDT_Root)
- sa structure ACR (NDT_Root)
- sa structure FCR (NDT_Root)
- son premier segment de données (noeud + entê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_1( "The size of the shared memory segment: (%d) is out of the system-imposed bounds", Size);
break;
case ENOMEM:
LG_LOG_ERROR_0( "The amount of memory is not sufficient to create the shared memory segment");
break;
case ENOSPC:
LG_LOG_ERROR_0( "The number of shared memory segments exceeds the system-imposed limit");
break;
default :
LG_LOG_ERROR_1( "Unknown error: (%d) while creating a shared memory segment", errno);
break;
}
rc = SMS_ERRSHM;
goto Error3;
}
/* Initialisation des informations rattachées à 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ée au processus courant
à une adresse la plus haute possible (MEM_LIMIT) afin d'é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_1( "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é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", 1, &index_type, "MHR_Manager", NULL, SMG_DataStruct_Handlers, TRUE, NULL)) != NDS_OK)
{
LG_LOG_ERROR_0( "Unable to create the MHR structure");
goto Error4;
}
/*
Création d'un premier heap qui constituera le heap système
(l'allocation du MHN, du MHH et des structures DSR, ACR et FCR
sont effectuées dans la base)
*/
rc = SM_Heap_Open_I( HEAP_SYSTEM, &System_Heap, 0, SMD_CREATE, &Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR_0( "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è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ème afin que désormais, les allocations des
nouveaux segments et chunks soient faites dans le segment de
données du heap systè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_0( "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_0( "Unable to unlock the shared memory base");
return rc;
}
/* Verrouillage de la base en écriture */
rc = SM_Base_Lock( SMD_WRITE);
if( rc != SMS_OK)
{
LG_LOG_ERROR_0( "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ème en dernier).
NB : à chaque destruction de heap, la base est verrouillée en é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ème, il faut redéfinir la fonction de
désallocation du MHR, car il a été alloué 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_1( "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_1( "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ée de la base */
if( shmctl( DataMemId, IPC_RMID, 0) == -1 || shmctl( SysMemId, IPC_RMID, 0) == -1)
{
switch( errno)
{
case EPERM:
{
LG_LOG_ERROR_3( "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_2( "No shared memory segment exists for identifier: (%d) or (%d)", SysMemId, DataMemId);
break;
}
default :
{
LG_LOG_ERROR_3( "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_2( "Current process: (%d) is not allowed to destroy semaphore: (%d)", (int)getpid (), SemId);
break;
}
case EINVAL:
{
LG_LOG_ERROR_1( "No semaphore corresponds to the identifier: (%d)", SemId);
break;
}
default:
{
LG_LOG_ERROR_2( "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ération de l'identifiant du segment de mémoire partagée de la base */
MemId = shmget( SM_Instance, 0, 0);
if( MemId == -1)
{
switch( errno)
{
case EACCES:
{
LG_LOG_ERROR_1( "The shared memory segment: (%d) is not accessible to the current process", SM_Instance);
break;
}
case EIDRM:
{
LG_LOG_ERROR_1( "The shared memory segment: (%d) has been deleted", SM_Instance);
break;
}
case ENOENT:
{
LG_LOG_ERROR_1( "No shared memory segment corresponds to the identifier: (%d)", SM_Instance);
break;
}
default:
{
LG_LOG_ERROR_1( "Unknown error: (%d) while retrieving a shared memory segment", errno);
break;
}
}
return SMS_ERRSHM;
}
/* On attache les segments de mémoire partagée de la base */
errno = 0;
SM_Base = shmat( MemId, 0, 0);
if( errno)
{
LG_LOG_ERROR_1( "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_2( "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_0( "Unable to lock the shared memory base for reading");
shmdt( (void *)SM_Base);
SM_Base = NULL;
return rc;
}
/* Ouverture du heap système (sans le verrouiller) */
rc = SM_Heap_Open_I( HEAP_SYSTEM, &System_Heap, 0, SMD_OPEN, &Locked);
if( rc != SMS_OK)
{
LG_LOG_ERROR_0( "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è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é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_0( "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_0( "Unable to lock the library base for writing");
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Libé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_0( "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_0( "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_6( "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_1( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR_1( "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é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_0( "The amount of memory is not sufficient to create a new semaphore");
break;
}
case ENOSPC:
{
LG_LOG_ERROR_0( "The number of semaphores exceeds the system-imposed limit");
break;
}
default:
{
LG_LOG_ERROR_1( "Unknown error: (%d) while creating a semaphore", errno);
break;
}
}
return( NDS_ERRMEM);
}
/* Initialisation du sémaphore à 1 (équivaut à aucun verrou posé) */
Sem_Ctl.val = 1;
if( semctl( SemId, 0, SETVAL, Sem_Ctl))
{
LG_LOG_ERROR_1( "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ème, dans le heap systè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_0( "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éation de la structure DSR :
- dans la base pour le heap système
- dans le heap systè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", 1, &index_type, "SM_DSR_Manager", NULL, SMG_DataStruct_Handlers, TRUE, NULL)) != NDS_OK)
{
LG_LOG_ERROR_0( "Unable to create the DSR structure");
goto Error4;
}
/*
Création de la structure ACR :
- dans la base pour le heap système
- dans le heap systè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", 1, &index_type, "SM_ACR_Manager", NULL, SMG_DataStruct_Handlers, TRUE, NULL)) != NDS_OK)
{
LG_LOG_ERROR_0( "Unable to create the ACR structure");
goto Error5;
}
/*
Création de la structure FCR :
- dans la base pour le heap système
- dans le heap systè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", 1, &index_type, "SM_FCR_Manager", NULL, SMG_DataStruct_Handlers, TRUE, NULL)) != NDS_OK)
{
LG_LOG_ERROR_0( "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_0( "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_0( "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é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ème, on doit procéder de manière spécifique
car le premier segment contient des références sur les autres
segments. Il faut donc supprimer celui-ci en dernier.
Par ailleurs, ce premier segment a été alloué dans la base.
Il faudra donc aussi redé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è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_1( "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_1( "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_1( "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énrencés par les ACR et FCR étaient alloués
dans les segments qui viennent d'être supprimé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_1( "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_1( "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é 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_1( "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_4( "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_1( "Unable to open Heap_Name: [%s] for reading", MHH_Ptr->Name);
return( status);
}
/* TEST !!! */
if( locked != TRUE)
{
LG_LOG_ERROR_1( "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_5( "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_6( "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_4( "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_0( "");
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_1( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR_1( "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ème, on doit procéder de manière spécifique
car le premier segment contient des références sur les autres
segments. Il faut donc supprimer celui-ci en dernier.
Par ailleurs, ce premier segment a été alloué dans la base.
Il faudra donc aussi redé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è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_1( "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_1( "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_1( "Unable to destroy the DSR structure of heap: [%s]", MHH->Name);
}
}
/*
Destruction des structures ACR et FCR.
NB : puisque tous les chunks réfénrencés par les ACR et FCR étaient alloués
dans les segments qui viennent d'être supprimé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_1( "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_1( "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é 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_1( "Unable to free the header of heap: [%s]", MHH->Name);
}
return rc;
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Gestion des segments de donné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_0( "The heap limit size would be exceeded");
*DSH_Ptr_Ptr = NULL;
return( NDS_KO);
}
}
/* Création de l'entê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_0( "Unable to allocate memory for the new data segment header");
return( NDS_KO);
}
/* Création d'un segment de mémoire partagée */
if( ( ( *DSH_Ptr_Ptr)->MemId = shmget (IPC_PRIVATE, Segment_Size, 0777|IPC_CREAT|IPC_EXCL)) == -1)
{
switch( errno)
{
case EINVAL:
{
LG_LOG_ERROR_1( "The size of the shared memory segment: (%d) is out of the system-imposed bounds", Segment_Size);
break;
}
case ENOMEM:
{
LG_LOG_ERROR_0( "The amount of memory is not sufficient to create the shared memory segment");
break;
}
case ENOSPC:
{
LG_LOG_ERROR_0( "The number of shared memory segments exceeds the system-imposed limit");
break;
}
default:
{
LG_LOG_ERROR_1( "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é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_1( "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ête */
( *DSH_Ptr_Ptr)->Size = Segment_Size;
/* Création d'un chunk libre au début du segment de donné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 à 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_1( "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ée du segment de données */
if( shmctl (DSH_Ptr->MemId, IPC_RMID, 0) == -1)
{
switch( errno)
{
case EPERM:
{
LG_LOG_ERROR_2( "Current process: (%d) is not allowed to destroy the shared memory segment: (%d)", (int)getpid (), DSH_Ptr->MemId);
break;
}
case EINVAL:
{
LG_LOG_ERROR_1( "No shared memory segment exists for identifier: (%d)", DSH_Ptr->MemId);
break;
}
default:
{
LG_LOG_ERROR_2( "Unknown error: (%d) while destroying the shared memory segment: (%d)", errno, DSH_Ptr->MemId);
break;
}
}
return SMS_ERRSHM;
}
/* Désallocation de l'entê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_0( "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_3( "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_1( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR_1( "Manager internal error in command: (%d)", Command);
return( NDS_ERRAPI);
}
/*------------------------------------------------------------------------------*/
/* Ouverture d'un segment de données */
/*------------------------------------------------------------------------------*/
SMT_Status SM_DataSegment_Open ( SMT_DSH *DSH)
{
void *Ptr;
/*
On attache le segment de mémoire partagée au processus courant.
Attention : il faut que ce segment soit attaché à la même adresse
que lorsqu'il a été créé 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_2( "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ées */
/*------------------------------------------------------------------------------*/
SMT_Status SM_DataSegment_Close( SMT_DSH *DSH)
{
/* On détache le segment de mémoire partagée du processus courant */
shmdt ( (void *)DSH->Start);
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Compression d'un segment de donné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é" 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és sont triés sur le champ (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_3( "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_1( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR_1( "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
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_3( "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_1( "Manager called with an undefined command: (%d)", Command);
return( NDS_ERRAPI);
}
}
LG_LOG_ERROR_1( "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_1( "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_1( "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 écriture car cela pourrait aboutir à un deadlock entre deux processus
qui voudraient réaliser cette opération en même temps.
=> On passe donc par un déverrouillage intermédiaire.
*/
if( (rc = SM_Semaphore_Operate( MHH->SemId, SM_SemOp_RSL, 2)) != SMS_OK)
{
LG_LOG_ERROR_1( "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_1( "Unable to transform the heap: [%s] lock for writing", MHH->Name);
/* On tente de revenir à l'état de verrouillage précé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_1( "Unable to transform the heap: [%s] lock for reading", MHH->Name);
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Libé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_1( "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_1( "Unable to unlock the heap: [%s] which had been locked for writing", MHH->Name);
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Opé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_0( "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_1( "Current process is not allowed to operate on semaphore: (%d)", SemId);
break;
}
case EIDRM:
{
LG_LOG_ERROR_1( "Semaphore: (%d) does not exist", SemId);
break;
}
case EINTR:
{
LG_LOG_ERROR_1( "A signal was received while operating on semaphore: (%d)", SemId);
return SMS_ERRSIG;
}
case EINVAL:
{
LG_LOG_ERROR_1( "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_1( "The maximum number of process which can operate on semaphore: (%d) in UNDO mode has been reached", SemId);
break;
}
case ERANGE:
{
LG_LOG_ERROR_1( "The value of semaphore: (%d) has reached the system-imposed limit", SemId);
break;
}
default:
{
LG_LOG_ERROR_2( "Unknown error: (%d) while operating on semaphore: (%d)", errno, SemId);
break;
}
}
return SMS_ERRSEM;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Récupère sous forme explicite l'é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);
}