5438 lines
171 KiB
C
5438 lines
171 KiB
C
/*---------------------------------------------------------------------------------*/
|
|
/* $RCSfile: libshmem.c,v $ */
|
|
/*---------------------------------------------------------------------------------*/
|
|
/* $Revision: 2.4 $ */
|
|
/* $Name: $ */
|
|
/* $Date: 2005/06/26 23:40:14 $ */
|
|
/* $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.4 $", "$Name: $",__FILE__,"$Author: agibert $")
|
|
#endif
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
/* FONCTIONS PUBLIQUES */
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* FONCTIONS OPTIMISEES (SM_MODE = 1) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ouverture d'une instance de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Instance : numéro de l'instance de la librairie */
|
|
/* (I) Context : nom du nouveau contexte */
|
|
/* (I) Open_Mode : indicateur création/ouverture + mode d'affichage des erreurs */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Open_I( int Instance, const char *Context, SMT_Flags Open_Mode)
|
|
{
|
|
SMT_Status rc;
|
|
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 à ouvrir */
|
|
|
|
if( Instance) To_Open_Instance = Instance;
|
|
else
|
|
{
|
|
if( !getenv( INSTANCE_ENV_VAR) || ( To_Open_Instance = atoi ( getenv( INSTANCE_ENV_VAR))) <= 0)
|
|
{
|
|
To_Open_Instance = DEFAULT_INSTANCE;
|
|
}
|
|
}
|
|
|
|
if( Open_Mode & SMD_CREATE) /* Création d'une nouvelle instance */
|
|
{
|
|
/* On vérifie que le processus courant n'accède pas déjà à une instance */
|
|
|
|
if( SM_Open_Counter > 0)
|
|
{
|
|
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éation de la base de mémoire partagé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à 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è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é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émente le compteur d'ouverture de la librairie */
|
|
|
|
SM_Open_Counter++;
|
|
|
|
return( SMS_OK);
|
|
|
|
/* Gestion d'erreur */
|
|
|
|
Error2:
|
|
ND_DataStruct_Close( Opened_Heap_List);
|
|
|
|
Error1:
|
|
ND_Library_Close();
|
|
|
|
return( rc);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Récupération du numéro de l'instance utilisée */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (O) Instance : adresse du numéro de l'instance utilisée */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Instance_Get_I( int *Instance)
|
|
{
|
|
*Instance = SM_Instance;
|
|
|
|
return( SMS_OK);
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Récupération du nom du contexte utilisé */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (O) Context : adresse du nom du contexte utilisé */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Context_Get_I ( char **Context)
|
|
{
|
|
*Context = SM_Context;
|
|
|
|
return( SMS_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Changement de contexte d'utilisation de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Context : nom du nouveau contexte */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Context_Set_I( const char *Context )
|
|
{
|
|
if( SM_Context) free( SM_Context);
|
|
|
|
if( Context && strlen( Context))
|
|
{
|
|
SM_Context = strdup( Context);
|
|
}
|
|
else
|
|
{
|
|
if( getenv( CONTEXT_ENV_VAR) && strlen ( getenv( CONTEXT_ENV_VAR)))
|
|
{
|
|
SM_Context = strdup (getenv (CONTEXT_ENV_VAR));
|
|
}
|
|
else
|
|
{
|
|
SM_Context = strdup (DEFAULT_CONTEXT);
|
|
}
|
|
}
|
|
|
|
return( SMS_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fermeture de l'instance de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Close_Mode : mode de fermeture (destruction ou fermeture simple) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Close_I( SMT_Flags Close_Mode)
|
|
{
|
|
SMT_Status rc;
|
|
|
|
|
|
if( Close_Mode & SMD_DESTROY) /* Destruction de l'instance */
|
|
{
|
|
/* Destruction de la base de mémoire partagée */
|
|
|
|
rc = SM_Base_End();
|
|
if( rc != SMS_OK)
|
|
{
|
|
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 été ouverte qu'une seule fois.
|
|
*/
|
|
|
|
if( SM_Open_Counter == 1)
|
|
{
|
|
/* Fermeture de la base de mémoire partagée */
|
|
|
|
rc = SM_Base_Close();
|
|
if( rc != SMS_OK)
|
|
{
|
|
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 à jour le compteur d'ouverture de la librairie */
|
|
|
|
SM_Open_Counter--;
|
|
}
|
|
|
|
return( SMS_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Affichage des informations de la base de mémoires partagées */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Dump_I( FILE *Out)
|
|
{
|
|
/* Affichage des informations sur la base */
|
|
|
|
fprintf( Out, "Base: (%d):[%s]\tSize: (%d)\tCreator PId: (%ld)\tLast write access PId: (%ld)\nId Mem: (%d):(%d)\tId Sem: (%d)\tStatus: [%s]\n\n",
|
|
SM_Instance, SM_Context, SM_Base->Size, SM_Base->Creator, SM_Base->Writer, SM_Base->SysMemId, SM_Base->DataMemId, SM_Base->SemId, SM_Lock_Status_Get( "base", SM_Base));
|
|
|
|
/* 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ération de tous les verrous (base, heap) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Unlock_I( void)
|
|
{
|
|
NDT_Node *Node;
|
|
union semun Sem_Ctl;
|
|
|
|
|
|
/* Libération des verrous sur la base */
|
|
|
|
Sem_Ctl.val = 1;
|
|
|
|
if( semctl( SM_Base->SemId, 0, SETVAL, Sem_Ctl))
|
|
{
|
|
sprintf( SM_Error_Msg, "SM_Library_Free : unable to unlock the shared memory base");
|
|
SM_Error_Print();
|
|
|
|
return( SMS_ERRSEM);
|
|
}
|
|
|
|
/* Libération des verrous sur les heaps */
|
|
|
|
ND_Index_Node_First_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
|
|
|
|
while( Node)
|
|
{
|
|
SMT_MHH *MHH;
|
|
|
|
MHH = (SMT_MHH *)( Node->Value);
|
|
|
|
if( semctl( MHH->SemId, 0, SETVAL, Sem_Ctl))
|
|
{
|
|
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ème en lecture */
|
|
|
|
SM_Heap_Lock_I( System_Heap, SMD_READ, &Locked);
|
|
}
|
|
|
|
/* Recherche dans le MHR */
|
|
|
|
ND_Index_Node_First_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
|
|
|
|
while( Node)
|
|
{
|
|
MHH = (SMT_MHH *)( Node->Value);
|
|
|
|
if (!strcmp( Prefixed_Name, MHH->Name))
|
|
{
|
|
return( SMS_YES);
|
|
}
|
|
|
|
ND_Index_Node_Next_Get( &Node, Node);
|
|
}
|
|
|
|
/* Déverrouillage éventuel du heap système */
|
|
|
|
if( Locked == TRUE)
|
|
{
|
|
SM_Heap_Unlock_I( System_Heap);
|
|
}
|
|
|
|
return( SMS_NO);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ouverture/création d'un heap */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Heap_Name : nom du heap */
|
|
/* (O) Heap : pointeur sur le heap ouvert / créé */
|
|
/* (I) Seg_Size : taille des segments du heap */
|
|
/* (I) Open_Mode : mode d'ouverture du heap */
|
|
/* (O) Locked : verrou effectif (TRUE ou FALSE) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Heap_Open_I( const char *Heap_Name, SMT_Heap **Heap, 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à 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é */
|
|
|
|
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à 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é */
|
|
|
|
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);
|
|
}
|
|
|
|
/*Alloc du MHH qui fait l'alloccation du premier segment de donnees*/
|
|
rc = ND_Value_Alloc( SM_Base->MHR, (void **)&MHH, Prefixed_Name, Seg_Size);
|
|
if( rc != NDS_OK)
|
|
{
|
|
sprintf( SM_Error_Msg, "SM_Heap_Open : unable to alloc a new MHH structure");
|
|
SM_Error_Print();
|
|
return(SMS_ERRAPI);
|
|
}
|
|
|
|
/* Ajout du nouveau heap à 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é */
|
|
|
|
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é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:
|
|
ND_Value_Free( 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à été 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 écriture */
|
|
|
|
rc = SM_Heap_Lock_I (Heap, SMD_WRITE, &Locked);
|
|
}
|
|
else
|
|
{
|
|
/* Ouverture du heap en écriture */
|
|
|
|
rc = SM_Heap_Open_I (Heap_Name, &Heap, 0, SMD_OPEN | SMD_WRITE, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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ées composant le heap
|
|
en commencant par le dernier (important pour le heap système)
|
|
*/
|
|
|
|
ND_Index_Node_Last_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
|
|
while (Node)
|
|
{
|
|
rc = SM_DataSegment_Close (Node->Value);
|
|
if (SM_ERROR(rc)) return rc;
|
|
|
|
ND_Index_Node_Previous_Get( &Node, Node);
|
|
}
|
|
|
|
/* Déverrouillage du heap */
|
|
|
|
SM_Heap_Unlock_I (Heap);
|
|
|
|
/* Suppression du heap de la liste des heaps ouverts */
|
|
|
|
rc = ND_DataStruct_Value_Remove( Opened_Heap_List, Heap);
|
|
if (SM_ERROR(rc)) return rc;
|
|
|
|
rc = ND_Value_Free( Opened_Heap_List, Heap);
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Pose d'un verrou sur un heap */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Heap : pointeur sur un heap ouvert */
|
|
/* (I) Lock_Mode : mode de verrouillage (SMD_READ ou SMD_WRITE) */
|
|
/* (O) Locked : verrouillage effectué (TRUE ou FALSE) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Heap_Lock_I ( SMT_Heap * Heap, SMT_Flags Lock_Mode, int * Locked )
|
|
{
|
|
SMT_Status rc;
|
|
int Nb_Detected, Nb_Corrected;
|
|
|
|
|
|
if( Lock_Mode == Heap->Lock_Mode)
|
|
{
|
|
/* Rien à faire : le heap est déjà verrouillé dans ce mode */
|
|
|
|
fprintf( stderr, "Already locked !!!\n");
|
|
fflush( stderr);
|
|
|
|
*Locked = FALSE;
|
|
}
|
|
else if( Heap->Lock_Mode == SMD_NO_LOCK)
|
|
{
|
|
/*
|
|
Verrouillage d'un heap qui ne l'était pas : le heap ayant pu être modifié
|
|
depuis la dernière fois qu'on y a accédé, il faut procéder à un certain
|
|
nombre de vérifications.
|
|
*/
|
|
|
|
/* Vérification de l'état du heap */
|
|
|
|
if( Heap->MHH->State == SMD_STATE_CORRUPTED)
|
|
{
|
|
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é */
|
|
|
|
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'état du heap */
|
|
|
|
if( Heap->MHH->State == SMD_STATE_UNVALIDATED)
|
|
{
|
|
/* Verrouillage du heap en écriture pour le vérifier */
|
|
|
|
if (Lock_Mode == SMD_READ)
|
|
{
|
|
rc = SM_Heap_Lock_Change (Heap->MHH, SMD_WRITE);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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 éventuellement le heap dans le mode demandé */
|
|
|
|
if( Lock_Mode == SMD_READ)
|
|
{
|
|
rc = SM_Heap_Lock_Change (Heap->MHH, SMD_READ);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* TEST !!!! */
|
|
|
|
{
|
|
NDT_Node *node_ptr = NULL;
|
|
SMT_Heap *heap_ptr;
|
|
|
|
|
|
if( SM_Heap_IsOpen_I( "system", &heap_ptr) != SMS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "SM_Heap_Lock : Internal Error 1 !");
|
|
SM_Error_Print ();
|
|
}
|
|
else
|
|
{
|
|
if( Heap->Nb_Seg != Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number)
|
|
{
|
|
ND_Index_Node_First_Get( &node_ptr, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
|
|
|
|
if( node_ptr == NULL)
|
|
{
|
|
sprintf (SM_Error_Msg, "SM_Heap_Lock : Internal Error 2 !");
|
|
SM_Error_Print ();
|
|
}
|
|
else
|
|
{
|
|
while( node_ptr)
|
|
{
|
|
if( ( rc = SM_DataSegment_Open( node_ptr->Value)) != SMS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "SM_Heap_Lock : unable to open one of the data segments of heap \"%s\"",
|
|
( (SMT_MHH *)(node_ptr->Value))->Name);
|
|
SM_Error_Print ();
|
|
}
|
|
else
|
|
{
|
|
// sprintf (SM_Error_Msg, "SM_Heap_Lock : Opening Segment (%x)", node_ptr->Value);
|
|
// SM_Error_Print ();
|
|
}
|
|
|
|
ND_Index_Node_Next_Get( &node_ptr, node_ptr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* On vérifie qu'aucun nouveau segment n'a été ajouté depuis la dernière ouverture */
|
|
|
|
if (Heap->Nb_Seg != Heap->MHH->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number)
|
|
{
|
|
NDT_Node * Node;
|
|
|
|
/* On ouvre tous les segments du heap */
|
|
|
|
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
|
|
while (Node)
|
|
{
|
|
rc = SM_DataSegment_Open (Node->Value);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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à verrouillé 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é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ôle que la limite fixée est inférieure à la taille actuelle du heap */
|
|
|
|
rc = ND_DataStruct_Traverse (Heap->MHH->DSR, NDD_CMD_VALUE_SUM, (void *)&Current_Size);
|
|
if (rc != NDS_OK) return rc;
|
|
|
|
if (Current_Size > Size)
|
|
{
|
|
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ée */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Heap_Compress_I( SMT_Heap *Heap, size_t *Compress)
|
|
{
|
|
SMT_Status rc;
|
|
NDT_Node *Node;
|
|
|
|
|
|
*Compress = 0;
|
|
|
|
/*
|
|
Pour permettre la compression, il faut que les
|
|
chunks libres soient triés par adresse.
|
|
*/
|
|
|
|
rc = ND_DataStruct_Reorg (Heap->MHH->FCR);
|
|
if( rc != NDS_OK) return( rc);
|
|
|
|
/* Compression de chaque segment de données du heap */
|
|
|
|
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
|
|
|
|
while( Node)
|
|
{
|
|
*Compress += SM_DataSegment_Compress( (SMT_DSH *)(Node->Value), Heap->MHH->FCR);
|
|
ND_Index_Node_Next_Get( &Node, Node);
|
|
}
|
|
|
|
Heap->MHH->Compress_Nb++;
|
|
|
|
return( SMS_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Vérification/correction des structures d'un heap */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Heap : pointeur sur un heap ouvert */
|
|
/* (O) Nb_Detected : pointeur sur le nombre d'erreurs détectées */
|
|
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigées */
|
|
/* (I) Out : pointeur sur le flux de sortie du rapport */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Heap_Check_I ( SMT_Heap * Heap, int * Nb_Detected, int * Nb_Corrected, FILE * Out)
|
|
{
|
|
SMT_Status rc;
|
|
NDT_Node * Node;
|
|
|
|
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 ça n'aurait pas été fait */
|
|
|
|
ND_Index_Node_First_Get( &Node, Heap->MHH->DSR, NDD_INDEX_PRIMARY);
|
|
|
|
while (Node)
|
|
{
|
|
rc = SM_DataSegment_Open (Node->Value);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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édure de vérification */
|
|
|
|
if (*Nb_Detected > *Nb_Corrected)
|
|
{
|
|
/* On déclare le heap corrompu afin que plus personne n'y accè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ées allouée */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Chunk_Alloc_I ( SMT_Heap * Heap, size_t Alloc_Size, void ** Ptr )
|
|
{
|
|
NDT_Node * Node;
|
|
SMT_Chunk * Chunk;
|
|
SMT_DSH * DSH;
|
|
int Found;
|
|
size_t Round_Size;
|
|
SMT_Status rc;
|
|
|
|
|
|
*Ptr = NULL;
|
|
|
|
/*
|
|
On invalide le heap jusqu'à ce que la procédure d'allocation soit entièrement terminée.
|
|
Ainsi, si celle-ci est interrompue, le heap restera invalide jusqu'à ce qu'il soit
|
|
"réparé" (appel de la fonction SM_Heap_Check par la fonction SM_Heap_Open).
|
|
*/
|
|
|
|
Heap->MHH->State = SMD_STATE_UNVALIDATED;
|
|
|
|
/*
|
|
Pour le heap système, tous les chunks alloués ont la même taille (DEFAULT_CHUNK_SIZE).
|
|
Ceci facilite notamment la récupération des errors (Recovery) dans le heap système.
|
|
Ceci a aussi pour but de simplifier (et donc d'optimiser) l'allocation de nouveaux chunks
|
|
dans ce heap système dont la mémoire n'a pas besoin d'être optimisée.
|
|
|
|
*/
|
|
|
|
if (Heap == System_Heap) Alloc_Size = DEFAULT_CHUNK_SIZE;
|
|
|
|
/*
|
|
Attention : pour les autres heaps, la taille allouée doit être arrondie à un multiple
|
|
de 4 octets (en 32 bits) afin que les adresses des chunks soient alignées (sinon SIGBUS !).
|
|
*/
|
|
|
|
Round_Size = Alloc_Size % sizeof (void *);
|
|
|
|
if (Round_Size) Alloc_Size += sizeof (void *) - Round_Size;
|
|
|
|
/* Recherche d'un chunk suffisamment grand dans la liste des chunks libres */
|
|
|
|
Found = FALSE;
|
|
|
|
ND_Index_Node_First_Get( &Node, Heap->MHH->FCR, NDD_INDEX_PRIMARY);
|
|
while (Found == FALSE && Node)
|
|
{
|
|
Chunk = (SMT_Chunk *)(Node->Value);
|
|
|
|
if (Chunk->Size >= Alloc_Size) Found = TRUE;
|
|
else ND_Index_Node_Next_Get( &Node, Node);
|
|
}
|
|
|
|
if (Found == FALSE)
|
|
{
|
|
/*
|
|
Si aucun chunk libre suffisamment grand n'a été trouvé,
|
|
alors on crée un nouveau segment de données.
|
|
*/
|
|
|
|
size_t Seg_Size;
|
|
|
|
if (Alloc_Size + sizeof (NDT_Node) + sizeof (SMT_Chunk) > Heap->MHH->Segment_Size)
|
|
Seg_Size = Alloc_Size + sizeof (NDT_Node) + sizeof (SMT_Chunk);
|
|
else
|
|
Seg_Size = Heap->MHH->Segment_Size;
|
|
|
|
|
|
rc = ND_Value_Alloc(Heap->MHH->DSR,(void**)&DSH,Heap->MHH, Seg_Size);
|
|
if (rc != NDS_OK )
|
|
{
|
|
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 ();
|
|
|
|
|
|
ND_Value_Free(Heap->MHH->DSR, DSH);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
Maintenant que l'on a ajouté un segment de données, il existe
|
|
un chunk libre suffisamment grand au début de ce segment.
|
|
*/
|
|
|
|
Node = (NDT_Node *)DSH->Start;
|
|
Chunk = (SMT_Chunk *)(Node->Value);
|
|
}
|
|
|
|
/* Suppression du chunk de la liste des chunks libres */
|
|
|
|
rc = ND_Index_Node_Remove (Node);
|
|
if (rc != NDS_OK)
|
|
{
|
|
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 à la liste des chunks alloué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ère */
|
|
|
|
ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, Node);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
Si le chunk trouvé est plus grand que ce dont on a besoin, alors
|
|
on peut créer un nouveau chunk libre avec le reliquat de mémoire.
|
|
*/
|
|
|
|
if (Chunk->Size - Alloc_Size > 0)
|
|
{
|
|
size_t Remaining_Size = Chunk->Size - Alloc_Size;
|
|
|
|
/*
|
|
La création d'un nouveau chunk libre requiert de la place pour les
|
|
données système (SMT_Chunk + NDT_Node) : on ne crée donc un nouveau
|
|
chunk libre que si le reliquat est suffisamment important.
|
|
*/
|
|
|
|
if (Remaining_Size > sizeof (SMT_Chunk) + sizeof (NDT_Node))
|
|
{
|
|
NDT_Node * New_Node;
|
|
SMT_Chunk * New_Chunk;
|
|
size_t New_Chunk_Size;
|
|
|
|
/* Création d'un nouveau chunk libre (noeud puis valeur) juste derrière le chunk trouvé */
|
|
|
|
New_Node = (NDT_Node *)((size_t)(Chunk->Data) + Alloc_Size);
|
|
|
|
New_Chunk = (SMT_Chunk *)((size_t)New_Node + sizeof (NDT_Node) );
|
|
|
|
New_Chunk_Size = Remaining_Size - sizeof (SMT_Chunk) - sizeof (NDT_Node);
|
|
|
|
New_Chunk->Size = New_Chunk_Size;
|
|
|
|
New_Chunk->Data = (void *)((size_t)(New_Chunk) + sizeof (SMT_Chunk) );
|
|
|
|
New_Node->Root = NULL;
|
|
New_Node->Parent = NULL;
|
|
New_Node->Left = NULL;
|
|
New_Node->Right = NULL;
|
|
New_Node->Value = New_Chunk;
|
|
|
|
rc = ND_Index_Node_Add( Heap->MHH->FCR, NDD_INDEX_PRIMARY, New_Node);
|
|
if (rc != NDS_OK)
|
|
{
|
|
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é */
|
|
|
|
Chunk->Size = Alloc_Size;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Pour une allocation dans le heap système, on anticipe l'ajout
|
|
d'un nouveau segment pour éviter de se retrouver bloqué.
|
|
|
|
Bien entendu, cette opération n'est faite que si l'on n'est
|
|
pas déjà en train d'étendre le heap système (Adding_Segment=TRUE).
|
|
*/
|
|
|
|
if (Heap == System_Heap && Adding_Segment == FALSE)
|
|
{
|
|
SMT_Chunk * Free_Chunk;
|
|
unsigned int Free_Usable_Chunk = 0;
|
|
size_t Free_Usable_Size = 0;
|
|
int New_Seg_Needed = FALSE;
|
|
|
|
/* On compte le nombre de chunks libres "utilisables" dans la structure FCR */
|
|
|
|
ND_Index_Node_First_Get( &Node, Heap->MHH->FCR, NDD_INDEX_PRIMARY);
|
|
while (Node)
|
|
{
|
|
Free_Chunk = Node->Value;
|
|
|
|
if (Free_Chunk->Size >= DEFAULT_CHUNK_SIZE)
|
|
{
|
|
Free_Usable_Chunk++;
|
|
Free_Usable_Size += Free_Chunk->Size;
|
|
}
|
|
|
|
ND_Index_Node_Next_Get( &Node, Node);
|
|
}
|
|
|
|
/*
|
|
S'il reste au moins FREE_CHUNK_LIMIT chunks libres "utilisables"
|
|
ou bien si ces chunks libres "utilisables" représentent suffisament de
|
|
place pour allouer FREE_CHUNK_LIMIT nouveaux chunks, alors tout est OK.
|
|
|
|
Dans le cas contraire, il est urgent d'étendre le heap système.
|
|
*/
|
|
|
|
if (Free_Usable_Chunk < FREE_CHUNK_LIMIT)
|
|
{
|
|
size_t Needed_Size;
|
|
|
|
Needed_Size = (size_t)(FREE_CHUNK_LIMIT * DEFAULT_CHUNK_SIZE) + (size_t)(FREE_CHUNK_LIMIT - Free_Usable_Chunk) * (sizeof (NDT_Node) + sizeof (SMT_Chunk));
|
|
|
|
if (Free_Usable_Size < Needed_Size) New_Seg_Needed = TRUE;
|
|
}
|
|
|
|
if (New_Seg_Needed == TRUE)
|
|
{
|
|
NDT_Node * New_Node;
|
|
|
|
/*
|
|
Puisque l'ajout d'un nouveau segment va appeler cette même fonction,
|
|
on positionne une variable globale pour ne pas recommencer cette opération.
|
|
*/
|
|
|
|
Adding_Segment = TRUE;
|
|
|
|
/*
|
|
On alloue le noeud du nouveau segment avant de faire appel à la fonction
|
|
ND_Value_Alloc pour éviter que ce noeud soit alloué dans le nouveau segment.
|
|
*/
|
|
|
|
SM_System_Alloc( (void **)(&New_Node), sizeof (NDT_Node), NULL);
|
|
New_Node->Root = NULL;
|
|
New_Node->Parent = NULL;
|
|
New_Node->Left = NULL;
|
|
New_Node->Right = NULL;
|
|
|
|
/* On crée le nouveau segment */
|
|
rc = ND_Value_Alloc(Heap->MHH->DSR,(void**)&DSH,Heap->MHH,Heap->MHH->Segment_Size);
|
|
if (rc != NDS_OK)
|
|
{
|
|
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è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 ();
|
|
|
|
|
|
ND_Value_Free(Heap->MHH->DSR, DSH);
|
|
return rc;
|
|
}
|
|
|
|
Adding_Segment = FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Puisque la procédure d'allocation d'un chunk s'est correctement
|
|
terminée, on peut rendre le heap à nouveau valide.
|
|
*/
|
|
|
|
Heap->MHH->State = SMD_STATE_VALID;
|
|
|
|
*Ptr = Chunk->Data;
|
|
|
|
return SMS_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Désallocation d'un chunk */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Heap : pointeur sur un heap ouvert */
|
|
/* (I) Ptr : pointeur sur la zone de données du chunk à désallouer */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Chunk_Free_I ( SMT_Heap * Heap, void * Ptr)
|
|
{
|
|
NDT_Node * Node;
|
|
SMT_Chunk * Chunk;
|
|
SMT_Status rc;
|
|
|
|
/*
|
|
On invalide le heap jusqu'à ce que la procédure de désallocation soit entièrement terminée.
|
|
Ainsi, si celle-ci est interrompue, le heap restera invalide jusqu'à ce qu'il soit
|
|
"réparé" (appel de la fonction SM_Heap_Check par la fonction SM_Heap_Open).
|
|
*/
|
|
|
|
Heap->MHH->State = SMD_STATE_UNVALIDATED;
|
|
|
|
/*
|
|
Le noeud du chunk étant adjoint à celui-ci, on n'a pas besoin
|
|
de le rechercher dans la liste des chunks alloués.
|
|
*/
|
|
|
|
Node = (NDT_Node *)((size_t)Ptr - sizeof (SMT_Chunk) - sizeof (NDT_Node));
|
|
|
|
Chunk = Node->Value;
|
|
|
|
/* Suppression du chunk de la liste des chunks alloués */
|
|
|
|
rc = ND_Index_Node_Remove (Node);
|
|
if (rc != NDS_OK)
|
|
{
|
|
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 à 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ère */
|
|
|
|
ND_Index_Node_Add( Heap->MHH->ACR, NDD_INDEX_PRIMARY, Node);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
Puisque la procédure de désallocation d'un chunk s'est correctement
|
|
terminé, on peut rendre le heap à nouveau valide.
|
|
*/
|
|
|
|
Heap->MHH->State = SMD_STATE_VALID;
|
|
|
|
/* Activation de la compression automatique */
|
|
|
|
if (Heap->MHH->Auto_Compress != SMD_NO_AUTO_COMPRESS &&
|
|
Heap->MHH->FCR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number > Heap->MHH->Auto_Compress)
|
|
{
|
|
size_t Compress_Size;
|
|
|
|
rc = SM_Heap_Compress (Heap, &Compress_Size);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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éation/ouverture + mode d'affichage des erreurs */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Open_C ( int Instance, const char * Context, SMT_Flags Open_Mode )
|
|
{
|
|
return SM_Library_Open_I (Instance, Context, Open_Mode);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Récupération du numéro de l'instance utilisée */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (O) Instance : adresse du numéro de l'instance utilisée */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Instance_Get_C ( int * Instance )
|
|
{
|
|
return SM_Library_Instance_Get_I (Instance);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Récupération du nom du contexte utilisé */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (O) Context : adresse du nom du contexte utilisé */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Context_Get_C ( char ** Context )
|
|
{
|
|
return SM_Library_Context_Get_I (Context);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Changement de contexte d'utilisation de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Context : nom du nouveau contexte */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Context_Set_C ( const char * Context )
|
|
{
|
|
return SM_Library_Context_Set_I (Context);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fermeture de l'instance de la librairie */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Close_Mode : mode de fermeture (destruction ou fermeture simple) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Library_Close_C ( SMT_Flags Close_Mode )
|
|
{
|
|
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é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é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éation d'un heap */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Heap_Name : nom du heap */
|
|
/* (O) Heap : pointeur sur le heap ouvert / créé */
|
|
/* (I) Seg_Size : taille des segments du heap */
|
|
/* (I) Open_Mode : mode d'ouverture du heap */
|
|
/* (O) Locked : verrou effectif (TRUE ou FALSE) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Heap_Open_C ( const char * Heap_Name, SMT_Heap ** Heap, 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à été ouvert par le processus courant */
|
|
/*------------------------------------------------------------------------------*/
|
|
/* (I) Heap_Name : Nom du heap */
|
|
/* (O) Heap : pointeur sur le heap ouvert */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Heap_IsOpen_C ( const char * Heap_Name, SMT_Heap ** Heap )
|
|
{
|
|
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é (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é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ôle que la limite fixée est inférieure à la taille actuelle du heap */
|
|
|
|
rc = ND_DataStruct_Traverse (Heap->MHH->DSR, NDD_CMD_VALUE_SUM, (void *)&Current_Size);
|
|
if (rc != NDS_OK) return rc;
|
|
|
|
if (Current_Size > 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é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ées */
|
|
/* (O) Nb_Corrected : pointeur sur le nombre d'erreurs corrigées */
|
|
/* (I) Out : pointeur sur le flux de sortie du rapport */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Heap_Check_C ( SMT_Heap * Heap, 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ées alloué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ées du chunk à 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è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è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é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 à 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éation d'un segment de mémoire partagée qui contiendra la structure SMT_Base.
|
|
Ce segment peut être attaché à n'importe quelle adresse.
|
|
*/
|
|
|
|
SysMemId = shmget (SM_Instance, (int) sizeof (SMT_Base), 0777|IPC_CREAT|IPC_EXCL);
|
|
if (SysMemId == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case EEXIST:
|
|
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é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ème n'est pas créé, on est obligé d'allouer de
|
|
la mémoire dans le segment de mémoire partagée de la base (fonction SM_Base_Alloc).
|
|
|
|
Les ressources à allouer (structure MHR + ressources du heap système) sont référencées
|
|
par des pointeurs et doivent par conséquent être contenues dans un segment attaché à
|
|
une adresse commune à tous les processus.
|
|
On crée donc ce segment de mémoire partagé spécifique dont l'adresse d'attachement
|
|
sera mémorisée dans la structure SMT_Base.
|
|
|
|
Pour ce segment de mémoire partagé, on réserve de la place pour :
|
|
- la structure du MHR (NDT_Root)
|
|
- les ressources du heap système, i.e :
|
|
- son noeud (NDT_Node)
|
|
- sa structure d'entête ( SMT_MHH)
|
|
- sa structure DSR (NDT_Root)
|
|
- sa structure ACR (NDT_Root)
|
|
- sa structure FCR (NDT_Root)
|
|
- son premier segment de données (noeud + entête)
|
|
*/
|
|
|
|
Size = sizeof (NDT_Root) + sizeof (NDT_Node) + sizeof (SMT_MHH) + 3 * sizeof (NDT_Root) + sizeof (NDT_Node) + sizeof (SMT_DSH);
|
|
|
|
DataMemId = shmget (IPC_PRIVATE, Size, 0777|IPC_CREAT|IPC_EXCL);
|
|
if (DataMemId == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case EINVAL:
|
|
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ées à la base */
|
|
|
|
SM_Base->SemId = SemId;
|
|
SM_Base->SysMemId = SysMemId;
|
|
SM_Base->DataMemId = DataMemId;
|
|
SM_Base->Size = Size;
|
|
SM_Base->Creator = getpid ();
|
|
SM_Base->Writer = SM_Base->Creator;
|
|
SM_Base->Attach = (void *)MEM_LIMIT;
|
|
SM_Base->MHR = NULL;
|
|
|
|
/*
|
|
On attache le segment de mémoire partagée au processus courant
|
|
à une adresse la plus haute possible (MEM_LIMIT) afin d'éviter
|
|
de déborder sur la plage d'adressage des symboles.
|
|
*/
|
|
|
|
errno = 0;
|
|
|
|
#ifndef __hpux
|
|
SM_Base->Free = shmat( DataMemId, (void *)((size_t)(SM_Base->Attach) - Size), SHM_RND);
|
|
#else
|
|
SM_Base->Free = shmat( DataMemId, 0, 0);
|
|
#endif
|
|
|
|
if (errno)
|
|
{
|
|
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é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éation d'un premier heap qui constituera le heap système
|
|
(l'allocation du MHN, du MHH et des structures DSR, ACR et FCR
|
|
sont effectuées dans la base)
|
|
*/
|
|
|
|
rc = SM_Heap_Open_I (HEAP_SYSTEM, &System_Heap, 0, SMD_CREATE, &Locked);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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è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ème afin que désormais, les allocations des
|
|
nouveaux segments et chunks soient faites dans le segment de
|
|
données du heap système.
|
|
*/
|
|
|
|
strcpy( System_Heap->MHH->DSR->Allocator_Name, "SM_System_Alloc");
|
|
strcpy( System_Heap->MHH->DSR->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 é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ème en dernier).
|
|
|
|
NB : à chaque destruction de heap, la base est verrouillée en écriture
|
|
*/
|
|
|
|
ND_Index_Node_Last_Get( &Node, SM_Base->MHR, NDD_INDEX_PRIMARY);
|
|
|
|
while (Node)
|
|
{
|
|
SMT_MHH * MHH = (SMT_MHH *)(Node->Value);
|
|
|
|
ND_Index_Node_Previous_Get( &Previous_Node, Node);
|
|
|
|
/*
|
|
Pour la suppression du heap système, il faut redéfinir la fonction de
|
|
désallocation du MHR, car il a été alloué dans la base (voir SM_Base_Init)
|
|
*/
|
|
|
|
if( !Previous_Node)
|
|
{
|
|
strcpy( SM_Base->MHR->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é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ération de l'identifiant du segment de mémoire partagée de la base */
|
|
|
|
MemId = shmget (SM_Instance, 0, 0);
|
|
if (MemId == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case EACCES:
|
|
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é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è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ème en dernier.
|
|
*/
|
|
|
|
ND_Index_Node_First_Get( &Node, Opened_Heap_List, NDD_INDEX_PRIMARY);
|
|
|
|
while (Node)
|
|
{
|
|
NDT_Node *Next_Node;
|
|
ND_Index_Node_Next_Get( &Next_Node, Node);
|
|
SM_Heap_Close_I ((SMT_Heap *)(Node->Value));
|
|
Node = Next_Node;;
|
|
}
|
|
|
|
/* Déverrouillage de la base en lecture */
|
|
|
|
SM_Base_Unlock (SMD_READ);
|
|
|
|
/* Détachement des segments de mémoire partagée de la base */
|
|
|
|
shmdt ((void *)SM_Base->MHR);
|
|
shmdt ((void *)SM_Base);
|
|
|
|
SM_Base = NULL;
|
|
|
|
return SMS_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Pose d'un verrou sur la base */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_Base_Lock ( SMT_Flags Lock_Mode )
|
|
{
|
|
SMT_Status rc;
|
|
|
|
if (Lock_Mode & SMD_READ)
|
|
{
|
|
rc = SM_Semaphore_Operate (SM_Base->SemId, SM_SemOp_SSL, 2);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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é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( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list Args)
|
|
{
|
|
NDT_Command_Name Command_Name;
|
|
|
|
|
|
switch( Command)
|
|
{
|
|
case NDD_CMD_MANAGER_VERSION:
|
|
{
|
|
NDT_Version_Name *Version_Name_Ptr = (NDT_Version_Name *)va_arg( Args, NDT_Version_Name *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_MANAGER_VERSION";
|
|
|
|
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INDEX_GET:
|
|
{
|
|
/*
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
*/
|
|
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INDEX_GET";
|
|
|
|
switch( Cmd)
|
|
{
|
|
/*
|
|
case NDT_CMD_SOME_USER_CMD:
|
|
{
|
|
*Reply_Index_Id_Ptr = 0;
|
|
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
|
|
break;
|
|
}
|
|
|
|
...
|
|
*/
|
|
|
|
default:
|
|
{
|
|
*Reply_Index_Id_Ptr = Index_Id;
|
|
*Reply_Command_Ptr = Cmd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ALLOC:
|
|
{
|
|
/*
|
|
void **Value_Ptr_Ptr = (void **)va_arg( Args, void **);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ALLOC";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_FREE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
SMT_Heap *Heap_Ptr = (SMT_Heap *)va_arg( Args, SMT_Heap *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_FREE";
|
|
|
|
free( Heap_Ptr->Name);
|
|
free( Heap_Ptr);
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_COMP:
|
|
{
|
|
/*
|
|
void *Value1_Ptr = (void *)va_arg( Args, void *);
|
|
void *Value2_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
SMT_Heap *Heap1_Ptr = (SMT_Heap *)va_arg( Args, SMT_Heap *);
|
|
SMT_Heap *Heap2_Ptr = (SMT_Heap *)va_arg( Args, SMT_Heap *);
|
|
|
|
long comp;
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_COMP";
|
|
|
|
comp = strcmp( Heap1_Ptr->Name, Heap2_Ptr->Name);
|
|
|
|
if( comp < 0) return( NDS_LOWER);
|
|
|
|
if( comp > 0) return( NDS_GREATER);
|
|
|
|
return( NDS_EQUAL);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ADD:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ADD";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_REMOVE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_REMOVE";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
SMT_Heap *Heap_Ptr = ( SMT_Heap *)( Node_Ptr->Value);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_PRINT";
|
|
|
|
fprintf( Out, "Heap_Name: [%s]/[%s] Heap_Addr: (%p) MHH_Ptr: (%p) Lock_Mode: (%d) Seg_Nb: (%d)\n",
|
|
SM_Context, Heap_Ptr->Name, Heap_Ptr, Heap_Ptr->MHH, Heap_Ptr->Lock_Mode, Heap_Ptr->Nb_Seg);
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INFO_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_INFO_PRINT";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
default:
|
|
{
|
|
printf( "ND_Default_Manager() called with an undefined command %d\n", Command);
|
|
return( NDS_ERRAPI);
|
|
}
|
|
}
|
|
|
|
printf( "ND_Default_Manager() called with command %d (%s)\n", Command, Command_Name);
|
|
return( NDS_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fonction manager du MHR (Memory Heap Root) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
NDT_Status MHR_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list Args)
|
|
{
|
|
NDT_Command_Name Command_Name;
|
|
|
|
|
|
switch( Command)
|
|
{
|
|
case NDD_CMD_MANAGER_VERSION:
|
|
{
|
|
NDT_Version_Name *Version_Name_Ptr = (NDT_Version_Name *)va_arg( Args, NDT_Version_Name *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_MANAGER_VERSION";
|
|
|
|
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INDEX_GET:
|
|
{
|
|
/*
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
*/
|
|
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INDEX_GET";
|
|
|
|
switch( Cmd)
|
|
{
|
|
/*
|
|
case NDT_CMD_SOME_USER_CMD:
|
|
{
|
|
*Reply_Index_Id_Ptr = 0;
|
|
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
|
|
break;
|
|
}
|
|
|
|
...
|
|
*/
|
|
|
|
default:
|
|
{
|
|
*Reply_Index_Id_Ptr = Index_Id;
|
|
*Reply_Command_Ptr = Cmd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ALLOC:
|
|
{
|
|
/*
|
|
void **Value_Ptr_Ptr = (void **)va_arg( Args, void **);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
SMT_MHH **MHH_Ptr_Ptr = (SMT_MHH **)va_arg( Args, SMT_MHH **);
|
|
va_list user_args = (va_list)va_arg( Args, va_list );
|
|
char *Prefixed_Name = (char*)va_arg( user_args, char *);
|
|
size_t Seg_Size = (size_t)va_arg( user_args, size_t );
|
|
|
|
union semun Sem_Ctl;
|
|
int SemId;
|
|
NDT_Status rc;
|
|
NDT_Index_Type index_type = ( NDD_INDEX_STATUS_OPENED | NDD_INDEX_TYPE_LIST | NDD_INDEX_SUBTYPE_FIFO);
|
|
SMT_DSH *DSH_Ptr;
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ALLOC";
|
|
|
|
/* Création du sémaphore pour gérer les verrous sur le nouveau MHH */
|
|
|
|
SemId = semget( IPC_PRIVATE, 1, 0777 | IPC_CREAT | IPC_EXCL);
|
|
if( SemId == -1)
|
|
{
|
|
switch( errno)
|
|
{
|
|
case ENOMEM:
|
|
{
|
|
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(NDS_ERRMEM);
|
|
}
|
|
|
|
/* Initialisation du sémaphore à 1 (équivaut à aucun verrou posé) */
|
|
|
|
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ème, dans le heap système pour les autres heaps) */
|
|
|
|
if( ND_Allocator_Exec( (void **)(MHH_Ptr_Ptr), 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_Ptr_Ptr)->Name, Prefixed_Name);
|
|
(*MHH_Ptr_Ptr)->Writer = getpid();
|
|
(*MHH_Ptr_Ptr)->SemId = SemId;
|
|
(*MHH_Ptr_Ptr)->State = SMD_STATE_UNVALIDATED;
|
|
(*MHH_Ptr_Ptr)->Segment_Size = ( ( Seg_Size > 0) ? Seg_Size : SEGMENT_DEFAULT_SIZE);
|
|
(*MHH_Ptr_Ptr)->Limit_Size = SMD_UNLIMITED;
|
|
(*MHH_Ptr_Ptr)->Auto_Compress = SMD_DEFAULT_COMPRESS;
|
|
(*MHH_Ptr_Ptr)->Compress_Nb = 0L;
|
|
|
|
/*
|
|
Création de la structure DSR :
|
|
- dans la base pour le heap système
|
|
- dans le heap système pour les autres heaps
|
|
*/
|
|
|
|
rc = ND_DataStruct_Open( &( (*MHH_Ptr_Ptr)->DSR), 1, &index_type, "SM_DSR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->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éation de la structure ACR :
|
|
- dans la base pour le heap système
|
|
- dans le heap système pour les autres heaps
|
|
*/
|
|
|
|
rc = ND_DataStruct_Open( &( (*MHH_Ptr_Ptr)->ACR), 1, &index_type, "SM_ACR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->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éation de la structure FCR :
|
|
- dans la base pour le heap système
|
|
- dans le heap système pour les autres heaps
|
|
*/
|
|
|
|
rc = ND_DataStruct_Open( &( (*MHH_Ptr_Ptr)->FCR), 1, &index_type, "SM_FCR_Manager", NULL, SM_Base->MHR->Allocator_Name, NULL, SM_Base->MHR->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;
|
|
|
|
}
|
|
|
|
/*alloction du premier segement de donnee pour le heap*/
|
|
rc = ND_Value_Alloc( (*MHH_Ptr_Ptr)->DSR, (void **)&DSH_Ptr, *MHH_Ptr_Ptr, (*MHH_Ptr_Ptr)->Segment_Size);
|
|
if( rc != NDS_OK)
|
|
{
|
|
sprintf( SM_Error_Msg, "MHR_Manager : unable to create the DSH structure");
|
|
SM_Error_Print();
|
|
rc = SMS_ERRSHM;
|
|
goto Error7;
|
|
}
|
|
|
|
rc = ND_DataStruct_Value_Add( (*MHH_Ptr_Ptr)->DSR, DSH_Ptr);
|
|
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_Ptr_Ptr)->State = SMD_STATE_VALID;
|
|
|
|
return( NDS_OK);
|
|
|
|
|
|
/* Gestion d'erreur sur création */
|
|
|
|
Error9:
|
|
ND_DataStruct_Value_Remove( (*MHH_Ptr_Ptr)->DSR, DSH_Ptr);
|
|
|
|
Error8:
|
|
ND_Value_Free( (*MHH_Ptr_Ptr)->DSR, DSH_Ptr);
|
|
|
|
Error7:
|
|
ND_Desallocator_Exec( (*MHH_Ptr_Ptr)->FCR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
|
|
|
|
Error6:
|
|
ND_Desallocator_Exec( (*MHH_Ptr_Ptr)->ACR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
|
|
|
|
Error5:
|
|
ND_Desallocator_Exec( (*MHH_Ptr_Ptr)->DSR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
|
|
|
|
Error4:
|
|
ND_Desallocator_Exec( *MHH_Ptr_Ptr, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
|
|
|
|
Error3:
|
|
semctl( SemId, 0, IPC_RMID, Sem_Ctl);
|
|
|
|
return( rc);
|
|
|
|
|
|
}
|
|
|
|
case NDD_CMD_VALUE_FREE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
SMT_MHH *MHH_Ptr = (SMT_MHH *)va_arg( Args, SMT_MHH *);
|
|
SMT_Status rc;
|
|
SMT_Heap To_Find;
|
|
union semun Sem_Ctl;
|
|
SMT_Heap * Opened_Heap;
|
|
|
|
Command_Name = "NDD_CMD_VALUE_FREE";
|
|
|
|
/* Destruction de la structure DSR (et de toutes ses valeurs) */
|
|
|
|
if (!strcmp (MHH_Ptr->Name, HEAP_SYSTEM))
|
|
{
|
|
NDT_Node * Node, * Previous_Node;
|
|
SMT_DSH * DSH;
|
|
|
|
/*
|
|
Pour le heap système, on doit procéder de manière spécifique
|
|
car le premier segment contient des références sur les autres
|
|
segments. Il faut donc supprimer celui-ci en dernier.
|
|
|
|
Par ailleurs, ce premier segment a été alloué dans la base.
|
|
Il faudra donc aussi redéfinir la fonction de désallocation
|
|
du DSR pour celui-ci.
|
|
*/
|
|
|
|
ND_Index_Node_Last_Get( &Node, MHH_Ptr->DSR, NDD_INDEX_PRIMARY);
|
|
|
|
while (Node)
|
|
{
|
|
DSH = (SMT_DSH *)(Node->Value);
|
|
|
|
ND_Index_Node_Previous_Get( &Previous_Node, Node);
|
|
|
|
/* S'agit-il du heap système ? */
|
|
|
|
if( !Previous_Node)
|
|
{
|
|
strcpy( MHH_Ptr->DSR->Desallocator_Name, "SM_Base_Free");
|
|
}
|
|
|
|
/* Retrait du segment du DSR */
|
|
|
|
rc = ND_DataStruct_Value_Remove( MHH_Ptr->DSR, DSH);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "MHR_Manager NDD_CMD_VALUE_FREE : 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_Ptr->DSR, DSH);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, " MHR_Manager NDD_CMD_VALUE_FREE: 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_Ptr->DSR);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "MHR_Manager NDD_CMD_VALUE_FREE : unable to destroy the DSR structure of heap \"%s\"", MHH_Ptr->Name);
|
|
SM_Error_Print ();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Destruction des structures ACR et FCR.
|
|
|
|
NB : puisque tous les chunks réfénrencés par les ACR et FCR étaient alloués
|
|
dans les segments qui viennent d'être supprimés, on se contente de détuire
|
|
leur racine.
|
|
*/
|
|
|
|
rc = ND_Desallocator_Exec( MHH_Ptr->ACR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "MHR_Manager NDD_CMD_VALUE_FREE : unable to free the ACR root of heap \"%s\"", MHH_Ptr->Name);
|
|
SM_Error_Print ();
|
|
}
|
|
|
|
rc = ND_Desallocator_Exec( MHH_Ptr->FCR, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "MHR_Manager NDD_CMD_VALUE_FREE : unable to free the FCR root of heap \"%s\"", MHH_Ptr->Name);
|
|
SM_Error_Print ();
|
|
}
|
|
|
|
/* Suppression du heap de la liste des heaps ouverts */
|
|
|
|
To_Find.Name = MHH_Ptr->Name;
|
|
rc = ND_DataStruct_Value_Find( (void **)&Opened_Heap, Opened_Heap_List, &To_Find);
|
|
|
|
if( ( rc == NDS_OK) && ( Opened_Heap != NULL))
|
|
{
|
|
rc = ND_DataStruct_Value_Remove( Opened_Heap_List, Opened_Heap);
|
|
|
|
if (rc != NDS_OK)
|
|
{
|
|
return( rc);
|
|
}
|
|
else
|
|
{
|
|
rc = ND_Value_Free( Opened_Heap_List, Opened_Heap);
|
|
|
|
if( rc != NDS_OK)
|
|
{
|
|
return( rc);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Destruction du sémaphore attaché au heap */
|
|
|
|
semctl (MHH_Ptr->SemId, 0, IPC_RMID, Sem_Ctl);
|
|
|
|
/* Désallocation de la structure du MHH */
|
|
|
|
rc = ND_Desallocator_Exec( MHH_Ptr, SM_Base->MHR->Desallocator_Name, SM_Base->MHR->Desallocator_Ptr, NULL);
|
|
if (rc != SMS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "MHR_Manager NDD_CMD_VALUE_FREE : unable to free the header of heap \"%s\"", MHH_Ptr->Name);
|
|
SM_Error_Print ();
|
|
}
|
|
|
|
|
|
return(NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_COMP:
|
|
{
|
|
/*
|
|
void *Value1_Ptr = (void *)va_arg( Args, void *);
|
|
void *Value2_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
SMT_MHH *MHH1_Ptr = (SMT_MHH *)va_arg( Args, SMT_MHH *);
|
|
SMT_MHH *MHH2_Ptr = (SMT_MHH *)va_arg( Args, SMT_MHH *);
|
|
|
|
long comp;
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_COMP";
|
|
|
|
comp = strcmp( MHH1_Ptr->Name, MHH2_Ptr->Name);
|
|
|
|
if( comp < 0) return( NDS_LOWER);
|
|
|
|
if( comp > 0) return( NDS_GREATER);
|
|
|
|
return( NDS_EQUAL);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ADD:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ADD";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_REMOVE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_REMOVE";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
SMT_MHH *MHH_Ptr = (SMT_MHH *)( Node_Ptr->Value);
|
|
|
|
SMT_Status status;
|
|
size_t segment_size=0, alloc_size=0, free_size=0;
|
|
int segment_nb, alloc_chunk_nb, free_chunk_nb;
|
|
SMT_Heap *heap_ptr;
|
|
char *heap_name;
|
|
int locked;
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_PRINT";
|
|
|
|
/* On n'affiche le heap que s'il fait partie du contexte courant */
|
|
|
|
if( ( heap_name = strstr( MHH_Ptr->Name, SM_Context)) != 0)
|
|
{
|
|
heap_name += strlen( SM_Context) + 1;
|
|
}
|
|
else
|
|
{
|
|
if( strcmp( HEAP_SYSTEM, MHH_Ptr->Name) == 0)
|
|
{
|
|
heap_name = MHH_Ptr->Name;
|
|
}
|
|
else
|
|
{
|
|
return( NDS_OK);
|
|
}
|
|
}
|
|
|
|
if( MHH_Ptr->State == SMD_STATE_CORRUPTED)
|
|
{
|
|
fprintf( Out, "Heap_Name: [%s]/[%s] Heap_Addr: (%lx) *** CORRUPTED *** Checker_PId: (%ld)\n",
|
|
SM_Context, MHH_Ptr->Name, MHH_Ptr, MHH_Ptr->Writer);
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
if( status = ( SM_Heap_Open_I( heap_name, &heap_ptr, 0, ( SMD_OPEN | SMD_READ), &locked)) != SMS_OK)
|
|
{
|
|
sprintf( SM_Error_Msg, "Error MHR_Manager : unable to open Heap_Name: [%s] for reading", MHH_Ptr->Name);
|
|
SM_Error_Print();
|
|
|
|
return( status);
|
|
}
|
|
/* TEST !!! */
|
|
|
|
if( locked != TRUE)
|
|
{
|
|
sprintf( SM_Error_Msg, "Error MHR_Manager : unable to lock Heap_Name: [%s] for reading", MHH_Ptr->Name);
|
|
SM_Error_Print();
|
|
|
|
return( SMS_KO);
|
|
}
|
|
|
|
segment_nb = MHH_Ptr->DSR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
|
|
ND_DataStruct_Traverse( MHH_Ptr->DSR, NDD_CMD_VALUE_SUM, (void *)&segment_size);
|
|
|
|
alloc_chunk_nb = MHH_Ptr->ACR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
|
|
ND_DataStruct_Traverse( MHH_Ptr->ACR, NDD_CMD_VALUE_SUM, (void *)&alloc_size);
|
|
|
|
free_chunk_nb = MHH_Ptr->FCR->Index_Tab[NDD_INDEX_PRIMARY].Node_Number;
|
|
ND_DataStruct_Traverse( MHH_Ptr->FCR, NDD_CMD_VALUE_SUM, (void *)&free_size);
|
|
|
|
fprintf( Out, "Heap_Name: [%s]/[%s] Heap_Addr: (%p) Sem_Id: (%d) Lock_Status: [%s]\nWriter_PId: (%ld) Seg_Nb: (%d) Heap_Size: (%lu) Size_Limit: (%ld) Auto_Compress: (%d) Compress_Nb: (%ld)\nAlloc_Chunk_Nb: (%d) Alloc_Size: (%lu) Free_Chunk_Nb: (%d) Free_Size: (%lu)\n\n",
|
|
SM_Context, heap_name, MHH_Ptr, MHH_Ptr->SemId, SM_Lock_Status_Get( "heap", MHH_Ptr),
|
|
MHH_Ptr->Writer, segment_nb, segment_size, MHH_Ptr->Limit_Size, MHH_Ptr->Auto_Compress, MHH_Ptr->Compress_Nb,
|
|
alloc_chunk_nb, alloc_size, free_chunk_nb, free_size);
|
|
|
|
if( locked == TRUE)
|
|
{
|
|
SM_Heap_Unlock_I( heap_ptr);
|
|
}
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INFO_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INFO_PRINT";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
default:
|
|
{
|
|
printf( "ND_Default_Manager() called with an undefined command %d\n", Command);
|
|
return( NDS_ERRAPI);
|
|
}
|
|
}
|
|
|
|
printf( "ND_Default_Manager() called with command %d (%s)\n", Command, Command_Name);
|
|
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ème, on doit procéder de manière spécifique
|
|
car le premier segment contient des références sur les autres
|
|
segments. Il faut donc supprimer celui-ci en dernier.
|
|
|
|
Par ailleurs, ce premier segment a été alloué dans la base.
|
|
Il faudra donc aussi redéfinir la fonction de désallocation
|
|
du DSR pour celui-ci.
|
|
*/
|
|
|
|
ND_Index_Node_Last_Get( &Node, MHH->DSR, NDD_INDEX_PRIMARY);
|
|
|
|
while (Node)
|
|
{
|
|
DSH = (SMT_DSH *)(Node->Value);
|
|
|
|
ND_Index_Node_Previous_Get( &Previous_Node, Node);
|
|
|
|
/* S'agit-il du heap système ? */
|
|
|
|
if( !Previous_Node)
|
|
{
|
|
strcpy( MHH->DSR->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énrencés par les ACR et FCR étaient alloués
|
|
dans les segments qui viennent d'être supprimés, on se contente de détuire
|
|
leur racine.
|
|
*/
|
|
|
|
rc = ND_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é 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ées */
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fonction manager pour un DSR (Data Segment Root) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
NDT_Status SM_DSR_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list Args)
|
|
{
|
|
NDT_Command_Name Command_Name;
|
|
NDT_Node * Chunk_Node;
|
|
SMT_Chunk * Chunk;
|
|
|
|
|
|
switch( Command)
|
|
{
|
|
case NDD_CMD_MANAGER_VERSION:
|
|
{
|
|
NDT_Version_Name *Version_Name_Ptr = (NDT_Version_Name *)va_arg( Args, NDT_Version_Name *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_MANAGER_VERSION";
|
|
|
|
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INDEX_GET:
|
|
{
|
|
/*
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
*/
|
|
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INDEX_GET";
|
|
|
|
switch( Cmd)
|
|
{
|
|
/*
|
|
case NDT_CMD_SOME_USER_CMD:
|
|
{
|
|
*Reply_Index_Id_Ptr = 0;
|
|
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
|
|
break;
|
|
}
|
|
|
|
...
|
|
*/
|
|
|
|
default:
|
|
{
|
|
*Reply_Index_Id_Ptr = Index_Id;
|
|
*Reply_Command_Ptr = Cmd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ALLOC:
|
|
{
|
|
/*
|
|
void **Value_Ptr_Ptr = (void **)va_arg( Args, void **);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
SMT_DSH **DSH_Ptr_Ptr = (SMT_DSH **)va_arg( Args, SMT_DSH **);
|
|
va_list user_args = (va_list)va_arg( Args, va_list );
|
|
SMT_MHH *MHH_Ptr = (SMT_MHH*)va_arg( user_args, SMT_MHH *);
|
|
size_t Segment_Size = (size_t)va_arg( user_args, size_t );
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ALLOC";
|
|
|
|
/* On vérifie que le heap n'atteint pas sa limite */
|
|
if (MHH_Ptr->Limit_Size != SMD_UNLIMITED)
|
|
{
|
|
size_t Current_Size;
|
|
|
|
ND_DataStruct_Traverse (MHH_Ptr->DSR, NDD_CMD_VALUE_SUM, (void *)&Current_Size);
|
|
|
|
if (Current_Size + Segment_Size > MHH_Ptr->Limit_Size)
|
|
{
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_ALLOC : the heap limit size would be exceeded");
|
|
SM_Error_Print ();
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* Création de l'entête */
|
|
|
|
if( ND_Allocator_Exec( (void **)DSH_Ptr_Ptr, sizeof (SMT_DSH), MHH_Ptr->DSR->Allocator_Name, MHH_Ptr->DSR->Allocator_Ptr, NULL) != NDS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_ALLOC : unable to allocate memory for the new data segment header");
|
|
SM_Error_Print ();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Création d'un segment de mémoire partagée */
|
|
if (((*DSH_Ptr_Ptr)->MemId = shmget (IPC_PRIVATE, Segment_Size, 0777|IPC_CREAT|IPC_EXCL)) == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case EINVAL:
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_ALLOC : 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_DSR_Manager NDD_CMD_VALUE_ALLOC : the amount of memory is not sufficient to create the shared memory segment");
|
|
break;
|
|
|
|
case ENOSPC:
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_ALLOC : the number of shared memory segments exceeds the system-imposed limit");
|
|
break;
|
|
|
|
default :
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_ALLOC : unknown error (%d) while creating a shared memory segment", errno);
|
|
break;
|
|
}
|
|
|
|
SM_Error_Print ();
|
|
|
|
ND_Desallocator_Exec( (*DSH_Ptr_Ptr), MHH_Ptr->DSR->Desallocator_Name, MHH_Ptr->DSR->Desallocator_Ptr, NULL);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* On attache le segment de mémoire partagée au processus courant */
|
|
|
|
errno = 0;
|
|
#ifndef __hpux
|
|
(*DSH_Ptr_Ptr)->Start = shmat( (*DSH_Ptr_Ptr)->MemId, (void *)((size_t)(SM_Base->Attach) - Segment_Size), SHM_RND);
|
|
#else
|
|
(*DSH_Ptr_Ptr)->Start = shmat( (*DSH_Ptr_Ptr)->MemId, 0, 0);
|
|
#endif
|
|
if (errno)
|
|
{
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_ALLOC : unable to attach the shared memory segment to the current process (error %d)", errno);
|
|
SM_Error_Print ();
|
|
|
|
shmctl ((*DSH_Ptr_Ptr)->MemId, IPC_RMID, 0);
|
|
|
|
ND_Desallocator_Exec( *DSH_Ptr_Ptr, MHH_Ptr->DSR->Desallocator_Name, MHH_Ptr->DSR->Desallocator_Ptr, NULL);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
SM_Base->Attach = (*DSH_Ptr_Ptr)->Start;
|
|
|
|
/* Initialisation des informations de l'entête */
|
|
|
|
(*DSH_Ptr_Ptr)->Size = Segment_Size;
|
|
|
|
/* Création d'un chunk libre au début du segment de données */
|
|
|
|
Chunk_Node = (NDT_Node *)(*DSH_Ptr_Ptr)->Start;
|
|
|
|
Chunk = (SMT_Chunk *)((size_t)Chunk_Node + sizeof (NDT_Node) );
|
|
|
|
Chunk_Node->Value = Chunk;
|
|
|
|
Chunk->Data = (void *)((size_t)Chunk + sizeof (SMT_Chunk) );
|
|
|
|
Chunk->Size = (*DSH_Ptr_Ptr)->Size - sizeof (NDT_Node) - sizeof (SMT_Chunk);
|
|
|
|
/* Ajout du chunk libre à la liste des chunks libres du heap */
|
|
|
|
if (ND_Index_Node_Add( MHH_Ptr->FCR, NDD_INDEX_PRIMARY, Chunk_Node) != NDS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_ALLOC : unable to add a first chunk to the FCR structure of heap \"%s\"", MHH_Ptr->Name);
|
|
SM_Error_Print ();
|
|
|
|
shmctl ((*DSH_Ptr_Ptr)->MemId, IPC_RMID, 0);
|
|
|
|
ND_Desallocator_Exec( (*DSH_Ptr_Ptr), MHH_Ptr->DSR->Desallocator_Name, MHH_Ptr->DSR->Desallocator_Ptr, NULL);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_FREE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
SMT_DSH *DSH_Ptr = (SMT_DSH *)va_arg( Args, SMT_DSH *);
|
|
SMT_Status rc;
|
|
|
|
Command_Name = "NDD_CMD_VALUE_FREE";
|
|
|
|
|
|
/* Destruction du segment de mémoire partagée du segment de données */
|
|
|
|
if (shmctl (DSH_Ptr->MemId, IPC_RMID, 0) == -1)
|
|
{
|
|
switch (errno)
|
|
{
|
|
case EPERM:
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_FREE : current process (%d) is not allowed to destroy the shared memory segment %d", (int)getpid (), DSH_Ptr->MemId);
|
|
break;
|
|
|
|
case EINVAL:
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_FREE : no shared memory segment exists for identifier %d", DSH_Ptr->MemId);
|
|
break;
|
|
|
|
default :
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_FREE: unknown error %d while destroying the shared memory segment %d", errno, DSH_Ptr->MemId);
|
|
break;
|
|
}
|
|
|
|
SM_Error_Print ();
|
|
|
|
return SMS_ERRSHM;
|
|
}
|
|
|
|
/* Désallocation de l'entête */
|
|
|
|
rc = ND_Desallocator_Exec( DSH_Ptr, Root_Ptr->Desallocator_Name, Root_Ptr->Desallocator_Ptr, NULL);
|
|
if (rc != NDS_OK)
|
|
{
|
|
sprintf (SM_Error_Msg, "SM_DSR_Manager NDD_CMD_VALUE_FREE : the data segment header is nul");
|
|
SM_Error_Print ();
|
|
|
|
return rc;
|
|
}
|
|
|
|
return NDS_OK;
|
|
|
|
}
|
|
|
|
case NDD_CMD_VALUE_COMP:
|
|
{
|
|
/*
|
|
void *Value1_Ptr = (void *)va_arg( Args, void *);
|
|
void *Value2_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
SMT_DSH *DSH1_Ptr = (SMT_DSH *)va_arg( Args, SMT_DSH *);
|
|
SMT_DSH *DSH2_Ptr = (SMT_DSH *)va_arg( Args, SMT_DSH *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_COMP";
|
|
|
|
if( DSH1_Ptr->MemId < DSH2_Ptr->MemId) return( NDS_LOWER);
|
|
|
|
if( DSH1_Ptr->MemId > DSH2_Ptr->MemId) return( NDS_GREATER);
|
|
|
|
return( NDS_EQUAL);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ADD:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ADD";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_REMOVE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_REMOVE";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
SMT_DSH *DSH_Ptr = (SMT_DSH *)( Node_Ptr->Value);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_PRINT";
|
|
|
|
fprintf( Out, "Data Segment Header: Mem_Id: (%d) Start: (%p) Size: (%ld)\n",
|
|
DSH_Ptr->MemId, DSH_Ptr->Start, DSH_Ptr->Size);
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INFO_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INFO_PRINT";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_SUM:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
size_t *Total_Size = (size_t *)va_arg( user_args, size_t *);
|
|
|
|
SMT_DSH *DSH_Ptr = (SMT_DSH *)( Node_Ptr->Value);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_SUM";
|
|
|
|
*Total_Size += DSH_Ptr->Size;
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
default:
|
|
{
|
|
printf( "ND_Default_Manager() called with an undefined command %d\n", Command);
|
|
return( NDS_ERRAPI);
|
|
}
|
|
}
|
|
|
|
printf( "ND_Default_Manager() called with command %d (%s)\n", Command, Command_Name);
|
|
return( NDS_OK);
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Ouverture d'un segment de données */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_DataSegment_Open ( SMT_DSH *DSH)
|
|
{
|
|
void *Ptr;
|
|
|
|
/*
|
|
On attache le segment de mémoire partagée au processus courant.
|
|
|
|
Attention : il faut que ce segment soit attaché à la même adresse
|
|
que lorsqu'il a été créé afin que les pointeurs qui pointent dans
|
|
ce segment soient valides.
|
|
*/
|
|
|
|
shmdt ((void *)DSH->Start);
|
|
|
|
errno = 0;
|
|
Ptr = shmat( DSH->MemId, DSH->Start, 0);
|
|
if (errno)
|
|
{
|
|
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ées */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
SMT_Status SM_DataSegment_Close ( SMT_DSH *DSH)
|
|
{
|
|
/* On détache le segment de mémoire partagée du processus courant */
|
|
|
|
shmdt ((void *)DSH->Start);
|
|
|
|
return SMS_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Compression d'un segment de données */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
size_t SM_DataSegment_Compress ( SMT_DSH *DSH, NDT_Root *FCR)
|
|
{
|
|
size_t Total_Compress = 0;
|
|
size_t Compress;
|
|
SMT_Chunk *Chunk, *Next_Chunk;
|
|
NDT_Node * Node, *Next_Node;
|
|
void *DSH_End;
|
|
int Found = FALSE;
|
|
|
|
|
|
DSH_End = (void *)((size_t)(DSH->Start) + DSH->Size);
|
|
|
|
/* Recherche du premier chunk libre contenu dans le segment courant */
|
|
|
|
ND_Index_Node_First_Get( &Node, FCR, NDD_INDEX_PRIMARY);
|
|
|
|
while (Found == FALSE && Node)
|
|
{
|
|
if (Node > (NDT_Node *)DSH_End) Node = NULL;
|
|
else
|
|
{
|
|
if (Node >= (NDT_Node *)(DSH->Start)) Found = TRUE;
|
|
else ND_Index_Node_Next_Get( &Node, Node);
|
|
}
|
|
}
|
|
|
|
if (!Node) return 0;
|
|
|
|
/* Parcours de tous les chunks libres du segment courant */
|
|
|
|
ND_Index_Node_Next_Get( &Next_Node, Node);
|
|
|
|
while (Next_Node && (void *)Next_Node < DSH_End)
|
|
{
|
|
Chunk = (SMT_Chunk *)(Node->Value);
|
|
|
|
Next_Chunk = (SMT_Chunk *)(Next_Node->Value);
|
|
|
|
/* Si le chunk suivant est "collé" au chunk courant, alors on les fusionne */
|
|
|
|
if (Next_Node == (NDT_Node *)((size_t)(Chunk->Data) + Chunk->Size))
|
|
{
|
|
ND_Index_Node_Remove (Next_Node);
|
|
|
|
Compress = sizeof (SMT_Chunk) + sizeof (NDT_Node);
|
|
|
|
Chunk->Size += Next_Chunk->Size + Compress;
|
|
|
|
Total_Compress += Compress;
|
|
|
|
ND_Index_Node_Next_Get( &Next_Node, Node);
|
|
}
|
|
else
|
|
{
|
|
Node = Next_Node;
|
|
ND_Index_Node_Next_Get( &Next_Node, Next_Node);
|
|
}
|
|
}
|
|
|
|
return Total_Compress;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fonction de gestion de chunks */
|
|
/*------------------------------------------------------------------------------*/
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fonction manager pour un ACR (Allocated Chunk Root) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
NDT_Status SM_ACR_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list Args)
|
|
{
|
|
NDT_Command_Name Command_Name;
|
|
|
|
|
|
switch( Command)
|
|
{
|
|
case NDD_CMD_MANAGER_VERSION:
|
|
{
|
|
NDT_Version_Name *Version_Name_Ptr = (NDT_Version_Name *)va_arg( Args, NDT_Version_Name *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_MANAGER_VERSION";
|
|
|
|
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INDEX_GET:
|
|
{
|
|
/*
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
*/
|
|
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INDEX_GET";
|
|
|
|
switch( Cmd)
|
|
{
|
|
/*
|
|
case NDT_CMD_SOME_USER_CMD:
|
|
{
|
|
*Reply_Index_Id_Ptr = 0;
|
|
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
|
|
break;
|
|
}
|
|
|
|
...
|
|
*/
|
|
|
|
default:
|
|
{
|
|
*Reply_Index_Id_Ptr = Index_Id;
|
|
*Reply_Command_Ptr = Cmd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ALLOC:
|
|
{
|
|
/*
|
|
void **Value_Ptr_Ptr = (void **)va_arg( Args, void **);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ALLOC";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_FREE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
Command_Name = "NDD_CMD_VALUE_FREE";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_COMP:
|
|
{
|
|
/*
|
|
void *Value1_Ptr = (void *)va_arg( Args, void *);
|
|
void *Value2_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
SMT_Chunk *Chunk1_Ptr = (SMT_Chunk *)va_arg( Args, SMT_Chunk *);
|
|
SMT_Chunk *Chunk2_Ptr = (SMT_Chunk *)va_arg( Args, SMT_Chunk *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_COMP";
|
|
|
|
/* Les chunks alloués sont triés sur le champ <Data> (adresse d'allocation) */
|
|
|
|
if( Chunk1_Ptr->Data < Chunk1_Ptr->Data) return( NDS_LOWER);
|
|
|
|
if( Chunk1_Ptr->Data > Chunk2_Ptr->Data) return( NDS_GREATER);
|
|
|
|
return( NDS_EQUAL);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ADD:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ADD";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_REMOVE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_REMOVE";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
SMT_Chunk *Chunk_Ptr = (SMT_Chunk *)( Node_Ptr->Value);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_PRINT";
|
|
|
|
fprintf( Out, "Allocated Chunk: Chunk_Addr: (%p) Data_Addr: (%p) Data_Size: (%ld)\n",
|
|
Chunk_Ptr, Chunk_Ptr->Data, Chunk_Ptr->Size);
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INFO_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INFO_PRINT";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_SUM:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
size_t *Total_Size = (size_t *)va_arg( user_args, size_t *);
|
|
|
|
SMT_Chunk *Chunk_Ptr = (SMT_Chunk *)( Node_Ptr->Value);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_SUM";
|
|
|
|
*Total_Size += Chunk_Ptr->Size;
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
default:
|
|
{
|
|
printf( "ND_Default_Manager() called with an undefined command %d\n", Command);
|
|
return( NDS_ERRAPI);
|
|
}
|
|
}
|
|
|
|
printf( "ND_Default_Manager() called with command %d (%s)\n", Command, Command_Name);
|
|
return( NDS_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* Fonction manager pour un FCR (Free Chunk Root) */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
NDT_Status SM_FCR_Manager( NDT_Root *Root_Ptr, NDT_Index_Id Index_Id, NDT_Node *Node_Ptr, NDT_Command Command, va_list Args)
|
|
{
|
|
NDT_Command_Name Command_Name;
|
|
|
|
|
|
switch( Command)
|
|
{
|
|
case NDD_CMD_MANAGER_VERSION:
|
|
{
|
|
NDT_Version_Name *Version_Name_Ptr = (NDT_Version_Name *)va_arg( Args, NDT_Version_Name *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_MANAGER_VERSION";
|
|
|
|
*Version_Name_Ptr = "$Revision: 2.4 $ $Name: $ $Date: 2005/06/26 23:40:14 $ $Author: agibert $";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INDEX_GET:
|
|
{
|
|
/*
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
*/
|
|
|
|
NDT_Index_Id *Reply_Index_Id_Ptr = (NDT_Index_Id *)va_arg( Args, NDT_Index_Id *);
|
|
NDT_Command *Reply_Command_Ptr = (NDT_Command *)va_arg( Args, NDT_Command *);
|
|
NDT_Command Cmd = (NDT_Command)va_arg( Args, NDT_Command);
|
|
void *Value_ptr = (void *)va_arg( Args, void *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INDEX_GET";
|
|
|
|
switch( Cmd)
|
|
{
|
|
/*
|
|
case NDT_CMD_SOME_USER_CMD:
|
|
{
|
|
*Reply_Index_Id_Ptr = 0;
|
|
*Reply_Command_Ptr = NDD_CMD_SOME_OTHER_CMD;
|
|
break;
|
|
}
|
|
|
|
...
|
|
*/
|
|
|
|
default:
|
|
{
|
|
*Reply_Index_Id_Ptr = Index_Id;
|
|
*Reply_Command_Ptr = Cmd;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ALLOC:
|
|
{
|
|
/*
|
|
void **Value_Ptr_Ptr = (void **)va_arg( Args, void **);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ALLOC";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_FREE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
Command_Name = "NDD_CMD_VALUE_FREE";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_COMP:
|
|
{
|
|
/*
|
|
void *Value1_Ptr = (void *)va_arg( Args, void *);
|
|
void *Value2_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
SMT_Chunk *Chunk1_Ptr = (SMT_Chunk *)va_arg( Args, SMT_Chunk *);
|
|
SMT_Chunk *Chunk2_Ptr = (SMT_Chunk *)va_arg( Args, SMT_Chunk *);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_COMP";
|
|
|
|
/*
|
|
La comparaison des chunks libres porte sur le champ <Data>
|
|
pour faciliter la compression des heaps.
|
|
*/
|
|
|
|
if( Chunk1_Ptr->Data < Chunk1_Ptr->Data) return( NDS_LOWER);
|
|
|
|
if( Chunk1_Ptr->Data > Chunk2_Ptr->Data) return( NDS_GREATER);
|
|
|
|
return( NDS_EQUAL);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_ADD:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_ADD";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_REMOVE:
|
|
{
|
|
/*
|
|
void *Value_Ptr = (void *)va_arg( Args, void *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
*/
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_REMOVE";
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
SMT_Chunk *Chunk_Ptr = (SMT_Chunk *)( Node_Ptr->Value);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_PRINT";
|
|
|
|
fprintf( Out, "Free Chunk: Chunk_Addr: (%p) Data_Ptr: (%p) Size: (%ld)\n", Chunk_Ptr, Chunk_Ptr->Data, Chunk_Ptr->Size);
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_INFO_PRINT:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
|
|
|
|
Command_Name = "NDD_CMD_INFO_PRINT";
|
|
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
case NDD_CMD_VALUE_SUM:
|
|
{
|
|
/*
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list lib_args = (va_list)va_arg( Args, va_list);
|
|
FILE *Out = (FILE *)va_arg( lib_args, FILE *);
|
|
NDT_Recursive_Mode Recursive_Mode = (NDT_Recursive_Mode)va_arg( lib_args, NDT_Recursive_Mode);
|
|
NDT_Recursive_Depth Recursive_Depth = (NDT_Recursive_Depth)va_arg( lib_args, NDT_Recursive_Depth);
|
|
NDT_Recursive_Offset Recursive_Offset = (NDT_Recursive_Offset)va_arg( lib_args, NDT_Recursive_Offset);
|
|
va_list user_args = (va_list)va_arg( lib_args, va_list);
|
|
user_type user_data = (user_type)va_arg( user_args, user_type);
|
|
... = (...)va_arg( user_args, ...);
|
|
|
|
void *Value_Ptr = Node_Ptr->Value;
|
|
*/
|
|
|
|
NDT_Node *Next_Node_Ptr = (NDT_Node *)va_arg( Args, NDT_Node *);
|
|
va_list user_args = (va_list)va_arg( Args, va_list);
|
|
size_t *Total_Size = (size_t *)va_arg( user_args, size_t *);
|
|
|
|
SMT_Chunk *Chunk_Ptr = (SMT_Chunk *)( Node_Ptr->Value);
|
|
|
|
|
|
Command_Name = "NDD_CMD_VALUE_SUM";
|
|
|
|
*Total_Size += Chunk_Ptr->Size;
|
|
|
|
return( NDS_OK);
|
|
}
|
|
|
|
default:
|
|
{
|
|
printf( "ND_Default_Manager() called with an undefined command %d\n", Command);
|
|
return( NDS_ERRAPI);
|
|
}
|
|
}
|
|
|
|
printf( "ND_Default_Manager() called with command %d (%s)\n", Command, Command_Name);
|
|
return( NDS_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 écriture car cela pourrait aboutir à un deadlock entre deux processus
|
|
qui voudraient réaliser cette opération en même temps.
|
|
|
|
=> On passe donc par un déverrouillage intermédiaire.
|
|
*/
|
|
|
|
if ((rc = SM_Semaphore_Operate (MHH->SemId, SM_SemOp_RSL, 2)) != SMS_OK)
|
|
{
|
|
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 à l'état de verrouillage précédent */
|
|
|
|
SM_Semaphore_Operate (MHH->SemId, SM_SemOp_SSL, 2);
|
|
|
|
return rc;
|
|
}
|
|
}
|
|
else if (Lock_Mode & SMD_READ)
|
|
{
|
|
rc = SM_Semaphore_Operate (MHH->SemId, SM_SemOp_TSL, 2);
|
|
if (rc != SMS_OK)
|
|
{
|
|
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é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é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ère sous forme explicite l'état d'un verrou */
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
char *SM_Lock_Status_Get( const char *Type_Name, void *Struct_Ptr)
|
|
{
|
|
static char status[50];
|
|
int i, sem_id;
|
|
pid_t writer;
|
|
union semun sem_ctl;
|
|
|
|
|
|
if( !strcmp( Type_Name, "base"))
|
|
{
|
|
sem_id = SM_Base->SemId;
|
|
writer = SM_Base->Writer;
|
|
}
|
|
else
|
|
{
|
|
if( !strcmp( Type_Name, "heap"))
|
|
{
|
|
SMT_MHH *MHH_Ptr = (SMT_MHH *)Struct_Ptr;
|
|
|
|
sem_id = MHH_Ptr->SemId;
|
|
writer = MHH_Ptr->Writer;
|
|
}
|
|
else
|
|
{
|
|
strcpy( status, "Unknown");
|
|
return( status);
|
|
}
|
|
}
|
|
|
|
i = semctl( sem_id, 0, GETVAL, sem_ctl);
|
|
|
|
switch( i)
|
|
{
|
|
case 0:
|
|
{
|
|
sprintf( status, "Exclusive Lock for PId: (%ld)", writer);
|
|
break;
|
|
}
|
|
|
|
case 1:
|
|
{
|
|
sprintf( status, "Unlocked");
|
|
break;
|
|
}
|
|
|
|
default :
|
|
{
|
|
if( i < 0)
|
|
{
|
|
sprintf( status, "Abnormal Status: (%d)", i);
|
|
}
|
|
else
|
|
{
|
|
sprintf( status, "Shared Lock Process_Nb: (%d)", i - 1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( status);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
/* 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é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;
|
|
}
|