SpeicherTest.c


/*
 * SpeicherTest.c
 *
 * ============================================================================================================
 * Das Modul Testet die Freispeicherverwaltung auf Herz, Nieren und verlorene Pointer
 * ============================================================================================================
 */

#include "mxMMU.h"
#include "mxUhr.h"
#include "mxVektor.h"
#include "mxSystem.h"
#include "mxAbbruch.h"
#include "mxAusgabe.h"
#include "mxSpeicher.h"
#include "mxProzess.h"

/* -------------------------------------------------------------------------------------------------------------------- */
/************
** Defines **
************/

#define cST_Blockgroesse     8					        /* Schaetzung fuer sizeof(tFreispeicherKnoten)  */
#define cST_FuellZeichen     0x00					/* zum ueberschreiben der Header	        */
#define cST_TimeOut          (60 * cTicksProSekunde)

#define STget(charptr)       *((long*)(charptr))                        /* bel. Pointer derefenrenzieren als long       */

/* -------------------------------------------------------------------------------------------------------------------- */
/***************
** Strukturen **
***************/
typedef enum {
  eST_notNULL,
  eST_address,
  eST_round,
  eST_NULL,
  eST_wrongfreemem,
  eST_badnext,
  eST_badsize,
  eST_result,
  eST_init
} tST_Fehler;

/* -------------------------------------------------------------------------------------------------------------------- */
/**********************
** Globale Variablen **
**********************/
static int  ST_RestZeit;
static long ST_Frei;
static long *ST_Start;
static int  ST_next;
static int  ST_size;

/* -------------------------------------------------------------------------------------------------------------------- */
/***************
** Funktionen **
***************/

/* --------------------------------------------------------------------------------------------------------------------
 * TimeOut
 * -------------------------------------------------------------------------------------------------------------------- */

void ST_TimeOut(void)
{
  Lock();

  asm(/*MOVEM.L  D0-D7/A0-A6,-(SP)                                    */);/* Adress- und Datenregister retten             */

  ST_RestZeit--;
  if(ST_RestZeit <= 0)
  {
    kprintf(/*\nSpeicherTest TimeOut!!!\n%c*/, cEndeZeichen);             /* Termination anzeigen                         */
    StelleInterruptVektorenWiederHerUndSperreUhrInterrupt();            /* genau das                                    */
    _exit(42);                                                          /* fertig                                       */
  }

  asm(/*MOVEM.L  (SP)+,D0-D7/A0-A6                                    */);/* Adress- und Datenregister vom Stack holen    */
  asm(/*RTE                                                           */);/* Beenden der Uhren-Unterbrechung              */
}

/* --------------------------------------------------------------------------------------------------------------------
 * die Speichertestroutinen
 * -------------------------------------------------------------------------------------------------------------------- */

void ST_Fehler( tST_Fehler FehlerNummer )
{
  kprintf("\nFehler: ");
  switch(FehlerNummer)								/* entsprechend der Fehlernummer	*/
  {	                                                                        /* einen Fehlerstring ausgeben 		*/
    case eST_notNULL:      kprintf("Es wurde nicht der NULL-Pointer uebergeben!"); break;
    case eST_address:      kprintf("Nicht erwartete Segmentadresse erhalten!"); break;
    case eST_round:        kprintf("Die uebergebene Speichergroesse wurde nicht aufgerundet!"); break;
    case eST_NULL:         kprintf("Speicher holen gescheitert, obwohl noch Speicher vorhanden!"); break;
    case eST_wrongfreemem: kprintf("Gesamtmenge des freien Speichers in der Liste ist falsch!"); break;
    case eST_badnext:      kprintf("Ungueltiger Verkettungszeiger gefunden!"); break;
    case eST_badsize:      kprintf("Ungueltige Bloeckgroesse gefunden!"); break;
    case eST_result:       kprintf("Block der letzten Operation hat falschen Zustand!"); break;
    case eST_init:         kprintf("Datenstruktur ist falsch, implementierte Version nicht feststellbar!"); break;
    default:               kprintf("Unbekannter Fehler!"); break;
  }
  kprintf("\n");
  while(1);                                                             /* bis TimeOut                                  */
}

/* -------------------------------------------------------------------------------------------------------------------- */

void ST_HeaderLoeschen( char* SpeicherAdresse )
/* Ueberschreibt den Header des Speichersegments
 */
{
  int i;

  for(i=0; i<cST_Blockgroesse; i++)
  {
    SpeicherAdresse[i] = (char)cST_FuellZeichen;
  }
}

/* -------------------------------------------------------------------------------------------------------------------- */

void ST_WhichImpl( void )
{
  ST_Start = (long*)cFreispeicherStart;
  ST_Frei  = (long)cRAMEnd - (long)cFreispeicherStart;

  if (ST_Start[0] == 0 && ST_Start[1] == ST_Frei) {
    ST_next = 0;
    ST_size = 1;
  } else if (ST_Start[1] == 0 && ST_Start[0] == ST_Frei) {
    ST_next = 1;
    ST_size = 0;
  } else {
    ST_Fehler(eST_init);
  }
}

/* -------------------------------------------------------------------------------------------------------------------- */

void ST_ListWalk( void* Adresse, long Wieviel, int shouldbefree )
{
  long  *p;
  long  freisum = 0;
  int   isfree  = 0;

  if (ST_Frei == 0) return;

  for (p = ST_Start; p; freisum += p[ST_size], p = (long*)(p[ST_next])) {
    /* Test des Verkettungszeigers */
    if ((p[ST_next] && p[ST_next] < (long)p + p[ST_size] + 8) ||
	p[ST_next] > (long)cRAMEnd - 8 ||
	(p[ST_next] & 7) != 0) {
      kprintf("\n  Block=%d Block.next=%d Block.size=%d", (long)p, p[ST_next], p[ST_size]);
      ST_Fehler(eST_badnext);
    }
    /* Test der Blockgroesse */
    if ((p[ST_size] & 7) != 0 ||
	p[ST_size] <= 0 ||
	p[ST_size] > ST_Frei ||
	(long)p + p[ST_size] > (long)cRAMEnd) {
      kprintf("\n  Block=%d Block.next=%d Block.size=%d", (long)p, p[ST_next], p[ST_size]);
      ST_Fehler(eST_badsize);
    }
    /* Test des angegebenen Blocks */
    if ((long)p <= (long)Adresse && (long)p + p[ST_size] > (long)Adresse) {
      isfree = 1;
      if ((long)p + p[ST_size] < (long)Adresse + Wieviel) {
	kprintf("\n  Block=%d Block.next=%d Block.size=%d", (long)p, p[ST_next], p[ST_size]);
	ST_Fehler(eST_result);
      }
    }
    if (Adresse && (long)Adresse < (long)p && (long)Adresse + Wieviel > (long)p) {
      kprintf("\n  Block=%d Block.next=%d Block.size=%d", (long)p, p[ST_next], p[ST_size]);
      ST_Fehler(eST_result);
    }
  }

  if (Adresse && isfree != shouldbefree) {
    ST_Fehler(eST_result);
  }
  if (freisum != ST_Frei) {
    kprintf("\n  Frei=%d erwartet=%d", freisum, ST_Frei);
    ST_Fehler(eST_wrongfreemem);
  }
}

/* -------------------------------------------------------------------------------------------------------------------- */

void ST_HolenTest( char* String, long Wieviel, void* Adresse )
{
  char* segment;
  long* next;
  long  size;

  if (String[0]) kprintf(String);

  next = (long*)ST_Start[ST_next];
  size =        ST_Start[ST_size];
  segment = SpeicherHolen(Wieviel);
  if (Wieviel & 7)
  {
    Wieviel = (Wieviel & ~7) + 8;
  }

  if((segment == NULL ) && (Adresse != NULL))
  {
    ST_Fehler(eST_NULL);
  }
  else if(((long)segment & 7) != 0)
  {
    ST_Fehler(eST_round);
  }
  else if(segment != Adresse)
  {
    if(Adresse != NULL)
    {
      ST_Fehler(eST_address);
    }
    else
    {
      ST_Fehler(eST_notNULL);
    }
  }

  if(Adresse != NULL) {
    ST_Frei -= Wieviel;
    if (Adresse == ST_Start) ST_Start = (Wieviel == size? next : Adresse + Wieviel);
  }
  ST_ListWalk(Adresse, Wieviel, 0);

  if(Adresse != NULL)
  {					                                /* Header l"oschen falls Speicher		*/
    ST_HeaderLoeschen(segment); 					/* angefordert werden konnte 			*/
  }
  if (String[0]) kprintf(" ok\n");
}

/* -------------------------------------------------------------------------------------------------------------------- */

void ST_FreigebenTest( char* String, void* Wo, long Wieviel )
{
  if (String[0]) kprintf(String);
  SpeicherFreigeben(Wo,Wieviel);
  if (Wieviel & 7)
  {
    Wieviel = (Wieviel & ~7) + 8;
  }
  if (Wo == NULL || Wieviel == 0) {
    Wo      = NULL;
    Wieviel = 0;
  } else {
    ST_Frei += Wieviel;
    if (ST_Start==NULL || (long)Wo < (long)ST_Start) ST_Start = Wo;
  }
  ST_ListWalk(Wo, Wieviel, 1);
  if (String[0]) kprintf(" ok\n");
}

/* -------------------------------------------------------------------------------------------------------------------- */

void ST_Zusammenlegen( void* First, long Blockgroesse )
/* gibt drei Speicherbl"ocke in unterschiedlicher Reihenfolge frei und fordert den frei werdenden Speicher wieder an
 * pre : die freien Speicherbloecke vor first m"ussen kleiner als die blockgroesse sein,
 *       der Speicher von first bis first + ( blockgroesse * 3 ) ist belegt
 */
{
  char* second  = First  + Blockgroesse;				       	/* hier liegen die folgenen Bl"ocke 	*/
  char* third   = second + Blockgroesse;			                /* die Adressen der drei Speicherbl"ocke*/
  long  wieviel = Blockgroesse - 1;						/* die angeforderte Speichergroesse	*/

  /* zwei angrenzende Bloecke freigeben -- das vordere zuerst */
  kprintf("Zwei angrenzende Bloecke freigeben -- das vordere zuerst:");
  ST_FreigebenTest(/**/, First, wieviel);						/* den ersten Block freigeben 		*/
  ST_FreigebenTest(/**/, second,wieviel);						/* und den anschlie|3enden Block auch 	*/
  ST_HolenTest(/**/, (Blockgroesse * 2 ) - 1, First);        			/* einen doppelt so grossen Block anf.	*/
  ST_HolenTest(/**/, Blockgroesse, NULL);        		        		/* soviel Speicher darf nicht mehr 	*/
  kprintf(" ok\n");

  /* s.o. diesmal allerdings das hintere zuerst */
  kprintf("Zwei angrenzende Bloecke freigeben -- das hintere zuerst:");
  ST_FreigebenTest(/**/, second,wieviel);						/* den zweiten Block freigeben 		*/
  ST_FreigebenTest(/**/, First, wieviel);						/* den ersten ebenfalls freigeben 	*/
  ST_HolenTest(/**/, (Blockgroesse * 2 ) - 1, First); 			        /* den doppelten Speicher anfordern	*/
  ST_HolenTest(/**/, Blockgroesse, NULL);          				/* soviel Speicher darf nicht mehr 	*/
  kprintf(" ok\n");

  /* drei angrenzende Bl"ocke freigeben -- mittlerer zuletzt */
  kprintf("Drei angrenzende Bloecke freigeben -- das mittlere zuletzt:");
  ST_FreigebenTest(/**/, First, wieviel);						/* ersten Block freigeben 		*/
  ST_FreigebenTest(/**/, third, wieviel);						/* den letzten Block freigeben 		*/
  ST_FreigebenTest(/**/, second,wieviel);						/* und auch den mittleren freigeben 	*/
  ST_HolenTest(/**/, (Blockgroesse * 3 ) - 1, First);      			/* den gesamten Speicher anfordern 	*/
  ST_HolenTest(/**/, Blockgroesse, NULL);         				/* soviel Speicher darf nicht mehr 	*/
  kprintf(" ok\n");
}

/* -------------------------------------------------------------------------------------------------------------------- */

void SpeicherTest(void)
{
  char* speicher;                	                                /* Anfangsadresse des Speichers         	*/
  long  gesamt;                                                         /* zu verwaltender Speicher 		        */
  long  wieviel;
  long  blockgroesse;
  void (*alteUhrUnterbrechungsBehandlungsRoutine)();

  /* Bildschirm loeschen und Cursor in die linke obere Ecke platzieren */
  kprintf("\033[2J");
  kprintf("\033[1;1H");

  /* TimeOut anwerfen */
  ST_RestZeit = cST_TimeOut;
  Lock();
  alteUhrUnterbrechungsBehandlungsRoutine = LiesInterruptVektor(cUhrInterruptVektor);
  SetzeInterruptVektor(cUhrInterruptVektor,ST_TimeOut);
  Unlock();

  /* Variablen initialisieren		*/
  speicher = (char*)cFreispeicherStart;
  gesamt = (long)cRAMEnd - (long)speicher;
  ST_WhichImpl();

  kprintf("### Grundlegender Funktionstest\n");
  ST_HolenTest( "Anfordern eines Speicherblocks mit Groesse 0:", 0, NULL );
  ST_HolenTest( "Einen Speicherblock holen:", 1024, speicher );
  ST_FreigebenTest( "und wieder freigeben:" , speicher, 1024 );
  wieviel = 1024 - 4;								/* 1KB anfordern 			*/
  blockgroesse = (( wieviel + 7 ) / 8 ) * 8;					/* aufrunden 				*/
  ST_HolenTest( "Anfordern eines Speicherblocks > 0:", wieviel, speicher );
  ST_HolenTest( "Test ob naechster Block direkt dahinter liegt:", 1, speicher + blockgroesse );
  ST_FreigebenTest( "Der gesamte Speicher wird auf einmal freigegeben:",  speicher, blockgroesse + 1 );

  kprintf("### Test mit vollstaendiger Speicherbelegung\n");
  /* den ges. Speicher am Stück holen 	*/
  ST_HolenTest( "Anfordern des gesamten Speichers in einem Segment:", gesamt, speicher );
  ST_HolenTest( "Scheitert naechstes SpeicherHolen?", 1, NULL );
  /* nichts freigeben 			*/
  ST_FreigebenTest( "Freigeben eines leeren Speicherblocks:", speicher, 0  );
  ST_FreigebenTest( "Freigeben eines NULL-Pointers:", NULL,42  );
  ST_HolenTest( "Scheitert naechstes SpeicherHolen immer noch?", 1, NULL );
  ST_FreigebenTest( "Der gesamte Speicher wird wieder freigeben:",
		    speicher, gesamt );			                        /* und wieder Friegeben 		*/
  ST_HolenTest( "Einen Speicherblock holen:", 1024, speicher );
  ST_FreigebenTest( "  und wieder freigeben:" , speicher, 1024 );

  kprintf("### Test, ob First-Fit richtig funktioniert\n");
  ST_HolenTest( "Anfordern des gesamten Speichers in einem Segment:", gesamt, speicher );
  ST_FreigebenTest( "1KB nach 1KB freigeben:", speicher+1024, 1024 );
  ST_FreigebenTest( "2KB nach 3KB freigeben:", speicher+3*1024, 2*1024 );
  ST_FreigebenTest( "3KB nach 6KB freigeben:", speicher+6*1024, 3*1024 );
  ST_HolenTest( "Anfordern 3KB:", 3*1024, speicher+6*1024 );
  ST_FreigebenTest( "3KB wieder freigeben:", speicher+6*1024, 3*1024 );
  ST_HolenTest( "Anfordern 2KB:", 2*1024, speicher+3*1024 );
  ST_FreigebenTest( "2KB wieder freigeben:", speicher+3*1024, 2*1024 );
  ST_HolenTest( "Anfordern 1.5KB:", 1600, speicher+3*1024 );
  ST_HolenTest( "Anfordern 1KB:", 1024, speicher+1024 );
  ST_HolenTest( "kann noch 4KB Block gefunden werden?", 4*1024, NULL );
  ST_HolenTest( "kann noch 0.5KB Block gefunden werden?", 2*1024-1600, speicher+3*1024+1600  );
  ST_HolenTest( "kann noch 3KB Block gefunden werden?", 3*1024, speicher+6*1024  );
  ST_HolenTest( "Ist der gesamte Speicher jetzt belegt?", 1, NULL );
  ST_Zusammenlegen( speicher + 1024, 1024 );
  ST_FreigebenTest( "Vor den drei Segmenten wird ein kleiner Speicherblock freigegeben:", speicher, 1024 / 2 );
  ST_Zusammenlegen( speicher + 1024, 1024 );
  ST_HolenTest( "Kleiner Speicherblock wird wieder belegt:", 1024 / 2, speicher );
  ST_FreigebenTest( "Gesamter Speicher wird wieder freigegeben:", speicher, gesamt);

  kprintf("### Test, ob freie Bloecke richtig zusammengelegt werden\n");
  ST_HolenTest( "Belegen des ersten  Speicherviertels:", gesamt/4, speicher+0*(gesamt/4));
  ST_HolenTest( "Belegen des zweiten Speicherviertels:", gesamt/4, speicher+1*(gesamt/4));
  ST_HolenTest( "Belegen des dritten Speicherviertels:", gesamt/4, speicher+2*(gesamt/4));
  ST_HolenTest( "Belegen des vierten Speicherviertels:", gesamt/4, speicher+3*(gesamt/4));
  ST_FreigebenTest( "Freigeben des zweiten Speicherviertels:", speicher+1*(gesamt/4), gesamt/4);
  ST_FreigebenTest( "Freigeben des vierten Speicherviertels:", speicher+3*(gesamt/4), gesamt/4);
  ST_FreigebenTest( "Freigeben des dritten Speicherviertels:", speicher+2*(gesamt/4), gesamt/4);
  ST_HolenTest( "Koennen jetzt 3/4 der Gesamtgroesse belegt werden?", 3*(gesamt/4), speicher+1*(gesamt/4));
  ST_FreigebenTest( "Freigeben des dritten Speicherviertels:", speicher+2*(gesamt/4), gesamt/4);
  ST_FreigebenTest( "Freigeben des vierten Speicherviertels:", speicher+3*(gesamt/4), gesamt/4);
  ST_FreigebenTest( "Freigeben des zweiten Speicherviertels:", speicher+1*(gesamt/4), gesamt/4);
  ST_FreigebenTest( "Freigeben des ersten  Speicherviertels:", speicher+0*(gesamt/4), gesamt/4);

  kprintf("### Test, ob immer noch der ganze Speicher da ist\n");
  ST_HolenTest( "Anfordern des gesamten Speichers in einem Segment:", gesamt, speicher );
  ST_HolenTest( "Scheitert naechstes SpeicherHolen?", 1, NULL );
  ST_FreigebenTest( "Gesamten Speicher zum Abschluss freigeben:", speicher, gesamt);

  kprintf("\n >>>>>  SpeicherTest hat keinen Fehler gefunden!  <<<<<");

  /* Ende */
  Lock();
  SetzeInterruptVektor(cUhrInterruptVektor,alteUhrUnterbrechungsBehandlungsRoutine);
  Unlock();
  Schlafe(10000);
}


Bei Problemen mit der Seite bitte eine Mail an Marek
Converted with C2HTML V0.669 by Iluvatar
Prozeßdatenverarbeitung