/* ##C_FILE#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FILE :          CpaMmg.c
 
DESCRIPTION :   this file contain all functions used to allocate memory :
		
		Initialisation of the module
		Initialisation of a static bloc
		switch between dynamic and static mode
		Allocate/ReAllocate/Free Memory
		Check function for debugging
		Destroy a static bloc
		Destroy the module
 
VERSION :       5.1.0/Pierrick Crepy/Creation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
/* ##INCLUDE#----------------------------------------------------------------------------
                          Includes Files
---------------------------------------------------------------------------------------*/
#include "ERM.h"
 
#include "MMG/CpaMmg.h"
#include "..\PrivMmg.h"
 
 
 
 
/* ##F#===================================================================================
NAME :          Mmg_fn_vPrintUsedStaticMemory
DESCRIPTION :   this function print the state of the statsic memory in 
				the file C_szErrorLogFileName
INPUT :			Module Id
				poniter on a block structure
=========================================================================================
CREATION : 06-11-97/Pierrick Crepy
=======================================================================================*/
void Mmg_fn_vPrintUsedStaticMemory(unsigned char ucModuleId, struct tdstBlockInfoPriv_ * a_stMyBlockInfo, unsigned char ucModuleMaxBlocksNb){
        unsigned char ucBlockId;
		char szTxt[200];
		unsigned long ulNbMalloc;
		unsigned long ulNbFree;
        tdstBlockInfoPriv *p_stMyBlockInfo;
        unitAlloc * p_uaPtr;		
        unitAlloc * p_uaFreePtr;
		unitAlloc uaTotalAllocatedSize;		
		unitAlloc uaTotalFreeSize;
		unitAlloc uaRemainSpace;
		unitAlloc uaBlockSize;
		unitAlloc uaMaxUsed;
	     		
		sprintf (szTxt, "\n===> Print the used Static memory on ");
		Erm_M_GetModuleInformation (szTxt+strlen(szTxt), ucModuleId);
		sprintf (szTxt+strlen(szTxt), " : <===\n");
		Erm_fn_v_Printsz (szTxt);
 
#ifdef __DEBUG_MALLOC_MODE__
		Erm_fn_v_Printsz ("===> With __DEBUG_MALLOC_MODE__ <===\n\n");				
#else /*__DEBUG_MALLOC_MODE__*/
		Erm_fn_v_Printsz ("===> Without __DEBUG_MALLOC_MODE__ <===\n\n");				
#endif /*__DEBUG_MALLOC_MODE__*/
 
		sprintf( szTxt, "Module Id = %d\n", ucModuleId );
		Erm_fn_v_Printsz( szTxt );
		if( a_stMyBlockInfo == NULL )
		{
			Erm_fn_v_Printsz( "\tThe info are not valid !!!\n" );
			return;
		}
 
        for (ucBlockId=0; ucBlockId<ucModuleMaxBlocksNb; ucBlockId++){
				p_stMyBlockInfo = a_stMyBlockInfo + ucBlockId;
 
				sprintf(szTxt, "\tThe block #%d:\n", ucBlockId);
				Erm_fn_v_Printsz (szTxt);
 
 
				/*Block whithout Free.*/
				if ((p_stMyBlockInfo->p_cBeginBlock != C_p_cBlockNotValidKey) &&
					(p_stMyBlockInfo->p_cFirstFree == C_FirstFreeValueForBlockWithoutFree)
					){
					uaBlockSize = p_stMyBlockInfo->p_cEndBlock - p_stMyBlockInfo->p_cBeginBlock +1;
 
					uaMaxUsed = p_stMyBlockInfo->p_cMaxMem - p_stMyBlockInfo->p_cBeginBlock +1;					
 
#ifdef D_CheckSystemForBlockWithoutFree
					uaMaxUsed -= (((tdstInformationHeaderOfBolckWithoutFree *)p_stMyBlockInfo->p_cBeginBlock)->ucBoundededHeaderSize);
					uaBlockSize -= (((tdstInformationHeaderOfBolckWithoutFree *)p_stMyBlockInfo->p_cBeginBlock)->ucBoundededHeaderSize);
#endif /*D_CheckSystemForBlockWithoutFree*/
 
					Erm_fn_v_Printsz ("\t\t --> MaxMen status: The higher address used in this block without Free\n");
					sprintf (szTxt, "\t\t\t -> %.2f%%%% used i.e %ldb (%.2fKb; %.2fMb) / %ldb (%.2fKb; %.2fMb)\n",									
						((float)uaMaxUsed * 100 / (float)uaBlockSize),
						(unsigned long)uaMaxUsed, (float)uaMaxUsed/1024, (float)uaMaxUsed/(1024*1024),
						(unsigned long)uaBlockSize, (float)uaBlockSize/1024, (float)uaBlockSize/(1024*1024)
					);
					Erm_fn_v_Printsz (szTxt);
 
					continue;/* go to the next Block (ucBlockId)*/
				}
 
 
				p_uaPtr=(unitAlloc *)p_stMyBlockInfo->p_cBeginBlock;
				p_uaFreePtr = (unitAlloc *)p_stMyBlockInfo->p_cFirstFree;
				uaTotalAllocatedSize = 0;
				uaTotalFreeSize = 0;
				ulNbFree = 0;
				ulNbMalloc =0;
				while (p_uaPtr < (unitAlloc *)p_stMyBlockInfo->p_cEndBlock){/* scan all malloc*/
					if (p_uaFreePtr == p_uaPtr){/* it's a free						*/
						if (((unitAlloc *) *(p_uaFreePtr+1)) != (unitAlloc *) 0){
							/* not the last free*/
							p_uaFreePtr = (unitAlloc *) *(p_uaFreePtr+1); /* go to the next free*/
							ulNbFree++;
							uaTotalFreeSize  += *p_uaPtr;
						}
					}
					else{/* this is a malloc*/
						uaTotalAllocatedSize += *p_uaPtr;
						ulNbMalloc++;
					}
					p_uaPtr += *(p_uaPtr);
				}/*end of while*/
 
				if (p_uaPtr != (unitAlloc *)(p_stMyBlockInfo->p_cEndBlock + 1)){
					Erm_fn_v_Printsz ("\t\t --> not valid (should be not initialized)\n");
				}
				else {
					uaBlockSize = p_stMyBlockInfo->p_cEndBlock - p_stMyBlockInfo->p_cBeginBlock +1;
					uaMaxUsed = p_stMyBlockInfo->p_cMaxMem - p_stMyBlockInfo->p_cBeginBlock +1;					
					if ( (unitAlloc *) (p_uaFreePtr) == (unitAlloc *) NULL){
						/*all the space is used !!*/
						uaRemainSpace = 0;
					}
					else {
						uaRemainSpace = ((*p_uaFreePtr)<<C_uwShiftAllocSize);
					}
 
#ifdef __DEBUG_MALLOC_MODE__
					uaBlockSize -= (p_stMyBlockInfo->ulMaxNbStaticMalloc*(C_ucDebugInformationLoss<<C_uwShiftAllocSize));
					uaMaxUsed -= ( (p_stMyBlockInfo->ulCountMallocBeforeMaxMem * C_ucDebugInformationLoss)) << C_uwShiftAllocSize;
					uaTotalAllocatedSize -= ( (ulNbMalloc * C_ucDebugInformationLoss));
#endif /*__DEBUG_MALLOC_MODE__*/
 
					uaTotalAllocatedSize <<= C_uwShiftAllocSize;
					uaTotalFreeSize <<= C_uwShiftAllocSize;
									
					Erm_fn_v_Printsz ("\t\t --> MaxMen status: The higher allocation\n");
					sprintf (szTxt, "\t\t\t -> %.2f%%%% used i.e %ldb (%.2fKb; %.2fMb) / %ldb (%.2fKb; %.2fMb)\n",									
						((float)uaMaxUsed * 100 / (float)uaBlockSize),
						(unsigned long)uaMaxUsed, (float)uaMaxUsed/1024, (float)uaMaxUsed/(1024*1024),
						(unsigned long)uaBlockSize, (float)uaBlockSize/1024, (float)uaBlockSize/(1024*1024)
					);
					Erm_fn_v_Printsz (szTxt);
#ifdef __DEBUG_MALLOC_MODE__
					sprintf (szTxt, "\t\t\t -> With %d allocation(s) & %d free(s)\n", p_stMyBlockInfo->ulCountMallocBeforeMaxMem, p_stMyBlockInfo->ulCountFreeBeforeMaxMem);
					Erm_fn_v_Printsz (szTxt);
#endif /*__DEBUG_MALLOC_MODE__*/
 
					Erm_fn_v_Printsz ("\t\t --> Current status:\n");
					sprintf (szTxt, "\t\t\t ->%.2f%%%% used  for allocation,  i.e %ldb (%.2fKb; %.2fMb) / %ldb (%.2fKb; %.2fMb)\n",									
						((float)uaTotalAllocatedSize * 100 / (float)uaBlockSize),
						(unsigned long)uaTotalAllocatedSize, (float)uaTotalAllocatedSize/1024, (float)uaTotalAllocatedSize/(1024*1024),
						(unsigned long)uaBlockSize, (float)uaBlockSize/1024, (float)uaBlockSize/(1024*1024)
					);
					Erm_fn_v_Printsz (szTxt);
#ifndef __DEBUG_MALLOC_MODE__
					sprintf (szTxt, "\t\t\t ->%.2f%%%% lost for the management of free, i.e %ldb (%.2fKb; %.2fMb) / %ldb (%.2fKb; %.2fMb)\n",									
						((float)uaTotalFreeSize * 100 / (float)uaBlockSize),
						(unsigned long)uaTotalFreeSize, (float)uaTotalFreeSize/1024, (float)uaTotalFreeSize/(1024*1024),
						(unsigned long)uaBlockSize, (float)uaBlockSize/1024, (float)uaBlockSize/(1024*1024)
					);
					Erm_fn_v_Printsz (szTxt);
					sprintf (szTxt, "\t\t\t ->%.2f%%%% remain i.e %ldb (%.2fKb; %.2fMb) / %ldb (%.2fKb; %.2fMb)\n",									
						((float)uaRemainSpace * 100 / (float)uaBlockSize),
						(unsigned long)uaRemainSpace, (float)uaRemainSpace/1024, (float)uaRemainSpace/(1024*1024),
						(unsigned long)uaBlockSize, (float)uaBlockSize/1024, (float)uaBlockSize/(1024*1024)
					);
					Erm_fn_v_Printsz (szTxt);
#endif /*__DEBUG_MALLOC_MODE__*/
					sprintf (szTxt, "\t\t\t -> There are %d allocation(s) & %d free(s)\n", ulNbMalloc, ulNbFree);
					Erm_fn_v_Printsz (szTxt);
				}
        }/* end of the for block*/
}/* Mmg_fn_vPrintUsedStaticMemory*/
