libshmem/lib/libshmem.c
agibert 4cfc687710 Continue LibNode 2.1.x migration,
Lot of bugs fixed,
Now compile,
Managers need a lot of fixes...
2005-01-24 23:10:09 +00:00

4294 lines
126 KiB
C
Raw Blame History

/*---------------------------------------------------------------------------------*/
/* $RCSfile: libshmem.c,v $ */
/*---------------------------------------------------------------------------------*/
/* $Revision: 2.1 $ */
/* $Name: $ */
/* $Date: 2005/01/24 23:10:09 $ */
/* $Author: agibert $ */
/*---------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------*/
/* 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 Licence as published by */
/* the Free Software Foundation; either version 2.1 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, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*---------------------------------------------------------------------------------*/
#define _LIBSHMEM_C_
#include <libshmem.h>
#ifdef _LIBVER_SUPPORT
VER_INFO_EXPORT(libshmem,"$Revision: 2.1 $", "$Name: $",__FILE__,"$Author: agibert $")
#endif
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* FONCTIONS PUBLIQUES */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* FONCTIONS OPTIMISEES (SM_MODE = 1) */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Ouverture d'une instance de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Instance : num<75>ro de l'instance de la librairie */
/* (I) Context : nom du nouveau contexte */
/* (I) Open_Mode : indicateur cr<63>ation/ouverture + mode d'affichage des erreurs */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Open_I( int Instance, const char *Context, SMT_Flags Open_Mode)
{
SMT_Status rc;
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;
/* D<>finition de l'instance <20> ouvrir */
if( Instance) To_Open_Instance = Instance;
else
{
if( !getenv( INSTANCE_ENV_VAR) || ( To_Open_Instance = atoi ( getenv( INSTANCE_ENV_VAR))) <= 0)
{
To_Open_Instance = DEFAULT_INSTANCE;
}
}
if( Open_Mode & SMD_CREATE) /* Cr<43>ation d'une nouvelle instance */
{
/* On v<>rifie que le processus courant n'acc<63>de pas d<>j<EFBFBD> <20> une instance */
if( SM_Open_Counter > 0)
{
sprintf( SM_Error_Msg, "SM_Library_Open : the current process has already opened an instance (%d) of the LIBSHMEM base", SM_Instance);
SM_Error_Print();
return( SMS_ERRAPI);
}
/* Ouverture de la librairie LIBNODE */
rc = ND_Library_Open( ND_Debug);
if( rc != SMS_OK)
{
sprintf( SM_Error_Msg, "SM_Library_Open : unable to open the LIBNODE library");
SM_Error_Print();
return( rc);
}
/* Ouverture de la liste des heaps ouverts (locale) */
rc = ND_DataStruct_Open( &Opened_Heap_List, 1, &index_type, "SM_Opened_Heap_List_Manager", NULL, NULL, NULL, NULL, NULL, TRUE, NULL);
if (rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Library_Open : unable to create the local opened heap cache");
SM_Error_Print();
goto Error1;
}
/* Cr<43>ation de la base de m<>moire partag<61>e */
SM_Instance = To_Open_Instance;
rc = SM_Base_Init();
if( rc != SMS_OK )
{
sprintf( SM_Error_Msg, "SM_Library_Open : unable to initialize the shared memory base");
SM_Error_Print();
goto Error2;
}
}
else if( Open_Mode & SMD_OPEN) /* Ouverture d'une instance existante */
{
/* On v<>rifie que le processus courant n'a pas d<>j<EFBFBD> ouvert une autre instance */
if( SM_Open_Counter > 0 && To_Open_Instance != SM_Instance)
{
sprintf( SM_Error_Msg, "SM_Library_Open : the current process cannot open instance %d because it is already accessing instance %d", To_Open_Instance, SM_Instance);
SM_Error_Print ();
return( SMS_ERRAPI);
}
SM_Instance = To_Open_Instance;
/* Ouverture effective si c'est la premi<6D>re fois */
if( SM_Open_Counter == 0)
{
/* Ouverture de la librairie LIBNODE */
rc = ND_Library_Open( ND_Debug);
if( rc != SMS_OK)
{
sprintf( SM_Error_Msg, "SM_Library_Open : unable to open the LIBNODE library");
SM_Error_Print();
return( rc);
}
/* Ouverture de la liste des heaps ouverts (locale) */
rc = ND_DataStruct_Open( &Opened_Heap_List, 1, &index_type, "SM_Opened_Heap_List_Manager", NULL, NULL, NULL, NULL, NULL, TRUE, NULL);
if( rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Library_Open : unable to create the local opened heap cache");
SM_Error_Print();
goto Error1;
}
/* Ouverture de la base de m<>moire partag<61>e */
rc = SM_Base_Open();
if( rc != SMS_OK )
{
sprintf( SM_Error_Msg, "SM_Library_Open : unable to open the shared memory base");
SM_Error_Print();
goto Error2;
}
}
}
/* D<>finition du contexte */
SM_Library_Context_Set_I( Context);
/* On incr<63>mente le compteur d'ouverture de la librairie */
SM_Open_Counter++;
return( SMS_OK);
/* Gestion d'erreur */
Error2:
ND_DataStruct_Close( Opened_Heap_List);
Error1:
ND_Library_Close();
return( rc);
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>ration du num<75>ro de l'instance utilis<69>e */
/*------------------------------------------------------------------------------*/
/* (O) Instance : adresse du num<75>ro de l'instance utilis<69>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Instance_Get_I( int *Instance)
{
*Instance = SM_Instance;
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>ration du nom du contexte utilis<69> */
/*------------------------------------------------------------------------------*/
/* (O) Context : adresse du nom du contexte utilis<69> */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Context_Get_I ( char **Context)
{
*Context = SM_Context;
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Changement de contexte d'utilisation de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Context : nom du nouveau contexte */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Context_Set_I( const char *Context )
{
if( SM_Context) free( SM_Context);
if( Context && strlen( Context))
{
SM_Context = strdup( Context);
}
else
{
if( getenv( CONTEXT_ENV_VAR) && strlen ( getenv( CONTEXT_ENV_VAR)))
{
SM_Context = strdup (getenv (CONTEXT_ENV_VAR));
}
else
{
SM_Context = strdup (DEFAULT_CONTEXT);
}
}
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Fermeture de l'instance de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Close_Mode : mode de fermeture (destruction ou fermeture simple) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Close_I( SMT_Flags Close_Mode)
{
SMT_Status rc;
if( Close_Mode & SMD_DESTROY) /* Destruction de l'instance */
{
/* Destruction de la base de m<>moire partag<61>e */
rc = SM_Base_End();
if( rc != SMS_OK)
{
sprintf( SM_Error_Msg, "SM_Library_Close: unable to destroy the shared memory base");
SM_Error_Print();
return( rc);
}
if( SM_Context)
{
free( SM_Context);
SM_Context = NULL;
}
/* Fermeture de la liste des heaps ouverts */
ND_DataStruct_Close( Opened_Heap_List);
/* Fermeture de la librairie LIBNODE */
ND_Library_Close();
/* R<>initialisation du compteur d'ouverture */
SM_Open_Counter = 0;
}
else if( Close_Mode & SMD_CLOSE) /* Fermeture de l'instance */
{
/*
La fermeture n'est effective que si la librairie
n'a <20>t<EFBFBD> ouverte qu'une seule fois.
*/
if( SM_Open_Counter == 1)
{
/* Fermeture de la base de m<>moire partag<61>e */
rc = SM_Base_Close();
if( rc != SMS_OK)
{
sprintf( SM_Error_Msg, "SM_Library_Close : unable to close the shared memory base");
SM_Error_Print();
return( rc);
}
if( SM_Context)
{
free( SM_Context);
SM_Context = NULL;
}
/* Fermeture de la liste des heaps ouverts */
ND_DataStruct_Close( Opened_Heap_List);
/* Fermeture de la librairie LIBNODE */
ND_Library_Close();
}
/* On met <20> jour le compteur d'ouverture de la librairie */
SM_Open_Counter--;
}
return( SMS_OK);
}
/*------------------------------------------------------------------------------*/
/* Affichage des informations de la base de m<>moires partag<61>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Dump_I( FILE *Out)
{
/* Affichage des informations sur la base */
fprintf( Out, "Base [%d/%s] :\n\t- Size = %d bytes\n\t- Creator pid = %ld\n\t- Last write access pid = %ld\n\t- ID Mem = %d (+%d)\n\t- ID Sem = %d\n\t- Status = %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));
/* Affichage des informations du MHR */
ND_DataStruct_Info_Print( Out, SM_Base->MHR, NDD_RECURSIVE_MODE_PARENT_CHILD, 0, 0);
fprintf( Out, "\n");
/* Affichage des informations de chaque heap */
return( ND_DataStruct_Value_Print( Out, SM_Base->MHR, NDD_RECURSIVE_MODE_PARENT_CHILD, 0, 0));
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration de tous les verrous (base, heap) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Unlock_I( void)
{
NDT_Node *Node;
union semun Sem_Ctl;
/* Lib<69>ration des verrous sur la base */
Sem_Ctl.val = 1;
if( semctl( SM_Base->SemID, 0, SETVAL, Sem_Ctl))
{
sprintf( SM_Error_Msg, "SM_Library_Free : unable to unlock the shared memory base");
SM_Error_Print();
return( SMS_ERRSEM);
}
/* Lib<69>ration des verrous sur les heaps */
ND_Index_Node_First_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
while( Node)
{
SMT_MHH *MHH;
MHH = (SMT_MHH *)( Node->Value);
if( semctl( MHH->SemID, 0, SETVAL, Sem_Ctl))
{
sprintf( SM_Error_Msg, "SM_Library_Free : unable to unlock heap \"%s\"", MHH->Name);
SM_Error_Print();
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 = SM_Name_Prefix( Heap_Name);
int Locked = FALSE;
if( strcmp( Heap_Name, HEAP_SYSTEM))
{
/* Verrouillage du heap syst<73>me en lecture */
SM_Heap_Lock_I( System_Heap, SMD_READ, &Locked);
}
/* Recherche dans le MHR */
ND_Index_Node_First_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
while( Node)
{
MHH = (SMT_MHH *)( Node->Value);
if (!strcmp( Prefixed_Name, MHH->Name))
{
return( SMS_YES);
}
ND_Index_Node_Next_Get( &Node, Node);
}
/* D<>verrouillage <20>ventuel du heap syst<73>me */
if( Locked == TRUE)
{
SM_Heap_Unlock_I( System_Heap);
}
return( SMS_NO);
}
/*------------------------------------------------------------------------------*/
/* Ouverture/cr<63>ation d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : nom du heap */
/* (O) Heap : pointeur sur le heap ouvert / cr<63><72> */
/* (I) Seg_Size : taille des segments du heap */
/* (I) Open_Mode : mode d'ouverture du heap */
/* (O) Locked : verrou effectif (TRUE ou FALSE) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Open_I( const char *Heap_Name, SMT_Heap **Heap, size_t Seg_Size, SMT_Flags Open_Mode, int *Locked)
{
SMT_MHH *MHH;
NDT_Node *Node;
SMT_DSH *New_DSH;
char *Prefixed_Name;
union semun Sem_Ctl;
int SemID;
SMT_Status rc;
NDT_Index_Type index_type = ( NDD_INDEX_STATUS_OPENED | NDD_INDEX_TYPE_LIST | NDD_INDEX_SUBTYPE_FIFO);
*Locked = FALSE;
/* On regarde si le heap est d<>j<EFBFBD> ouvert par le processus courant */
if( SM_Heap_IsOpen_I( Heap_Name, Heap) == SMS_YES)
{
if( Open_Mode & SMD_OPEN)
{
/* Verrouillage du heap dans le mode demand<6E> */
rc = SM_Heap_Lock_I( *Heap, SMD_LOCK_MSK( Open_Mode), Locked);
if (rc != SMS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to lock heap \"%s\" for %s", Heap_Name, Open_Mode & SMD_READ ? "reading" : "writing");
SM_Error_Print();
return( rc);
}
return( SMS_OK);
}
else
{
sprintf( SM_Error_Msg, "SM_Heap_Open : the heap already exists but (Flags & SMD_OPEN) is false");
SM_Error_Print();
return( SMS_ERRAPI);
}
}
Prefixed_Name = SM_Name_Prefix( Heap_Name);
/* On regarde si le heap existe d<>j<EFBFBD> dans la base */
if( SM_Heap_Exist_I( Heap_Name) == SMS_YES)
{
if( Open_Mode & SMD_OPEN)
{
SMT_MHH To_Find;
/* Ouverture d'un heap existant */
strcpy( To_Find.Name, Prefixed_Name);
ND_Index_Node_Find( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY, &To_Find, NULL);
MHH = (SMT_MHH *)( Node->Value);
*Heap = (SMT_Heap *) malloc( sizeof( SMT_Heap));
if( !*Heap)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to allocate memory for the opened heap \"%s\"", Prefixed_Name);
SM_Error_Print();
return( SMS_ERRMEM);
}
( *Heap)->Name = strdup( Prefixed_Name);
( *Heap)->MHH = MHH;
( *Heap)->Lock_Mode = SMD_NO_LOCK;
/* 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)
{
sprintf (SM_Error_Msg, "SM_Heap_Open : unable to open one of the data segments of heap \"%s\"", Prefixed_Name);
SM_Error_Print ();
goto Error1;
}
ND_Index_Node_Next_Get( &Node, Node);
}
(*Heap)->Nb_Seg = (*Heap)->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
/* Verrouillage du heap dans le mode demand<6E> */
rc = SM_Heap_Lock_I( *Heap, SMD_LOCK_MSK( Open_Mode), Locked);
if( rc != SMS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to lock heap \"%s\" for %s", Prefixed_Name, Open_Mode & SMD_READ ? "reading" : "writing");
SM_Error_Print();
goto Error1;
}
/* Ajout au cache des heaps ouverts */
rc = ND_DataStruct_Value_Add (Opened_Heap_List, *Heap);
if( rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to add heap \"%s\" to the opened heap cache", Prefixed_Name);
SM_Error_Print();
goto Error2;
}
return( SMS_OK);
}
else
{
sprintf( SM_Error_Msg, "SM_Heap_Open : the heap already exists but (Open_Mode & SMD_OPEN) is false");
SM_Error_Print();
return( SMS_ERRAPI);
}
}
if( !( Open_Mode & SMD_CREATE))
{
sprintf( SM_Error_Msg, "SM_Heap_Open : the heap \"%s\" does no exist and (Open_Mode & SMD_CREATE) is false", Prefixed_Name);
SM_Error_Print();
return( SMS_ERRAPI);
}
/* Cr<43>ation du s<>maphore pour g<>rer les verrous sur le nouveau MHH */
SemID = semget( IPC_PRIVATE, 1, 0777 | IPC_CREAT | IPC_EXCL);
if( SemID == -1)
{
switch( errno)
{
case ENOMEM:
{
sprintf( SM_Error_Msg, "SM_Heap_Open : the amount of memory is not sufficient to create a new semaphore");
break;
}
case ENOSPC:
{
sprintf( SM_Error_Msg, "SM_Heap_Open : the number of semaphores exceeds the system-imposed limit");
break;
}
default :
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unknown error (%d) while creating a semaphore", errno);
break;
}
}
SM_Error_Print();
return( SMS_ERRSEM);
}
/* Initialisation du s<>maphore <20> 1 (<28>quivaut <20> aucun verrou pos<6F>) */
Sem_Ctl.val = 1;
if( semctl( SemID, 0, SETVAL, Sem_Ctl))
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to initialize the value of the semaphore %d", SemID);
SM_Error_Print();
rc = SMS_ERRSEM;
goto Error3;
}
/* R<>servation du MHH (dans la base pour le heap syst<73>me, dans le heap syst<73>me pour les autres heaps) */
if( ND_Allocator_Exec( (void **)(&MHH), sizeof( SMT_MHH), SM_Base->MHR->Allocator_Name, SM_Base->MHR->Allocator_Ptr, NULL) != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to allocate memory for the heap header");
SM_Error_Print();
rc = SMS_ERRSHM;
goto Error3;
}
/* Initialisation de la structure du nouveau MHH */
strcpy( MHH->Name, Prefixed_Name);
MHH->Writer = getpid();
MHH->SemID = SemID;
MHH->State = SMD_STATE_UNVALIDATED;
MHH->Segment_Size = ( ( Seg_Size > 0) ? Seg_Size : SEGMENT_DEFAULT_SIZE);
MHH->Limit_Size = SMD_UNLIMITED;
MHH->Auto_Compress = SMD_DEFAULT_COMPRESS;
/*
Cr<43>ation de la structure DSR :
- dans la base pour le heap syst<73>me
- dans le heap syst<73>me pour les autres heaps
*/
rc = ND_DataStruct_Open( &( MHH->DSR), 1, &index_type, "SM_DSR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->Desallocator_Name, NULL, TRUE, NULL);
if (rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to create the DSR structure");
SM_Error_Print();
goto Error4;
}
/*
Cr<43>ation de la structure ACR :
- dans la base pour le heap syst<73>me
- dans le heap syst<73>me pour les autres heaps
*/
rc = ND_DataStruct_Open( &( MHH->ACR), 1, &index_type, "SM_ACR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->Desallocator_Name, NULL, TRUE, NULL);
if (rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to create the ACR structure");
SM_Error_Print();
goto Error5;
}
/*
Cr<43>ation de la structure FCR :
- dans la base pour le heap syst<73>me
- dans le heap syst<73>me pour les autres heaps
*/
rc = ND_DataStruct_Open( &( MHH->FCR), 1, &index_type, "SM_FCR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->Desallocator_Name, NULL, TRUE, NULL);
if( rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to create the FCR structure");
SM_Error_Print();
goto Error6;
}
/* Cr<43>ation d'un premier segment de donn<6E>es */
New_DSH = SM_DataSegment_Init( MHH, MHH->Segment_Size);
if( !New_DSH)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to create a data segment for the new heap");
SM_Error_Print();
rc = SMS_ERRSHM;
goto Error7;
}
rc = ND_DataStruct_Value_Add( MHH->DSR, New_DSH);
if( rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to add a data segment to the DSR structure");
SM_Error_Print();
goto Error8;
}
MHH->State = SMD_STATE_VALID;
/* Ajout du nouveau heap <20> la structure MHR */
rc = ND_DataStruct_Value_Add( SM_Base->MHR, MHH);
if( rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to add the new heap to the MHR structure");
SM_Error_Print();
goto Error9;
}
/* Verrouillage du nouveau MHH dans le mode demand<6E> */
rc = SM_Heap_Lock_Set( MHH, SMD_LOCK_MSK( Open_Mode));
if( rc != SMS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to lock heap \"%s\" for %s",
Prefixed_Name, Open_Mode & SMD_READ ? "reading" : "writing");
SM_Error_Print();
goto Error10;
}
*Locked = TRUE;
/* Ajout du nouveau heap au cache des heaps ouverts */
*Heap = (SMT_Heap *)malloc( sizeof( SMT_Heap));
if( !*Heap)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to allocate memory for a new opened heap \"%s\"", Prefixed_Name);
SM_Error_Print();
rc = SMS_ERRMEM;
goto Error10;
}
( *Heap)->Name = strdup( Prefixed_Name);
( *Heap)->MHH = MHH;
( *Heap)->Lock_Mode = SMD_LOCK_MSK( Open_Mode);
( *Heap)->Nb_Seg = 1;
rc = ND_DataStruct_Value_Add( Opened_Heap_List, *Heap);
if( rc != NDS_OK)
{
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to add heap \"%s\" to the opened heap cache", Prefixed_Name);
SM_Error_Print();
goto Error11;
}
return( SMS_OK);
/* Gestion d'erreur sur cr<63>ation */
Error11:
free( ( *Heap)->Name);
free( *Heap);
*Heap = NULL;
Error10:
ND_DataStruct_Value_Remove( SM_Base->MHR, MHH);
Error9:
ND_DataStruct_Value_Remove( MHH->DSR, New_DSH);
Error8:
SM_DataSegment_End( MHH->DSR, New_DSH);
Error7:
ND_Desallocator_Exec( MHH->FCR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
Error6:
ND_Desallocator_Exec( MHH->ACR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
Error5:
ND_Desallocator_Exec( MHH->DSR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
Error4:
ND_Desallocator_Exec( MHH, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
Error3:
semctl( SemID, 0, IPC_RMID, Sem_Ctl);
return( rc);
/* Gestion d'erreur sur ouverture */
Error2:
SM_Heap_Unlock_I( *Heap);
Error1:
free( (*Heap)->Name);
free( *Heap);
*Heap = NULL;
return( rc);
}
/*------------------------------------------------------------------------------*/
/* Teste si un heap a d<>j<EFBFBD> <20>t<EFBFBD> ouvert par le processus courant */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : Nom du heap */
/* (O) Heap : pointeur sur le heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_IsOpen_I( const char *Heap_Name, SMT_Heap **Heap )
{
SMT_Status rc;
SMT_Heap To_Find;
NDT_Node *Node_Ptr;
*Heap = NULL;
To_Find.Name = SM_Name_Prefix( 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)
{
return( SMS_NO);
}
else
{
*Heap = (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)
{
sprintf (SM_Error_Msg, "SM_Heap_End: heap \"%s\" does not exist", Heap_Name);
SM_Error_Print ();
return SMS_KO;
}
rc = SM_Heap_IsOpen_I (Heap_Name, &Heap);
if (SM_ERROR(rc)) return rc;
if (rc == SMS_YES)
{
/* Verrouillage en <20>criture */
rc = SM_Heap_Lock_I (Heap, SMD_WRITE, &Locked);
}
else
{
/* Ouverture du heap en <20>criture */
rc = SM_Heap_Open_I (Heap_Name, &Heap, 0, SMD_OPEN | SMD_WRITE, &Locked);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_End : unable to open the heap to remove for writing");
SM_Error_Print ();
return rc;
}
}
/* Suppression du heap */
rc = ND_DataStruct_Value_Remove( SM_Base->MHR, Heap->MHH);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_End: unable to remove heap \"%s\" from the MHR structure", Heap_Name);
SM_Error_Print ();
return rc;
}
rc = ND_Value_Free( SM_Base->MHR, Heap->MHH);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_End: unable to free heap \"%s\"", Heap_Name);
SM_Error_Print ();
return rc;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Fermeture d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Close_I ( SMT_Heap * Heap)
{
SMT_Status rc;
NDT_Node * Node;
/*
Fermeture des segments de donn<6E>es composant le heap
en commencant par le dernier (important pour le heap syst<73>me)
*/
ND_Index_Node_Last_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
while (Node)
{
rc = SM_DataSegment_Close (Node->Value);
if (SM_ERROR(rc)) return rc;
ND_Index_Node_Previous_Get( &Node, Node);
}
/* D<>verrouillage du heap */
SM_Heap_Unlock_I (Heap);
/* Suppression du heap de la liste des heaps ouverts */
rc = ND_DataStruct_Value_Remove( Opened_Heap_List, Heap);
if (SM_ERROR(rc)) return rc;
rc = ND_Value_Free( Opened_Heap_List, Heap);
return rc;
}
/*------------------------------------------------------------------------------*/
/* Pose d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Lock_Mode : mode de verrouillage (SMD_READ ou SMD_WRITE) */
/* (O) Locked : verrouillage effectu<74> (TRUE ou FALSE) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_I ( SMT_Heap * Heap, SMT_Flags Lock_Mode, int * Locked )
{
SMT_Status rc;
int Nb_Detected, Nb_Corrected;
if (Lock_Mode == Heap->Lock_Mode)
{
/* Rien <20> faire : le heap est d<>j<EFBFBD> verrouill<6C> dans ce mode */
*Locked = FALSE;
}
else if (Heap->Lock_Mode == SMD_NO_LOCK)
{
/*
Verrouillage d'un heap qui ne l'<27>tait pas : le heap ayant pu <20>tre modifi<66>
depuis la derni<6E>re fois qu'on y a acc<63>d<EFBFBD>, il faut proc<6F>der <20> un certain
nombre de v<>rifications.
*/
/* V<>rification de l'<27>tat du heap */
if (Heap->MHH->State == SMD_STATE_CORRUPTED)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : heap \"%s\" is flagged as being corrupted", Heap->Name);
SM_Error_Print ();
return SMS_KO;
}
/* Verrouillage du heap dans le mode demand<6E> */
rc = SM_Heap_Lock_Set (Heap->MHH, Lock_Mode);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : unable to lock heap \"%s\" for %s", Heap->Name, Lock_Mode & SMD_READ ? "reading" : "writing");
SM_Error_Print ();
return rc;
}
/* V<>rification de l'<27>tat du heap */
if (Heap->MHH->State == SMD_STATE_UNVALIDATED)
{
/* Verrouillage du heap en <20>criture pour le v<>rifier */
if (Lock_Mode == SMD_READ)
{
rc = SM_Heap_Lock_Change (Heap->MHH, SMD_WRITE);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : unable to lock heap \"%s\" for writing before checking", Heap->Name);
SM_Error_Print ();
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)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : unable to check heap \"%s\"", Heap->Name);
SM_Error_Print ();
SM_Heap_Unlock_I (Heap);
return rc;
}
/* On reverrouille <20>ventuellement le heap dans le mode demand<6E> */
if (Lock_Mode == SMD_READ)
{
rc = SM_Heap_Lock_Change (Heap->MHH, SMD_READ);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : unable to lock heap \"%s\" for reading", Heap->Name);
SM_Error_Print ();
SM_Heap_Unlock_I (Heap);
return rc;
}
}
}
/* On v<>rifie qu'aucun nouveau segment n'a <20>t<EFBFBD> ajout<75> depuis la derni<6E>re ouverture */
if (Heap->Nb_Seg != Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number)
{
NDT_Node * Node;
/* On ouvre tous les segments du heap */
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
while (Node)
{
rc = SM_DataSegment_Open (Node->Value);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : unable to open one of the data segments of heap \"%s\"", Heap->Name);
SM_Error_Print ();
SM_Heap_Unlock_I (Heap);
return rc;
}
ND_Index_Node_Next_Get( &Node, Node);
}
Heap->Nb_Seg = Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
}
Heap->Lock_Mode = Lock_Mode;
*Locked = TRUE;
}
else
{
/* Verrouillage du heap qui est d<>j<EFBFBD> verrouill<6C> dans un autre mode */
rc = SM_Heap_Lock_Change (Heap->MHH, Lock_Mode);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : unable to change lock of heap \"%s\" for %s", Heap->Name, Lock_Mode & SMD_READ ? "reading" : "writing");
SM_Error_Print ();
return rc;
}
Heap->Lock_Mode = Lock_Mode;
*Locked = TRUE;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur unheap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Unlock_I ( SMT_Heap * Heap)
{
SMT_Status rc;
rc = SM_Heap_Lock_Release (Heap->MHH, Heap->Lock_Mode);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Unlock : unable to unlock heap \"%s\" for %s",
Heap->Name, Heap->Lock_Mode & SMD_READ ? "reading" : "writing");
SM_Error_Print ();
return rc;
}
Heap->Lock_Mode = SMD_NO_LOCK;
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Configuration d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Tag : type de configuration */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Config_I ( SMT_Heap * Heap, SMT_Config Tag, ... )
{
va_list Arguments;
size_t Size, Current_Size;
SMT_Status rc;
va_start (Arguments, Tag);
switch (Tag)
{
case SMD_AUTO_COMPRESS:
Size = va_arg (Arguments, size_t);
Heap->MHH->Auto_Compress = Size;
break;
case SMD_SEGMENT_SIZE:
Size = va_arg (Arguments, size_t);
Heap->MHH->Segment_Size = Size;
break;
case SMD_HEAP_LIMIT:
Size = va_arg (Arguments, size_t);
Current_Size = 0;
if (Size != SMD_UNLIMITED)
{
/* On contr<74>le que la limite fix<69>e est inf<6E>rieure <20> la taille actuelle du heap */
rc = ND_DataStruct_Traverse (Heap->MHH->DSR, SMD_CMD_VALUE_SUM, (void *)&Current_Size);
if (rc != NDS_OK) return rc;
if (Current_Size > Size)
{
sprintf (SM_Error_Msg, "SM_Heap_Config : the heap has already exceeded the limit size (%d bytes)", Current_Size);
SM_Error_Print ();
va_end (Arguments);
return SMS_ERRAPI;
}
}
Heap->MHH->Limit_Size = Size;
break;
default :
sprintf (SM_Error_Msg, "SM_Heap_Config : unknown config tag %d", Tag);
SM_Error_Print ();
va_end (Arguments);
return SMS_ERRAPI;
}
va_end (Arguments);
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Compression d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (O) Compress : pointeur sur la taille m<>moire gagn<67>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Compress_I ( SMT_Heap * Heap, size_t * Compress)
{
SMT_Status rc;
NDT_Node * Node;
*Compress = 0;
/*
Pour permettre la compression, il faut que les
chunks libres soient tri<72>s par adresse.
*/
rc = ND_DataStruct_Reorg (Heap->MHH->FCR);
if (rc != NDS_OK) return rc;
/* Compression de chaque segment de donn<6E>es du heap */
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
while (Node)
{
*Compress += SM_DataSegment_Compress ((SMT_DSH *)(Node->Value), Heap->MHH->FCR);
ND_Index_Node_Next_Get( &Node, Node);
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* V<>rification/correction des structures d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (O) Nb_Detected : pointeur sur le nombre d'erreurs d<>tect<63>es */
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrig<69>es */
/* (I) Out : pointeur sur le flux de sortie du rapport */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Check_I ( SMT_Heap * Heap, int * Nb_Detected, int * Nb_Corrected, FILE * Out)
{
SMT_Status rc;
NDT_Node * Node;
if (Out) fprintf (Out, "Checking heap \"%s\" ...\n", Heap->Name);
if (Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number == 0)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : unable to check heap \"%s\" which has no data segment", Heap->Name);
SM_Error_Print ();
(*Nb_Detected) ++;
if (Out) fprintf (Out, "%d error(s) could not be corrected in heap \"%s\" which will be declared as corrupted.\n Please contact an administrator about it.\n", *Nb_Detected - *Nb_Corrected, Heap->Name);
Heap->MHH->State = SMD_STATE_CORRUPTED;
return SMS_ERRAPI;
}
else
{
/* V<>rification de la structure DSR du heap */
if (Out) fprintf (Out, "Checking the DSR node structure ...\n");
rc = ND_DataStruct_Check (Heap->MHH->DSR, Nb_Detected, Nb_Corrected, Out);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : unable to check the DSR structure");
SM_Error_Print ();
if (Out) fprintf (Out, "%d error(s) could not be corrected in heap \"%s\" which will be declared as corrupted.\n Please contact an administrator about it.\n", *Nb_Detected - *Nb_Corrected, Heap->Name);
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
}
fprintf (Out, "Trying to open every data segment of the heap ...\n");
/* Ouverture des segments du heap au cas <20>a n'aurait pas <20>t<EFBFBD> fait */
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
while (Node)
{
rc = SM_DataSegment_Open (Node->Value);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : unable to open one of the data segments of heap \"%s\"", Heap->Name);
SM_Error_Print ();
(*Nb_Detected) ++;
if (Out) fprintf (Out, "%d error(s) could not be corrected in heap \"%s\" which will be declared as corrupted.\n Please contact an administrator about it.\n", *Nb_Detected - *Nb_Corrected, Heap->Name);
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
ND_Index_Node_Next_Get( &Node, Node);
}
/* V<>rification de la structure ACR du heap */
if (Out) fprintf (Out, "Checking the ACR node structure ...\n");
rc = ND_DataStruct_Check (Heap->MHH->ACR, Nb_Detected, Nb_Corrected, Out);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : unable to check the ACR node structure");
SM_Error_Print ();
if (Out) fprintf (Out, "%d error(s) could not be corrected in heap \"%s\" which will be declared as corrupted.\n Please contact an administrator about it.\n", *Nb_Detected - *Nb_Corrected, Heap->Name);
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
/* V<>rification de la structure FCR du heap */
if (Out) fprintf (Out, "Checking the FCR node structure ...\n");
rc = ND_DataStruct_Check (Heap->MHH->FCR, Nb_Detected, Nb_Corrected, Out);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : unable to check the ACR node structure");
SM_Error_Print ();
if (Out) fprintf (Out, "%d error(s) could not be corrected in heap \"%s\" which will be declared as corrupted.\n Please contact an administrator about it.\n", *Nb_Detected - *Nb_Corrected, Heap->Name);
Heap->MHH->State = SMD_STATE_CORRUPTED;
return rc;
}
/* Conclusion de la proc<6F>dure de v<>rification */
if (*Nb_Detected > *Nb_Corrected)
{
/* On d<>clare le heap corrompu afin que plus personne n'y acc<63>de */
if (Out) fprintf (Out, "%d error(s) could not be corrected in heap \"%s\" which will be declared as corrupted.\n Please contact an administrator about it.\n", *Nb_Detected - *Nb_Corrected, Heap->Name);
Heap->MHH->State = SMD_STATE_CORRUPTED;
return SMS_KO;
}
/* On rend le heap valide */
if (*Nb_Detected == 0)
{
if (Out) fprintf (Out, "No error detected on heap \"%s\" which will be declared as a valid heap\n", Heap->Name);
}
else
{
if (Out) fprintf (Out, "Every %d error(s) have beeen corrected on heap \"%s\" which will be declared as a valid heap\n", *Nb_Corrected, Heap->Name);
}
Heap->MHH->State = SMD_STATE_VALID;
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Allocation d'un chunk dans un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Size : taille du chunk */
/* (O) Ptr : adresse d'un pointeur sur la zone de donn<6E>es allou<6F>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Chunk_Alloc_I ( SMT_Heap * Heap, size_t Alloc_Size, void ** Ptr )
{
NDT_Node * Node;
SMT_Chunk * Chunk;
SMT_DSH * DSH;
int Found;
size_t Round_Size;
SMT_Status rc;
*Ptr = NULL;
/*
On invalide le heap jusqu'<27> ce que la proc<6F>dure d'allocation soit enti<74>rement termin<69>e.
Ainsi, si celle-ci est interrompue, le heap restera invalide jusqu'<27> ce qu'il soit
"r<>par<61>" (appel de la fonction SM_Heap_Check par la fonction SM_Heap_Open).
*/
Heap->MHH->State = SMD_STATE_UNVALIDATED;
/*
Pour le heap syst<73>me, tous les chunks allou<6F>s ont la m<>me taille (DEFAULT_CHUNK_SIZE).
Ceci facilite notamment la r<>cup<75>ration des errors (Recovery) dans le heap syst<73>me.
Ceci a aussi pour but de simplifier (et donc d'optimiser) l'allocation de nouveaux chunks
dans ce heap syst<73>me dont la m<>moire n'a pas besoin d'<27>tre optimis<69>e.
*/
if (Heap == System_Heap) Alloc_Size = DEFAULT_CHUNK_SIZE;
/*
Attention : pour les autres heaps, la taille allou<6F>e doit <20>tre arrondie <20> un multiple
de 4 octets (en 32 bits) afin que les adresses des chunks soient align<67>es (sinon SIGBUS !).
*/
Round_Size = Alloc_Size % sizeof (void *);
if (Round_Size) Alloc_Size += sizeof (void *) - Round_Size;
/* Recherche d'un chunk suffisamment grand dans la liste des chunks libres */
Found = FALSE;
ND_Index_Node_First_Get( &Node, Heap->MHH->FCR, NDD_INDEX_PRIMARY);
while (Found == FALSE && Node)
{
Chunk = (SMT_Chunk *)(Node->Value);
if (Chunk->Size >= Alloc_Size) Found = TRUE;
else ND_Index_Node_Next_Get( &Node, Node);
}
if (Found == FALSE)
{
/*
Si aucun chunk libre suffisamment grand n'a <20>t<EFBFBD> trouv<75>,
alors on cr<63>e un nouveau segment de donn<6E>es.
*/
size_t Seg_Size;
if (Alloc_Size + sizeof (NDT_Node) + sizeof (SMT_Chunk) > Heap->MHH->Segment_Size)
Seg_Size = Alloc_Size + sizeof (NDT_Node) + sizeof (SMT_Chunk);
else
Seg_Size = Heap->MHH->Segment_Size;
DSH = SM_DataSegment_Init (Heap->MHH, Seg_Size);
if (!DSH)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : unable to create a new data segment for heap \"%s\"", Heap->Name);
SM_Error_Print ();
return SMS_ERRSHM;
}
rc = ND_DataStruct_Value_Add (Heap->MHH->DSR, DSH);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : unable to add a data segment to the DSR structure of heap \"%s\"", Heap->Name);
SM_Error_Print ();
SM_DataSegment_End (Heap->MHH->DSR, DSH);
return rc;
}
/*
Maintenant que l'on a ajout<75> un segment de donn<6E>es, il existe
un chunk libre suffisamment grand au d<>but de ce segment.
*/
Node = (NDT_Node *)DSH->Start;
Chunk = (SMT_Chunk *)(Node->Value);
}
/* Suppression du chunk de la liste des chunks libres */
rc = ND_Index_Node_Remove (Node);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : unable to remove a chunk from the FCR structure of heap \"%s\"", Heap->Name);
SM_Error_Print ();
return rc;
}
/* Ajout du chunk <20> la liste des chunks allou<6F>s */
rc = ND_Index_Node_Add( Heap->MHH->ACR, NDD_INDEX_PRIMARY, Node);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : unable to add a chunk to the ACR structure of heap \"%s\"", Heap->Name);
SM_Error_Print ();
/* On tente de revenir en arri<72>re */
ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, Node);
return rc;
}
/*
Si le chunk trouv<75> est plus grand que ce dont on a besoin, alors
on peut cr<63>er un nouveau chunk libre avec le reliquat de m<>moire.
*/
if (Chunk->Size - Alloc_Size > 0)
{
size_t Remaining_Size = Chunk->Size - Alloc_Size;
/*
La cr<63>ation d'un nouveau chunk libre requiert de la place pour les
donn<6E>es syst<73>me (SMT_Chunk + NDT_Node) : on ne cr<63>e donc un nouveau
chunk libre que si le reliquat est suffisamment important.
*/
if (Remaining_Size > sizeof (SMT_Chunk) + sizeof (NDT_Node))
{
NDT_Node * New_Node;
SMT_Chunk * New_Chunk;
size_t New_Chunk_Size;
/* Cr<43>ation d'un nouveau chunk libre (noeud puis valeur) juste derri<72>re le chunk trouv<75> */
New_Node = (NDT_Node *)((size_t)(Chunk->Data) + Alloc_Size);
New_Chunk = (SMT_Chunk *)((size_t)New_Node + sizeof (NDT_Node) );
New_Chunk_Size = Remaining_Size - sizeof (SMT_Chunk) - sizeof (NDT_Node);
New_Chunk->Size = New_Chunk_Size;
New_Chunk->Data = (void *)((size_t)(New_Chunk) + sizeof (SMT_Chunk) );
New_Node->Root = NULL;
New_Node->Parent = NULL;
New_Node->Left = NULL;
New_Node->Right = NULL;
New_Node->Value = New_Chunk;
rc = ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, New_Node);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : unable to add a chunk to the FCR structure of heap \"%s\"", Heap->Name);
SM_Error_Print ();
return rc;
}
/* Ajustement du chunk allou<6F> */
Chunk->Size = Alloc_Size;
}
}
/*
Pour une allocation dans le heap syst<73>me, on anticipe l'ajout
d'un nouveau segment pour <20>viter de se retrouver bloqu<71>.
Bien entendu, cette op<6F>ration n'est faite que si l'on n'est
pas d<>j<EFBFBD> en train d'<27>tendre le heap syst<73>me (Adding_Segment=TRUE).
*/
if (Heap == System_Heap && Adding_Segment == FALSE)
{
SMT_Chunk * Free_Chunk;
unsigned int Free_Usable_Chunk = 0;
size_t Free_Usable_Size = 0;
int New_Seg_Needed = FALSE;
/* On compte le nombre de chunks libres "utilisables" dans la structure FCR */
ND_Index_Node_First_Get( &Node, Heap->MHH->FCR, NDD_INDEX_PRIMARY);
while (Node)
{
Free_Chunk = Node->Value;
if (Free_Chunk->Size >= DEFAULT_CHUNK_SIZE)
{
Free_Usable_Chunk++;
Free_Usable_Size += Free_Chunk->Size;
}
ND_Index_Node_Next_Get( &Node, Node);
}
/*
S'il reste au moins FREE_CHUNK_LIMIT chunks libres "utilisables"
ou bien si ces chunks libres "utilisables" repr<70>sentent suffisament de
place pour allouer FREE_CHUNK_LIMIT nouveaux chunks, alors tout est OK.
Dans le cas contraire, il est urgent d'<27>tendre le heap syst<73>me.
*/
if (Free_Usable_Chunk < FREE_CHUNK_LIMIT)
{
size_t Needed_Size;
Needed_Size = (size_t)(FREE_CHUNK_LIMIT * DEFAULT_CHUNK_SIZE) + (size_t)(FREE_CHUNK_LIMIT - Free_Usable_Chunk) * (sizeof (NDT_Node) + sizeof (SMT_Chunk));
if (Free_Usable_Size < Needed_Size) New_Seg_Needed = TRUE;
}
if (New_Seg_Needed == TRUE)
{
NDT_Node * New_Node;
/*
Puisque l'ajout d'un nouveau segment va appeler cette m<>me fonction,
on positionne une variable globale pour ne pas recommencer cette op<6F>ration.
*/
Adding_Segment = TRUE;
/*
On alloue le noeud du nouveau segment avant de faire appel <20> la fonction
SM_DataSegment_Init pour <20>viter que ce noeud soit allou<6F> dans le nouveau segment.
*/
SM_System_Alloc( (void **)(&New_Node), sizeof (NDT_Node), NULL);
New_Node->Root = NULL;
New_Node->Parent = NULL;
New_Node->Left = NULL;
New_Node->Right = NULL;
/* On cr<63>e le nouveau segment */
DSH = SM_DataSegment_Init (Heap->MHH, Heap->MHH->Segment_Size);
if (!DSH)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : unable to create un new data segment for the system heap (anticipation)");
SM_Error_Print ();
return SMS_ERRSHM;
}
New_Node->Value = DSH;
/* On ajoute le nouveau segment au heap syst<73>me */
rc = ND_Index_Node_Add( Heap->MHH->DSR, NDD_INDEX_PRIMARY, New_Node);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : unable to add a data segment to the DSR structure of the system heap (anticipation)");
SM_Error_Print ();
SM_DataSegment_End (Heap->MHH->DSR, DSH);
return rc;
}
Adding_Segment = FALSE;
}
}
/*
Puisque la proc<6F>dure d'allocation d'un chunk s'est correctement
termin<69>e, on peut rendre le heap <20> nouveau valide.
*/
Heap->MHH->State = SMD_STATE_VALID;
*Ptr = Chunk->Data;
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* D<>sallocation d'un chunk */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Ptr : pointeur sur la zone de donn<6E>es du chunk <20> d<>sallouer */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Chunk_Free_I ( SMT_Heap * Heap, void * Ptr)
{
NDT_Node * Node;
SMT_Chunk * Chunk;
SMT_Status rc;
/*
On invalide le heap jusqu'<27> ce que la proc<6F>dure de d<>sallocation soit enti<74>rement termin<69>e.
Ainsi, si celle-ci est interrompue, le heap restera invalide jusqu'<27> ce qu'il soit
"r<>par<61>" (appel de la fonction SM_Heap_Check par la fonction SM_Heap_Open).
*/
Heap->MHH->State = SMD_STATE_UNVALIDATED;
/*
Le noeud du chunk <20>tant adjoint <20> celui-ci, on n'a pas besoin
de le rechercher dans la liste des chunks allou<6F>s.
*/
Node = (NDT_Node *)((size_t)Ptr - sizeof (SMT_Chunk) - sizeof (NDT_Node));
Chunk = Node->Value;
/* Suppression du chunk de la liste des chunks allou<6F>s */
rc = ND_Index_Node_Remove (Node);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Chunk_Free : unable to remove the allocated chunk from the ACR structure of heap \"%s\"", Heap->Name);
SM_Error_Print ();
return rc;
}
/* Ajout du chunk <20> la liste des chunks libres */
rc = ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, Node);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Chunk_Free : unable to add the free chunk to the FCR structure of heap \"%s\"", Heap->Name);
SM_Error_Print ();
/* Retour arri<72>re */
ND_Index_Node_Add( Heap->MHH->ACR, NDD_INDEX_PRIMARY, Node);
return rc;
}
/*
Puisque la proc<6F>dure de d<>sallocation d'un chunk s'est correctement
termin<69>, on peut rendre le heap <20> nouveau valide.
*/
Heap->MHH->State = SMD_STATE_VALID;
/* Activation de la compression automatique */
if (Heap->MHH->Auto_Compress != SMD_NO_AUTO_COMPRESS &&
Heap->MHH->FCR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number > Heap->MHH->Auto_Compress)
{
size_t Compress_Size;
rc = SM_Heap_Compress (Heap, &Compress_Size);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Chunk_Free : 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);
SM_Error_Print ();
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* FONCTIONS SECURISEES (SM_MODE = 0) */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Ouverture d'une instance de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Instance : instance de la librairie */
/* (I) Context : nom du nouveau contexte */
/* (I) Open_Mode : indicateur cr<63>ation/ouverture + mode d'affichage des erreurs */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Open_C ( int Instance, const char * Context, SMT_Flags Open_Mode )
{
return SM_Library_Open_I (Instance, Context, Open_Mode);
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>ration du num<75>ro de l'instance utilis<69>e */
/*------------------------------------------------------------------------------*/
/* (O) Instance : adresse du num<75>ro de l'instance utilis<69>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Instance_Get_C ( int * Instance )
{
return SM_Library_Instance_Get_I (Instance);
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>ration du nom du contexte utilis<69> */
/*------------------------------------------------------------------------------*/
/* (O) Context : adresse du nom du contexte utilis<69> */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Context_Get_C ( char ** Context )
{
return SM_Library_Context_Get_I (Context);
}
/*------------------------------------------------------------------------------*/
/* Changement de contexte d'utilisation de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Context : nom du nouveau contexte */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Context_Set_C ( const char * Context )
{
return SM_Library_Context_Set_I (Context);
}
/*------------------------------------------------------------------------------*/
/* Fermeture de l'instance de la librairie */
/*------------------------------------------------------------------------------*/
/* (I) Close_Mode : mode de fermeture (destruction ou fermeture simple) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Close_C ( SMT_Flags Close_Mode )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Library_Close : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Library_Close_I (Close_Mode);
}
/*------------------------------------------------------------------------------*/
/* Affichage des informations de la base de m<>moires partag<61>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Dump_C (FILE * Out)
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Library_Dump : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Library_Dump_I (Out);
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration de tous les verrous (base, heap) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Library_Unlock_C ( void )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Library_Unlock : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
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 )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_Exist : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap_Name)
{
sprintf (SM_Error_Msg, "SM_Heap_Exist : the heap name is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Heap_Exist_I (Heap_Name);
}
/*------------------------------------------------------------------------------*/
/* Ouverture/cr<63>ation d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : nom du heap */
/* (O) Heap : pointeur sur le heap ouvert / cr<63><72> */
/* (I) Seg_Size : taille des segments du heap */
/* (I) Open_Mode : mode d'ouverture du heap */
/* (O) Locked : verrou effectif (TRUE ou FALSE) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Open_C ( const char * Heap_Name, SMT_Heap ** Heap, size_t Seg_Size, SMT_Flags Open_Mode, int * Locked )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_Open : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap_Name)
{
sprintf (SM_Error_Msg, "SM_Heap_Open : the heap name is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Heap_Open_I (Heap_Name, Heap, Seg_Size, Open_Mode, Locked);
}
/*------------------------------------------------------------------------------*/
/* Teste si un heap a d<>j<EFBFBD> <20>t<EFBFBD> ouvert par le processus courant */
/*------------------------------------------------------------------------------*/
/* (I) Heap_Name : Nom du heap */
/* (O) Heap : pointeur sur le heap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_IsOpen_C ( const char * Heap_Name, SMT_Heap ** Heap )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_IsOpen : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap_Name)
{
sprintf (SM_Error_Msg, "SM_Heap_IsOpen : the heap name is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
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 )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_End : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap_Name)
{
sprintf (SM_Error_Msg, "SM_Heap_End : the heap name is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
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 )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_Close : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap)
{
sprintf (SM_Error_Msg, "SM_Heap_Close : the heap is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Heap_Close_I (Heap);
}
/*------------------------------------------------------------------------------*/
/* Pose d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Lock_Mode : mode de verrouillage (SMD_READ ou SMD_WRITE) */
/* (O) Locked : verrouillage effectu<74> (TRUE ou FALSE) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_C ( SMT_Heap * Heap, SMT_Flags Lock_Mode, int * Locked )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock : the heap is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Heap_Lock_I (Heap, Lock_Mode, Locked);
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur unheap ouvert */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Unlock_C ( SMT_Heap * Heap )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_Unlock : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap)
{
sprintf (SM_Error_Msg, "SM_Heap_Unlock : the heap is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Heap_Unlock_I (Heap);
}
/*------------------------------------------------------------------------------*/
/* 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, SMT_Config Tag, ... )
{
va_list Arguments;
size_t Segment_Size, Limit_Size, Current_Size;
SMT_Status rc;
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_Config : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap)
{
sprintf (SM_Error_Msg, "SM_Heap_Config : the heap is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
va_start (Arguments, Tag);
switch (Tag)
{
case SMD_SEGMENT_SIZE:
Segment_Size = va_arg (Arguments, size_t);
Heap->MHH->Segment_Size = Segment_Size;
break;
case SMD_HEAP_LIMIT:
Limit_Size = va_arg (Arguments, size_t);
Current_Size = 0;
if (Limit_Size != SMD_UNLIMITED)
{
/* On contr<74>le que la limite fix<69>e est inf<6E>rieure <20> la taille actuelle du heap */
rc = ND_DataStruct_Traverse (Heap->MHH->DSR, SMD_CMD_VALUE_SUM, (void *)&Current_Size);
if (rc != NDS_OK) return rc;
if (Current_Size > Limit_Size)
{
sprintf (SM_Error_Msg, "SM_Heap_Config : the heap has already exceeded the limit size (%d bytes)", Current_Size);
SM_Error_Print ();
va_end (Arguments);
return SMS_ERRAPI;
}
}
Heap->MHH->Limit_Size = Limit_Size;
break;
default :
sprintf (SM_Error_Msg, "SM_Heap_Config : unknown config tag %d", Tag);
SM_Error_Print ();
va_end (Arguments);
return SMS_ERRAPI;
}
va_end (Arguments);
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Compression d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (O) Compress : pointeur sur la taille m<>moire gagn<67>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Compress_C ( SMT_Heap * Heap, size_t * Compress )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_Compress : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap)
{
sprintf (SM_Error_Msg, "SM_Heap_Compress : the heap is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Compress)
{
sprintf (SM_Error_Msg, "SM_Heap_Compress : the compress size pointer is null");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Heap_Compress_I (Heap, Compress);
}
/*------------------------------------------------------------------------------*/
/* V<>rification/correction des structures d'un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (O) Nb_Detected : pointeur sur le nombre d'erreurs d<>tect<63>es */
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrig<69>es */
/* (I) Out : pointeur sur le flux de sortie du rapport */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Check_C ( SMT_Heap * Heap, int * Nb_Detected, int * Nb_Corrected, FILE * Out )
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : the heap is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Nb_Detected || !Nb_Corrected)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : the error number pointer is null");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Out)
{
sprintf (SM_Error_Msg, "SM_Heap_Check : the out stream is null");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Heap_Check_I (Heap, Nb_Detected, Nb_Corrected, Out);
}
/*------------------------------------------------------------------------------*/
/* Allocation d'un chunk dans un heap */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Size : taille du chunk */
/* (O) Ptr : adresse d'un pointeur sur la zone de donn<6E>es allou<6F>e */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Chunk_Alloc_C ( SMT_Heap * Heap, size_t Alloc_Size, void ** Ptr)
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : the heap is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Ptr)
{
sprintf (SM_Error_Msg, "SM_Chunk_Alloc : the chunk address is null");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Chunk_Alloc_I (Heap, Alloc_Size, Ptr);
}
/*------------------------------------------------------------------------------*/
/* D<>sallocation d'un chunk */
/*------------------------------------------------------------------------------*/
/* (I) Heap : pointeur sur un heap ouvert */
/* (I) Ptr : pointeur sur la zone de donn<6E>es du chunk <20> d<>sallouer */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Chunk_Free_C ( SMT_Heap * Heap, void * Ptr)
{
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Chunk_Free : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Heap)
{
sprintf (SM_Error_Msg, "SM_Chunk_Free : the heap is undefined");
SM_Error_Print ();
return SMS_ERRAPI;
}
if (!Ptr)
{
sprintf (SM_Error_Msg, "SM_Chunk_Free : the chunk pointer is null");
SM_Error_Print ();
return SMS_ERRAPI;
}
return SM_Chunk_Free_I (Heap, Ptr);
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* FONCTIONS PRIVEES */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Allocation de m<>moire dans la base */
/*------------------------------------------------------------------------------*/
NDT_Status SM_Base_Alloc( void **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, void *Data_Ptr)
{
if( !Ptr) return( SMS_ERRAPI);
return( NDS_OK);
}
/*------------------------------------------------------------------------------*/
/* Allocation de m<>moire dans le heap syst<73>me */
/*------------------------------------------------------------------------------*/
NDT_Status SM_System_Alloc( void **Ptr, size_t Size, void *Data_Ptr)
{
return( SM_Chunk_Alloc_I( System_Heap, Size, Ptr));
}
/*------------------------------------------------------------------------------*/
/* D<>sallocation de m<>moire dans le heap syst<73>me */
/*------------------------------------------------------------------------------*/
NDT_Status SM_System_Free( void *Ptr, void *Data_Ptr)
{
return( SM_Chunk_Free_I( System_Heap, Ptr));
}
/*------------------------------------------------------------------------------*/
/* Initialisation de la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Init ( void )
{
SMT_Status rc;
int SemID;
int SysMemID;
int DataMemID;
union semun Sem_Ctl;
size_t Size;
int Locked;
NDT_Index_Type index_type = ( NDD_INDEX_STATUS_OPENED | NDD_INDEX_TYPE_LIST | NDD_INDEX_SUBTYPE_FIFO);
/* Cr<43>ation du s<>maphore pour la gestion des verrous sur la base */
SemID = semget (IPC_PRIVATE, 1, 0777|IPC_CREAT|IPC_EXCL);
if (SemID == -1)
{
switch (errno)
{
case ENOMEM:
sprintf (SM_Error_Msg, "SM_Base_Init : the amount of memory is not sufficient to create a new semaphore");
break;
case ENOSPC:
sprintf (SM_Error_Msg, "SM_Base_Init : the number of semaphores exceeds the system-imposed limit");
break;
default :
sprintf (SM_Error_Msg, "SM_Base_Init : unknown error (%d) while creating a semaphore", errno);
break;
}
SM_Error_Print ();
return SMS_ERRSEM;
}
/* Initialisation du s<>maphore <20> 1 (aucun verrou) */
Sem_Ctl.val = 1;
if (semctl (SemID, 0, SETVAL, Sem_Ctl ))
{
sprintf (SM_Error_Msg, "SM_Base_Init : unable to initialize the value of semaphore %d", SemID);
SM_Error_Print ();
rc = SMS_ERRSEM;
goto Error1;
}
/*
Cr<43>ation d'un segment de m<>moire partag<61>e qui contiendra la structure SMT_Base.
Ce segment peut <20>tre attach<63> <20> n'importe quelle adresse.
*/
SysMemID = shmget (SM_Instance, (int) sizeof (SMT_Base), 0777|IPC_CREAT|IPC_EXCL);
if (SysMemID == -1)
{
switch (errno)
{
case EEXIST:
sprintf (SM_Error_Msg, "SM_Base_Init : the shared memory segment identifier %d already exists", SM_Instance);
break;
case EINVAL:
sprintf (SM_Error_Msg, "SM_Base_Init : the size of the shared memory segment (%d) is out of the system-imposed bounds", sizeof (SMT_Base));
break;
case ENOMEM:
sprintf (SM_Error_Msg, "SM_Base_Init : the amount of memory is not sufficient to create the shared memory segment");
break;
case ENOSPC:
sprintf (SM_Error_Msg, "SM_Base_Init : the number of shared memory segments exceeds the system-imposed limit");
break;
default :
sprintf (SM_Error_Msg, "SM_Base_Init : unknown error (%d) while creating the shared memory segment", errno);
break;
}
SM_Error_Print ();
rc = SMS_ERRSHM;
goto Error1;
}
/* On attache le segment de m<>moire partag<61>e au processus courant */
errno = 0;
SM_Base = shmat (SysMemID, 0, 0);
if (errno)
{
sprintf (SM_Error_Msg, "SM_Base_Init : unable to attach the first shared memory segment to the current process (error %d)", errno);
SM_Error_Print ();
rc = SMS_ERRSHM;
goto Error2;
}
/*
Attention : tant que le heap syst<73>me n'est pas cr<63><72>, on est oblig<69> d'allouer de
la m<>moire dans le segment de m<>moire partag<61>e de la base (fonction SM_Base_Alloc).
Les ressources <20> allouer (structure MHR + ressources du heap syst<73>me) sont r<>f<EFBFBD>renc<6E>es
par des pointeurs et doivent par cons<6E>quent <20>tre contenues dans un segment attach<63> <20>
une adresse commune <20> tous les processus.
On cr<63>e donc ce segment de m<>moire partag<61> sp<73>cifique dont l'adresse d'attachement
sera m<>moris<69>e dans la structure SMT_Base.
Pour ce segment de m<>moire partag<61>, on r<>serve de la place pour :
- la structure du MHR (NDT_Root)
- les ressources du heap syst<73>me, i.e :
- son noeud (NDT_Node)
- sa structure d'ent<6E>te ( SMT_MHH)
- sa structure DSR (NDT_Root)
- sa structure ACR (NDT_Root)
- sa structure FCR (NDT_Root)
- son premier segment de donn<6E>es (noeud + ent<6E>te)
*/
Size = sizeof (NDT_Root) + sizeof (NDT_Node) + sizeof (SMT_MHH) + 3 * sizeof (NDT_Root) + sizeof (NDT_Node) + sizeof (SMT_DSH);
DataMemID = shmget (IPC_PRIVATE, Size, 0777|IPC_CREAT|IPC_EXCL);
if (DataMemID == -1)
{
switch (errno)
{
case EINVAL:
sprintf (SM_Error_Msg, "SM_Base_Init : the size of the shared memory segment (%d) is out of the system-imposed bounds", Size);
break;
case ENOMEM:
sprintf (SM_Error_Msg, "SM_Base_Init : the amount of memory is not sufficient to create the shared memory segment");
break;
case ENOSPC:
sprintf (SM_Error_Msg, "SM_Base_Init : the number of shared memory segments exceeds the system-imposed limit");
break;
default :
sprintf (SM_Error_Msg, "SM_Base_Init : unknown error (%d) while creating a shared memory segment", errno);
break;
}
SM_Error_Print ();
rc = SMS_ERRSHM;
goto Error3;
}
/* Initialisation des informations rattach<63>es <20> la base */
SM_Base->SemID = SemID;
SM_Base->SysMemID = SysMemID;
SM_Base->DataMemID = DataMemID;
SM_Base->Size = Size;
SM_Base->Creator = getpid ();
SM_Base->Writer = SM_Base->Creator;
SM_Base->Attach = (void *)MEM_LIMIT;
SM_Base->MHR = NULL;
/*
On attache le segment de m<>moire partag<61>e au processus courant
<20> une adresse la plus haute possible (MEM_LIMIT) afin d'<27>viter
de d<>border sur la plage d'adressage des symboles.
*/
errno = 0;
SM_Base->Free = shmat (DataMemID, (void *)((size_t)(SM_Base->Attach) - Size), SHM_RND);
if (errno)
{
sprintf (SM_Error_Msg, "SM_Base_Init : unable to attach the second shared memory segment to the current process (error %d)", errno);
SM_Error_Print ();
rc = SMS_ERRSHM;
goto Error4;
}
SM_Base->Attach = SM_Base->Free;
/* Cr<43>ation du MHR dans la base */
rc = ND_DataStruct_Open( &( SM_Base->MHR), 1, &index_type, "MHR_Manager", NULL, "SM_Base_Alloc", NULL, "SM_Base_Free", NULL, TRUE, NULL);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_Init : unable to create the MHR structure");
SM_Error_Print ();
goto Error4;
}
/*
Cr<43>ation d'un premier heap qui constituera le heap syst<73>me
(l'allocation du MHN, du MHH et des structures DSR, ACR et FCR
sont effectu<74>es dans la base)
*/
rc = SM_Heap_Open_I (HEAP_SYSTEM, &System_Heap, 0, SMD_CREATE, &Locked);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_Init : unable to create the system heap");
SM_Error_Print ();
goto Error5;
}
/*
On change les fonctions d'allocation et de d<>sallocation du MHR afin que d<>sormais,
les allocations des nouveaux heaps soient faites dans le heap syst<73>me.
*/
strcpy( SM_Base->MHR->Allocator_Name, "SM_System_Alloc");
strcpy( SM_Base->MHR->Desallocator_Name, "SM_System_Free");
/*
On change les fonctions Allocator et Desallocator du DSR, ACR
et FCR du heap syst<73>me afin que d<>sormais, les allocations des
nouveaux segments et chunks soient faites dans le segment de
donn<6E>es du heap syst<73>me.
*/
strcpy( System_Heap->MHH->DSR->Allocator_Name, "SM_System_Alloc");
strcpy( System_Heap->MHH->DSR->Desallocator_Name, "SM_System_Free");
strcpy( System_Heap->MHH->ACR->Allocator_Name, "SM_System_Alloc");
strcpy( System_Heap->MHH->ACR->Desallocator_Name, "SM_System_Free");
strcpy( System_Heap->MHH->FCR->Allocator_Name, "SM_System_Alloc");
strcpy( System_Heap->MHH->FCR->Desallocator_Name, "SM_System_Free");
/* Verrouillage de la base en lecture */
rc = SM_Base_Lock (SMD_READ);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_Init : unable to lock the shared memory base for reading");
SM_Error_Print ();
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)
{
sprintf (SM_Error_Msg, "SM_Base_End : unable to unlock the shared memory base");
SM_Error_Print ();
return rc;
}
/* Verrouillage de la base en <20>criture */
rc = SM_Base_Lock (SMD_WRITE);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_End : unable to lock the shared memory base for writing");
SM_Error_Print ();
SM_Base_Lock (SMD_READ);
return rc;
}
/*
Destruction de tous les heaps (parcours du MHR en
sens inverse pour d<>truire le heap syst<73>me en dernier).
NB : <20> chaque destruction de heap, la base est verrouill<6C>e en <20>criture
*/
ND_Index_Node_Last_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
while (Node)
{
SMT_MHH * MHH = (SMT_MHH *)(Node->Value);
ND_Index_Node_Previous_Get( &Previous_Node, Node);
/*
Pour la suppression du heap syst<73>me, il faut red<65>finir la fonction de
d<>sallocation du MHR, car il a <20>t<EFBFBD> allou<6F> dans la base (voir SM_Base_Init)
*/
if( !Previous_Node)
{
strcpy( SM_Base->MHR->Desallocator_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)
{
sprintf (SM_Error_Msg, "SM_Base_End : unable to remove heap \"%s\" from the MHR", MHH->Name);
SM_Error_Print ();
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)
{
sprintf (SM_Error_Msg, "SM_Base_End : unable to free heap \"%s\"", MHH->Name);
SM_Error_Print ();
SM_Base_Unlock (SMD_WRITE);
SM_Base_Lock (SMD_READ);
return rc;
}
Node = Previous_Node;
}
SemID = SM_Base->SemID;
SysMemID = SM_Base->SysMemID;
DataMemID = SM_Base->DataMemID;
/* Destruction des segments de m<>moire partag<61>e de la base */
if (shmctl (DataMemID, IPC_RMID, 0) == -1 || shmctl (SysMemID, IPC_RMID, 0) == -1)
{
switch (errno)
{
case EPERM:
sprintf (SM_Error_Msg, "SM_Base_End : current process (%d) is not allowed to destroy the shared memory segment %d or %d", (int)getpid (), SysMemID, DataMemID);
break;
case EINVAL:
sprintf (SM_Error_Msg, "SM_Base_End : no shared memory segment exists for identifier %d or %d", SysMemID, DataMemID);
break;
default :
sprintf (SM_Error_Msg, "SM_Base_End : unknown error (%d) while destroying the shared memory segment %d or %d", errno, SysMemID, DataMemID);
break;
}
SM_Error_Print ();
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:
sprintf (SM_Error_Msg, "SM_Base_End : current process (%d) is not allowed to destroy semaphore %d", (int)getpid (), SemID);
break;
case EINVAL:
sprintf (SM_Error_Msg, "SM_Base_End : no semaphore corresponds to the identifier %d", SemID);
break;
default :
sprintf (SM_Error_Msg, "SM_Base_End : unknown error (%d) while destroying semaphore %d", errno, SemID);
break;
}
SM_Error_Print ();
return SMS_ERRSEM;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Ouverture de la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Open ( void )
{
SMT_Status rc;
void * Ptr;
int MemID;
int Locked;
if (SM_Base) return SMS_OK;
/* R<>cup<75>ration de l'identifiant du segment de m<>moire partag<61>e de la base */
MemID = shmget (SM_Instance, 0, 0);
if (MemID == -1)
{
switch (errno)
{
case EACCES:
sprintf (SM_Error_Msg, "SM_Base_Open : the shared memory segment %d is not accessible to the current process", SM_Instance);
break;
case EIDRM:
sprintf (SM_Error_Msg, "SM_Base_Open : the shared memory segment %d has been deleted", SM_Instance);
break;
case ENOENT:
sprintf (SM_Error_Msg, "SM_Base_Open : no shared memory segment corresponds to the identifier %d", SM_Instance);
break;
default :
sprintf (SM_Error_Msg, "SM_Base_Open : unknown error %d while retrieving a shared memory segment", errno);
break;
}
SM_Error_Print ();
return SMS_ERRSHM;
}
/* On attache les segments de m<>moire partag<61>e de la base */
errno = 0;
SM_Base = shmat (MemID, 0, 0);
if (errno)
{
sprintf (SM_Error_Msg, "SM_Base_Open : unable to attach the shared memory segment to the current process (error %d)", errno);
SM_Error_Print ();
SM_Base = NULL;
return SMS_ERRSHM;
}
errno = 0;
Ptr = shmat (SM_Base->DataMemID, SM_Base->MHR, 0);
if (errno)
{
sprintf (SM_Error_Msg, "SM_Base_Open : unable to attach the shared memory segment to the current process at the specified address %p (error %d)", SM_Base->MHR, errno);
SM_Error_Print ();
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)
{
sprintf (SM_Error_Msg, "SM_Base_Open : unable to lock the shared memory base for reading");
SM_Error_Print ();
shmdt ((void *)SM_Base);
SM_Base = NULL;
return rc;
}
/* Ouverture du heap syst<73>me (sans le verrouiller) */
rc = SM_Heap_Open_I (HEAP_SYSTEM, &System_Heap, 0, SMD_OPEN, &Locked);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_Open : unable to open the system heap");
SM_Error_Print ();
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;
if (!SM_Base)
{
sprintf (SM_Error_Msg, "SM_Base_Close : the LIBSHMEM library is not open");
SM_Error_Print ();
return SMS_ERRAPI;
}
/*
Fermeture de tous les heaps (sans d<>verrouillage) ouverts.
Attention : il faut fermer le heap syst<73>me en dernier.
*/
ND_Index_Node_First_Get( &Node, Opened_Heap_List, NDD_INDEX_PRIMARY);
while (Node)
{
NDT_Node *Next_Node;
ND_Index_Node_Next_Get( &Next_Node, Node);
SM_Heap_Close_I ((SMT_Heap *)(Node->Value));
Node = Next_Node;;
}
/* D<>verrouillage de la base en lecture */
SM_Base_Unlock (SMD_READ);
/* D<>tachement des segments de m<>moire partag<61>e de la base */
shmdt ((void *)SM_Base->MHR);
shmdt ((void *)SM_Base);
SM_Base = NULL;
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Pose d'un verrou sur la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Lock ( SMT_Flags Lock_Mode )
{
SMT_Status rc;
if (Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate (SM_Base->SemID, SM_SemOp_SSL, 2);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_Lock : unable to lock the library base for reading");
SM_Error_Print ();
return rc;
}
}
if (Lock_Mode & SMD_WRITE)
{
rc = SM_Semaphore_Operate (SM_Base->SemID, SM_SemOp_SEL, 2);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_Lock : unable to lock the library base for writing");
SM_Error_Print ();
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration d'un verrou sur la base */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Base_Unlock ( SMT_Flags Lock_Mode )
{
SMT_Status rc;
if (Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate (SM_Base->SemID, SM_SemOp_RSL, 2);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_Unlock : unable to unlock the library base which had been locked for reading");
SM_Error_Print ();
return rc;
}
}
if (Lock_Mode & SMD_WRITE)
{
rc = SM_Semaphore_Operate (SM_Base->SemID, SM_SemOp_REL, 2);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Base_Unlock : unable to unlock the library base which had been locked for writing");
SM_Error_Print ();
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Fonction manager de la liste des heaps ouverts */
/*------------------------------------------------------------------------------*/
NDT_Status SM_Opened_Heap_List_Manager (va_list Args)
{
NDT_Command Command = (NDT_Command)va_arg (Args, NDT_Command);
if (Command == NDD_CMD_VALUE_COMP)
{
SMT_Heap * Heap1, * Heap2;
long comp;
Heap1 = (SMT_Heap *)va_arg (Args, void *);
Heap2 = (SMT_Heap *)va_arg (Args, void *);
va_end (Args);
comp = strcmp (Heap1->Name, Heap2->Name);
if (comp < 0) return NDS_LOWER;
if (comp > 0) return NDS_GREATER;
return NDS_EQUAL;
}
if (Command == NDD_CMD_VALUE_FREE)
{
NDT_Root * Root = va_arg (Args, NDT_Root *);
SMT_Heap * Heap = (SMT_Heap *) va_arg (Args, void *);
free (Heap->Name);
free (Heap);
}
return NDS_OK;
}
/*------------------------------------------------------------------------------*/
/* Fonction manager du MHR (Memory Heap Root) */
/*------------------------------------------------------------------------------*/
NDT_Status MHR_Manager (va_list Args)
{
SMT_Status rc;
NDT_Command Command = (NDT_Command)va_arg (Args, NDT_Command);
if (Command == NDD_CMD_VALUE_PRINT)
{
SMT_MHH * MHH = (SMT_MHH *)va_arg (Args, void *);
FILE * Out = va_arg (Args, FILE *);
size_t Segment_Size;
size_t Alloc_Size;
size_t Free_Size;
int Nb_Segment;
int Nb_Alloc_Chunk;
int Nb_Free_Chunk;
SMT_Heap * Heap;
int Locked;
char * ptr;
/* On n'affiche le heap que s'il fait partie du contexte courant */
ptr = strstr (MHH->Name, SM_Context);
if (ptr) ptr += strlen (SM_Context) + 1;
else if (!strcmp (HEAP_SYSTEM, MHH->Name)) ptr = MHH->Name;
else return SMS_KO;
if (MHH->State == SMD_STATE_CORRUPTED)
{
fprintf (Out, "Heap \"%s\" : *** CORRUPTED *** (checked by process %ld)", MHH->Name, MHH->Writer);
return NDS_OK;
}
rc = SM_Heap_Open_I (ptr, &Heap, 0, SMD_OPEN | SMD_READ, &Locked);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "Error MHR_Manager : unable to open heap \"%s\" for reading", MHH->Name);
SM_Error_Print ();
return rc;
}
Nb_Segment = MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
ND_DataStruct_Traverse (MHH->DSR, SMD_CMD_VALUE_SUM, (void *)&Segment_Size);
Nb_Alloc_Chunk = MHH->ACR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
ND_DataStruct_Traverse (MHH->ACR, SMD_CMD_VALUE_SUM, (void *)&Alloc_Size);
Nb_Free_Chunk = MHH->FCR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
ND_DataStruct_Traverse (MHH->FCR, SMD_CMD_VALUE_SUM, (void *)&Free_Size);
fprintf (Out, "Heap \"%s\" :\n\t- Last write access pid = %ld\n\t- ID Sem = %d\n\t- Status = %s\n\t- Data = %d segment(s) - %d bytes\n\t- Allocated = %d chunk(s) - %d bytes\n\t- Free = %d chunk(s) - %d bytes",
ptr, MHH->Writer, MHH->SemID, SM_Lock_Status_Get ("heap", MHH), Nb_Segment, Segment_Size, Nb_Alloc_Chunk, Alloc_Size, Nb_Free_Chunk, Free_Size);
if (Locked == TRUE) SM_Heap_Unlock_I (Heap);
return NDS_OK;
}
if (Command == NDD_CMD_INFO_PRINT)
{
NDT_Root * Root = va_arg (Args, NDT_Root *);
FILE * Out = va_arg (Args, FILE *);
fprintf (Out, SM_Root_Description_Get ("Memory Heap Root", Root));
return NDS_OK;
}
if (Command == NDD_CMD_VALUE_COMP)
{
SMT_MHH * MHH1, * MHH2;
long comp;
MHH1 = (SMT_MHH *)va_arg (Args, void *);
MHH2 = (SMT_MHH *)va_arg (Args, void *);
va_end (Args);
comp = strcmp (MHH1->Name, MHH2->Name);
if (comp < 0)return NDS_LOWER;
if (comp > 0) return NDS_GREATER;
return NDS_EQUAL;
}
if (Command == NDD_CMD_VALUE_FREE)
{
NDT_Root * Root = va_arg (Args, NDT_Root *);
SMT_MHH * MHH = (SMT_MHH *)va_arg (Args, void *);
return SM_MHH_End (MHH);
}
return NDS_OK;
}
/*------------------------------------------------------------------------------*/
/* Destruction d'un MHH (Memory Heap Header) */
/*------------------------------------------------------------------------------*/
SMT_Status SM_MHH_End ( SMT_MHH * MHH)
{
SMT_Status rc;
SMT_Heap To_Find;
union semun Sem_Ctl;
SMT_Heap * Opened_Heap;
/* Destruction de la structure DSR (et de toutes ses valeurs) */
if (!strcmp (MHH->Name, HEAP_SYSTEM))
{
NDT_Node * Node, * Previous_Node;
SMT_DSH * DSH;
/*
Pour le heap syst<73>me, on doit proc<6F>der de mani<6E>re sp<73>cifique
car le premier segment contient des r<>f<EFBFBD>rences sur les autres
segments. Il faut donc supprimer celui-ci en dernier.
Par ailleurs, ce premier segment a <20>t<EFBFBD> allou<6F> dans la base.
Il faudra donc aussi red<65>finir la fonction de d<>sallocation
du DSR pour celui-ci.
*/
ND_Index_Node_Last_Get( &Node, MHH->DSR, NDD_INDEX_PRIMARY);
while (Node)
{
DSH = (SMT_DSH *)(Node->Value);
ND_Index_Node_Previous_Get( &Previous_Node, Node);
/* S'agit-il du heap syst<73>me ? */
if( !Previous_Node)
{
strcpy( MHH->DSR->Desallocator_Name, "SM_Base_Free");
}
/* Retrait du segment du DSR */
rc = ND_DataStruct_Value_Remove( MHH->DSR, DSH);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_MHH_End : unable to remove the shared memory segment (address=%p) from the DSR structure", DSH->Start);
SM_Error_Print ();
if (SM_ERROR(rc)) return rc;
}
/* Destruction du segment */
rc = ND_Value_Free( MHH->DSR, DSH);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_MHH_End : unable to free the shared memory segment (address=%p)", DSH->Start);
SM_Error_Print ();
if (SM_ERROR(rc)) return rc;
}
Node = Previous_Node;
}
}
else
{
rc = ND_DataStruct_Close (MHH->DSR);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_MHH_End : unable to destroy the DSR structure of heap \"%s\"", MHH->Name);
SM_Error_Print ();
}
}
/*
Destruction des structures ACR et FCR.
NB : puisque tous les chunks r<>f<EFBFBD>nrenc<6E>s par les ACR et FCR <20>taient allou<6F>s
dans les segments qui viennent d'<27>tre supprim<69>s, on se contente de d<>tuire
leur racine.
*/
rc = ND_Desallocator_Exec( MHH->ACR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_MHH_End : unable to free the ACR root of heap \"%s\"", MHH->Name);
SM_Error_Print ();
}
rc = ND_Desallocator_Exec( MHH->FCR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_MHH_End : unable to free the FCR root of heap \"%s\"", MHH->Name);
SM_Error_Print ();
}
/* Suppression du heap de la liste des heaps ouverts */
To_Find.Name = MHH->Name;
rc = ND_DataStruct_Value_Find( (void **)&Opened_Heap, Opened_Heap_List, &To_Find);
if( ( rc == NDS_OK) && ( Opened_Heap != NULL))
{
rc = ND_DataStruct_Value_Remove( Opened_Heap_List, Opened_Heap);
if (rc != NDS_OK)
{
return( rc);
}
else
{
rc = ND_Value_Free( Opened_Heap_List, Opened_Heap);
if( rc != NDS_OK)
{
return( rc);
}
}
}
/* Destruction du s<>maphore attach<63> au heap */
semctl (MHH->SemID, 0, IPC_RMID, Sem_Ctl);
/* D<>sallocation de la structure du MHH */
rc = ND_Desallocator_Exec( MHH, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_MHH_End : unable to free the header of heap \"%s\"", MHH->Name);
SM_Error_Print ();
}
return rc;
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Gestion des segments de donn<6E>es */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Fonction manager pour un DSR (Data Segment Root) */
/*------------------------------------------------------------------------------*/
NDT_Status SM_DSR_Manager (va_list Args)
{
NDT_Command Command = (NDT_Command)va_arg (Args, NDT_Command);
if (Command == SMD_CMD_VALUE_SUM)
{
SMT_DSH * DSH = (SMT_DSH *)va_arg (Args, void *);
int * Total_Size = (int *)va_arg (Args, int *);
(*Total_Size) += DSH->Size;
return NDS_OK;
}
if (Command == NDD_CMD_VALUE_PRINT)
{
SMT_DSH * DSH = (SMT_DSH *)va_arg (Args, void *);
FILE * Out = va_arg (Args, FILE *);
fprintf (Out, "Data Segment Header :\n\t- ID Mem = %d\n\t- Start = %p\n\t- Size = %d bytes",
DSH->MemID, DSH->Start, DSH->Size);
return NDS_OK;
}
if (Command == NDD_CMD_INFO_PRINT)
{
NDT_Root * Root = Root = va_arg (Args, NDT_Root *);
FILE * Out = va_arg (Args, FILE *);
fprintf (Out, SM_Root_Description_Get ("Data Segment Root", Root));
return NDS_OK;
}
if (Command == NDD_CMD_VALUE_COMP)
{
int comp;
SMT_DSH * DSH1 = (SMT_DSH *)va_arg (Args, void *);
SMT_DSH * DSH2 = (SMT_DSH *)va_arg (Args, void *);
va_end (Args);
comp = (unsigned int)DSH1 - (unsigned int)DSH2;
if (comp < 0) return NDS_LOWER;
if (comp > 0) return NDS_GREATER;
return NDS_EQUAL;
}
if (Command == NDD_CMD_VALUE_FREE)
{
NDT_Root * Root = va_arg (Args, NDT_Root *);
SMT_DSH * DSH = (SMT_DSH *)va_arg (Args, void *);
return SM_DataSegment_End (Root, DSH);
}
return NDS_OK;
}
/*------------------------------------------------------------------------------*/
/* Cr<43>ation d'un nouveau segment de donn<6E>es */
/*------------------------------------------------------------------------------*/
SMT_DSH * SM_DataSegment_Init ( SMT_MHH * MHH, size_t Segment_Size)
{
SMT_DSH * New_DSH;
NDT_Node * Chunk_Node;
SMT_Chunk * Chunk;
/* On v<>rifie que le heap n'atteint pas sa limite */
if (MHH->Limit_Size != SMD_UNLIMITED)
{
size_t Current_Size;
ND_DataStruct_Traverse (MHH->DSR, SMD_CMD_VALUE_SUM, (void *)&Current_Size);
if (Current_Size + Segment_Size > MHH->Limit_Size)
{
sprintf (SM_Error_Msg, "SM_DataSegment_Init : the heap limit size would be exceeded");
SM_Error_Print ();
return NULL;
}
}
/* Cr<43>ation de l'ent<6E>te */
if( ND_Allocator_Exec( (void **)(&New_DSH), sizeof (SMT_DSH), MHH->DSR->Allocator_Name, MHH->DSR->Allocator_Ptr, NULL) != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_DataSegment_Init : unable to allocate memory for the new data segment header");
SM_Error_Print ();
return NULL;
}
/* Cr<43>ation d'un segment de m<>moire partag<61>e */
if ((New_DSH->MemID = shmget (IPC_PRIVATE, Segment_Size, 0777|IPC_CREAT|IPC_EXCL)) == -1)
{
switch (errno)
{
case EINVAL:
sprintf (SM_Error_Msg, "SM_DataSegment_Init : the size of the shared memory segment (%d) is out of the system-imposed bounds", Segment_Size);
break;
case ENOMEM:
sprintf (SM_Error_Msg, "SM_DataSegment_Init : the amount of memory is not sufficient to create the shared memory segment");
break;
case ENOSPC:
sprintf (SM_Error_Msg, "SM_DataSegment_Init : the number of shared memory segments exceeds the system-imposed limit");
break;
default :
sprintf (SM_Error_Msg, "SM_DataSegment_Init : unknown error (%d) while creating a shared memory segment", errno);
break;
}
SM_Error_Print ();
ND_Desallocator_Exec( New_DSH, MHH->DSR->Desallocator_Name, MHH->DSR->Desallocator_Ptr, NULL);
return NULL;
}
/* On attache le segment de m<>moire partag<61>e au processus courant */
errno = 0;
New_DSH->Start = shmat (New_DSH->MemID, (void *)((size_t)(SM_Base->Attach) - Segment_Size), SHM_RND);
if (errno)
{
sprintf (SM_Error_Msg, "SM_DataSegment_Init : unable to attach the shared memory segment to the current process (error %d)", errno);
SM_Error_Print ();
shmctl (New_DSH->MemID, IPC_RMID, 0);
ND_Desallocator_Exec( New_DSH, MHH->DSR->Desallocator_Name, MHH->DSR->Desallocator_Ptr, NULL);
return NULL;
}
SM_Base->Attach = New_DSH->Start;
/* Initialisation des informations de l'ent<6E>te */
New_DSH->Size = Segment_Size;
/* Cr<43>ation d'un chunk libre au d<>but du segment de donn<6E>es */
Chunk_Node = (NDT_Node *)New_DSH->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 = New_DSH->Size - sizeof (NDT_Node) - sizeof (SMT_Chunk);
/* Ajout du chunk libre <20> la liste des chunks libres du heap */
if (ND_Index_Node_Add( MHH->FCR, NDD_INDEX_PRIMARY, Chunk_Node) != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_DataSegment_Init : unable to add a first chunk to the FCR structure of heap \"%s\"", MHH->Name);
SM_Error_Print ();
shmctl (New_DSH->MemID, IPC_RMID, 0);
ND_Desallocator_Exec( New_DSH, MHH->DSR->Desallocator_Name, MHH->DSR->Desallocator_Ptr, NULL);
return NULL;
}
return New_DSH;
}
/*------------------------------------------------------------------------------*/
/* Terminaison d'un segment de donn<6E>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_DataSegment_End (NDT_Root * Root, SMT_DSH *DSH)
{
SMT_Status rc;
/* Destruction du segment de m<>moire partag<61>e du segment de donn<6E>es */
if (shmctl (DSH->MemID, IPC_RMID, 0) == -1)
{
switch (errno)
{
case EPERM:
sprintf (SM_Error_Msg, "SM_DataSegment_End : current process (%d) is not allowed to destroy the shared memory segment %d", (int)getpid (), DSH->MemID);
break;
case EINVAL:
sprintf (SM_Error_Msg, "SM_DataSegment_End : no shared memory segment exists for identifier %d", DSH->MemID);
break;
default :
sprintf (SM_Error_Msg, "SM_DataSegment_End : unknown error %d while destroying the shared memory segment %d", errno, DSH->MemID);
break;
}
SM_Error_Print ();
return SMS_ERRSHM;
}
/* D<>sallocation de l'ent<6E>te */
rc = ND_Desallocator_Exec( DSH, Root->Desallocator_Name, Root->Desallocator_Ptr, NULL);
if (rc != NDS_OK)
{
sprintf (SM_Error_Msg, "SM_DataSegment_End : the data segment header is nul");
SM_Error_Print ();
return rc;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Ouverture d'un segment de donn<6E>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_DataSegment_Open ( SMT_DSH *DSH)
{
void *Ptr;
/*
On attache le segment de m<>moire partag<61>e au processus courant.
Attention : il faut que ce segment soit attach<63> <20> la m<>me adresse
que lorsqu'il a <20>t<EFBFBD> cr<63><72> afin que les pointeurs qui pointent dans
ce segment soient valides.
*/
shmdt ((void *)DSH->Start);
errno = 0;
Ptr = shmat (DSH->MemID, DSH->Start, 0);
if (errno)
{
sprintf (SM_Error_Msg, "SM_DataSegment_Open : unable to attach the shared memory segment at the specified address %p (error %d)", DSH->Start, errno);
SM_Error_Print ();
return SMS_ERRSHM;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Fermeture d'un segment de donn<6E>es */
/*------------------------------------------------------------------------------*/
SMT_Status SM_DataSegment_Close ( SMT_DSH *DSH)
{
/* On d<>tache le segment de m<>moire partag<61>e du processus courant */
shmdt ((void *)DSH->Start);
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Compression d'un segment de donn<6E>es */
/*------------------------------------------------------------------------------*/
size_t SM_DataSegment_Compress ( SMT_DSH *DSH, NDT_Root *FCR)
{
size_t Total_Compress = 0;
size_t Compress;
SMT_Chunk *Chunk, *Next_Chunk;
NDT_Node * Node, *Next_Node;
void *DSH_End;
int Found = FALSE;
DSH_End = (void *)((size_t)(DSH->Start) + DSH->Size);
/* Recherche du premier chunk libre contenu dans le segment courant */
ND_Index_Node_First_Get( &Node, FCR, NDD_INDEX_PRIMARY);
while (Found == FALSE && Node)
{
if (Node > (NDT_Node *)DSH_End) Node = NULL;
else
{
if (Node >= (NDT_Node *)(DSH->Start)) Found = TRUE;
else ND_Index_Node_Next_Get( &Node, Node);
}
}
if (!Node) return 0;
/* Parcours de tous les chunks libres du segment courant */
ND_Index_Node_Next_Get( &Next_Node, Node);
while (Next_Node && (void *)Next_Node < DSH_End)
{
Chunk = (SMT_Chunk *)(Node->Value);
Next_Chunk = (SMT_Chunk *)(Next_Node->Value);
/* Si le chunk suivant est "coll<6C>" au chunk courant, alors on les fusionne */
if (Next_Node == (NDT_Node *)((size_t)(Chunk->Data) + Chunk->Size))
{
ND_Index_Node_Remove (Next_Node);
Compress = sizeof (SMT_Chunk) + sizeof (NDT_Node);
Chunk->Size += Next_Chunk->Size + Compress;
Total_Compress += Compress;
ND_Index_Node_Next_Get( &Next_Node, Node);
}
else
{
Node = Next_Node;
ND_Index_Node_Next_Get( &Next_Node, Next_Node);
}
}
return Total_Compress;
}
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Fonction de gestion de chunks */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* Fonction manager pour un ACR (Allocated Chunk Root) */
/*------------------------------------------------------------------------------*/
NDT_Status SM_ACR_Manager (va_list Args)
{
NDT_Command Command = (NDT_Command)va_arg (Args, NDT_Command);
if (Command == SMD_CMD_VALUE_SUM)
{
SMT_Chunk * Chunk = (SMT_Chunk *)va_arg (Args, void *);
int * Total_Size = (int *)va_arg (Args, int *);
(*Total_Size) += Chunk->Size;
return NDS_OK;
}
if (Command == NDD_CMD_VALUE_PRINT)
{
SMT_Chunk *Chunk = (SMT_Chunk *)va_arg (Args, void *);
FILE * Out = va_arg (Args, FILE *);
fprintf (Out, "Allocated chunk :\n\t- Size = %d\n\t- Data = %p", Chunk->Size, Chunk->Data);
return NDS_OK;
}
if (Command == NDD_CMD_INFO_PRINT)
{
NDT_Root * Root = va_arg (Args, NDT_Root *);
FILE * Out = va_arg (Args, FILE *);
fprintf (Out, SM_Root_Description_Get ("Allocated Chunk Root", Root));
return NDS_OK;
}
if (Command == NDD_CMD_VALUE_COMP)
{
int comp;
SMT_Chunk *Chunk1 = (SMT_Chunk *)va_arg (Args, void *);
SMT_Chunk *Chunk2 = (SMT_Chunk *)va_arg (Args, void *);
va_end (Args);
/* Les chunks allou<6F>s sont tri<72>s sur le champ <Data> (adresse d'allocation) */
comp = (unsigned int)Chunk1->Data - (unsigned int)Chunk2->Data;
if (comp < 0) return NDS_LOWER;
if (comp > 0) return NDS_GREATER;
return NDS_EQUAL;
}
return NDS_OK;
}
/*------------------------------------------------------------------------------*/
/* Fonction manager pour un FCR (Free Chunk Root) */
/*------------------------------------------------------------------------------*/
NDT_Status SM_FCR_Manager (va_list Args)
{
NDT_Command Command = (NDT_Command)va_arg (Args, NDT_Command);
if (Command == SMD_CMD_VALUE_SUM)
{
SMT_Chunk * Chunk = (SMT_Chunk *)va_arg (Args, void *);
int * Total_Size = (int *)va_arg (Args, int *);
(*Total_Size) += Chunk->Size;
return NDS_OK;
}
if (Command == NDD_CMD_VALUE_PRINT)
{
SMT_Chunk * Chunk = (SMT_Chunk *)va_arg (Args, void *);
FILE * Out = va_arg (Args, FILE *);
fprintf (Out, "Free Chunk :\n\t- Size = %d\n\t- Data = %p", Chunk->Size, Chunk->Data);
return NDS_OK;
}
if (Command == NDD_CMD_INFO_PRINT)
{
NDT_Root * Root = va_arg (Args, NDT_Root *);
FILE * Out = va_arg (Args, FILE *);
fprintf (Out, SM_Root_Description_Get ("Free Chunk Root", Root));
return NDS_OK;
}
if (Command == NDD_CMD_VALUE_COMP)
{
int comp;
SMT_Chunk *Chunk1 = (SMT_Chunk *)va_arg (Args, void *);
SMT_Chunk *Chunk2 = (SMT_Chunk *)va_arg (Args, void *);
va_end (Args);
/*
La comparaison des chunks libres porte sur le champ <Data>
pour faciliter la compression des heaps.
*/
comp = (unsigned int)(Chunk1->Data) - (unsigned int)(Chunk2->Data);
if (comp < 0) return NDS_LOWER;
if (comp > 0) return NDS_GREATER;
return NDS_EQUAL;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* 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)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock_Set : unable to lock the heap for reading");
SM_Error_Print ();
return rc;
}
}
if (Lock_Mode & SMD_WRITE)
{
rc = SM_Semaphore_Operate (MHH->SemID, SM_SemOp_SEL, 2);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock_Set : unable to lock the heap for writing");
SM_Error_Print ();
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Changement d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_Change ( SMT_MHH * MHH, SMT_Flags Lock_Mode )
{
SMT_Status rc;
if (Lock_Mode & SMD_WRITE)
{
/*
Attention : il ne faut pas tenter de transformer directement un verrou en lecture en
un verrou en <20>criture car cela pourrait aboutir <20> un deadlock entre deux processus
qui voudraient r<>aliser cette op<6F>ration en m<>me temps.
=> On passe donc par un d<>verrouillage interm<72>diaire.
*/
if ((rc = SM_Semaphore_Operate (MHH->SemID, SM_SemOp_RSL, 2)) != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock_Change : unable to transform the heap lock for writing");
SM_Error_Print ();
return rc;
}
if ((rc = SM_Semaphore_Operate (MHH->SemID, SM_SemOp_SEL, 2)) != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock_Change : unable to transform the heap lock for writing");
SM_Error_Print ();
/* On tente de revenir <20> l'<27>tat de verrouillage pr<70>c<EFBFBD>dent */
SM_Semaphore_Operate (MHH->SemID, SM_SemOp_SSL, 2);
return rc;
}
}
else if (Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate (MHH->SemID, SM_SemOp_TSL, 2);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock_Change : unable to transform the heap lock for reading");
SM_Error_Print ();
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Lib<69>ration d'un verrou sur un heap */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Heap_Lock_Release ( SMT_MHH * MHH, SMT_Flags Lock_Mode )
{
SMT_Status rc;
if (Lock_Mode & SMD_READ)
{
rc = SM_Semaphore_Operate (MHH->SemID, SM_SemOp_RSL, 2);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock_Release : unable to unlock the heap which had been locked for reading");
SM_Error_Print ();
return rc;
}
}
if (Lock_Mode & SMD_WRITE)
{
rc = SM_Semaphore_Operate (MHH->SemID, SM_SemOp_REL, 2);
if (rc != SMS_OK)
{
sprintf (SM_Error_Msg, "SM_Heap_Lock_Release : unable to unlock the heap which had been locked for writing");
SM_Error_Print ();
return rc;
}
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* Op<4F>ration sur un s<>maphore */
/*------------------------------------------------------------------------------*/
SMT_Status SM_Semaphore_Operate (int SemID, struct sembuf * Operations, unsigned int Nb_Oper)
{
if (semop (SemID, Operations, Nb_Oper) == -1)
{
switch (errno)
{
case EAGAIN:
sprintf (SM_Error_Msg, "SM_Semaphore_Operate : the operation would result in suspension of the calling process but the operations have been defined in no wait mode");
return SMS_NO_WAIT;
break;
case EACCES:
sprintf (SM_Error_Msg, "SM_Semaphore_Operate : current process is not allowed to operate on semaphore %d", SemID);
break;
case EIDRM:
sprintf (SM_Error_Msg, "SM_Semaphore_Operate : semaphore %d does not exist", SemID);
break;
case EINTR:
sprintf (SM_Error_Msg, "SM_Semaphore_Operate : a signal was received while operating on semaphore %d", SemID);
return SMS_ERRSIG;
break;
case EINVAL:
sprintf (SM_Error_Msg, "SM_Semaphore_Operate : 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:
sprintf (SM_Error_Msg, "SM_Semaphore_Operate : the maximum number of process which can operate on semaphore in UNDO mode has been reached");
break;
case ERANGE:
sprintf (SM_Error_Msg, "SM_Semaphore_Operate: the value of semaphore %d has reached the system-imposed limit", SemID);
break;
default :
sprintf (SM_Error_Msg, "SM_Semaphore_Operate : unknown error %d while operating on semaphore %d", errno, SemID);
break;
}
SM_Error_Print ();
return SMS_ERRSEM;
}
return SMS_OK;
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>re sous forme explicite l'<27>tat d'un verrou */
/*------------------------------------------------------------------------------*/
char * SM_Lock_Status_Get ( const char * Type, void * Struct)
{
static char Status [50];
int i, SemID;
pid_t Writer;
union semun Sem_Ctl;
if (!strcmp (Type, "base"))
{
SemID = SM_Base->SemID;
Writer = SM_Base->Writer;
}
else if (!strcmp (Type, "heap"))
{
SMT_MHH * MHH = (SMT_MHH *)Struct;
SemID = MHH->SemID;
Writer = MHH->Writer;
}
else
{
strcpy (Status, "unknown");
return Status;
}
i = semctl (SemID, 0, GETVAL, Sem_Ctl);
switch (i)
{
case 0:
sprintf (Status, "exclusive lock (process id = %ld)", Writer);
break;
case 1:
sprintf (Status, "unlocked");
break;
default :
if (i < 0)
sprintf (Status, "anormal status (%d)", i);
else
sprintf (Status, "share lock (%d process)", i - 1);
break;
}
return Status;
}
/*------------------------------------------------------------------------------*/
/* R<>cup<75>re sous forme explicite la description d'une racine de structure */
/*------------------------------------------------------------------------------*/
char * SM_Root_Description_Get ( const char * Root_Label, NDT_Root * Root )
{
static char Root_Info [256];
sprintf (Root_Info, "%s :\n\t- Structure type = %s:%s\n\t- Node number = %ld\n",
Root_Label,
ND_INDEX_TYPE_ASCII_GET( Root, NDD_INDEX_PRIMARY),
ND_INDEX_SUBTYPE_ASCII_GET( Root, NDD_INDEX_PRIMARY),
Root->Index_Tab[NDD_INDEX_PRIMARY].Node_Number);
return( Root_Info);
}
/*------------------------------------------------------------------------------*/
/* Routine d'affichage d'un message d'erreur */
/*------------------------------------------------------------------------------*/
void SM_Error_Print ( void )
{
if (SM_stderr) fprintf (SM_stderr, "Error %s\n", SM_Error_Msg);
}
/*------------------------------------------------------------------------------*/
/* Pour pr<70>fixer un nom de heap avec le nom du contexte d'utilisation */
/*------------------------------------------------------------------------------*/
static char * SM_Name_Prefix ( const char * Name)
{
static char Prefixed [256];
if (!SM_Context || !strlen (SM_Context) || !strcmp (Name, HEAP_SYSTEM))
strcpy (Prefixed, Name);
else
sprintf (Prefixed, "%s/%s", SM_Context, Name);
return Prefixed;
}