home *** CD-ROM | disk | FTP | other *** search
- /* memalloc.c 28-10-91 memory allocation routines for the Tierra simulator */
- /** Tierra Simulator V3.0: Copyright (c) 1991 Thomas S. Ray **/
-
- #include "license.h"
-
- #ifndef lint
- static char memalloc_sccsid[] = "%W% %G%";
- #endif
-
- #include <sys/types.h>
- #include "tierra.h"
- #include "extern.h"
-
- #ifdef SOCKETS
-
- #include "allayer.h"
- #include "tlayer.h"
-
- #endif
-
- /* check to see if cell has write privelage at address */
- I8s IsPriv(ce, a)
- Pcells ce;
- Ind a;
- {
- #ifdef ERROR
- if(a >= SoupSize || a < 0)
- { sprintf(mes[0],"IsPriv error: address %ld not in soup", a);
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"system being saved to disk");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- #endif
- if(IsInsideCell(ce, a)) return 1;
- return IsFree(a);
- }
-
- I8s IsBitPriv(ce,a,mode,track)
- Pcells ce;
- Ind a; /* address being checked */
- I8s mode, track;
- /* modes: 1 bit = execute, 2 bit = write, 4 bit = read */
- { if(a < 0 || a >= SoupSize)
- return 0;
- if(IsInsideCell(ce,a))
- return 1;
- else
- switch(mode)
- { case 1: return !soup[a][track].exec;
- case 2: return !soup[a][track].write;
- case 4: return !soup[a][track].read;
- case 6: return (!soup[a][track].read) && (!soup[a][track].write);
- default: return 0;
- }
- }
-
- /* check to see if address is inside allocated memory cell ce */
- I8s IsInsideCell(ce, a)
- Pcells ce;
- Ind a;
- {
- #ifdef ERROR
- if(a >= SoupSize || a < 0)
- { sprintf(mes[0],"IsInsideCell error: address %ld not in soup", a);
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"system being saved to disk");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- #endif
- if((ce->mm.p <= a && a < ce->mm.p + ce->mm.s) || (ce->md.s > 0 &&
- (ce->md.p <= a && a < ce->md.p + ce->md.s))) return 1; return 0;
- }
-
- /* check to see if address is free, not allocated by any cell */
- I8s IsFree(a)
- Ind a;
- { I32s j;
- I32s mp; /* index to element of FreeMem array */
- Pmf f;
-
- #ifdef ERROR
- if(a >= SoupSize || a < 0)
- { sprintf(mes[0],"IsFree error: address %ld not in soup", a);
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"system being saved to disk");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- #endif
- f = FreeMem; /* abbreviation for FreeMem */
- mp = FreeMem->n; /* this is the first free block */
- if(a < (f + mp)->p) return 0; j = 1;
- /* find block whose end is equal or above a: */
- while((f + mp)->p + (f + mp)->s < a)
- { mp = (f + mp)->n; j++;
- if(j > FreeBlocks) return 0;
- } /* is a in free block: */
- if((f + mp)->p <= a && a < (f + mp)->p + (f + mp)->s) return 1;
- return 0;
- }
-
- void WhichCell(a, ci, md) /* find cell with address a */
- Ind a; /* note: a must be in a cell!, call IsFree() before */
- I32s *ci; /* WhichCell() to find out if a is in a cell or not */
- I8s *md;
- { I32s i;
-
- for(i = 2; i < CellsSize; i++)
- { if((cells + i)->ld && (cells + i)->mm.p <= a &&
- ((cells + i)->mm.p + (cells + i)->mm.s - 1) >= a)
- { *ci = i; *md = 'm'; break; }
- if((cells + i)->ld && (cells + i)->md.p <= a &&
- ((cells + i)->md.p + (cells + i)->md.s - 1) >= a)
- { *ci = i; *md = 'd'; break; }
- }
- }
-
- Ind MemAlloc(size)
- I32s *size;
- { I32s j; /* counts the physical order of the free block we are indexing */
- I32s mb; /* memory block index */
- I32s pb; /* previous memory block index */
- Ind ti; /* temporary instruction location index, for return value */
-
- if(!*size || !FreeBlocks) { *size = 0; return 0; }
- mb = FreeMem->n; /* this is the first free block */
- pb = 0; /* this is SoupBot */
- j = 1; /* counts the physical order of the free block we are indexing */
- while((FreeMem + mb)->s < *size) /* find big enough free block */
- { pb = mb;
- mb = (FreeMem + mb)->n;
- j++;
- if(j > FreeBlocks) /* if memory is very fragmented, reap some: */
- { if(FreeMemCurrent > 3 * *size) fragment = 1;
- *size = 0; return 0;
- }
- }
- fragment = 0;
- FreeMemCurrent -= *size;
- if((FreeMem + mb)->s == *size) /* free block is exactly the right size */
- { (FreeMem + pb)->n = (FreeMem + mb)->n;
- (FreeMem + mb)->o = 0;
- FreeBlocks--;
- if((FreeMem + mb)->p > SoupSize)
- { sprintf(mes[0],"Tierra memalloc() error 1");
- FEMessage(1);
- }
-
- #ifdef SOCKETS
- TRepBirth( (FreeMem + mb)->p, *size );
- #endif
-
- return (FreeMem + mb)->p;
- }
- if((FreeMem + mb)->s > *size) /* free block bigger than needed */
- { ti = (FreeMem + mb)->p;
- if(ti > SoupSize)
- { sprintf(mes[0],"Tierra memalloc() error 2");
- FEMessage(1);
- }
- (FreeMem + mb)->p += *size;
- if((FreeMem + mb)->p > SoupSize)
- { sprintf(mes[0],"Tierra memalloc() error 3");
- FEMessage(1);
- }
- (FreeMem + mb)->s -= *size;
- if((FreeMem + mb)->s > SoupSize)
- { sprintf(mes[0],"Tierra memalloc() error 4");
- FEMessage(1);
- }
-
- #ifdef SOCKETS
- TRepBirth( ti, *size );
- #endif
-
- return ti;
- }
- return 0;
- }
-
- void MemDealloc(p, size)
- Ind p;
- I32s size;
- { I32s i, j, a, b, ola, olb, bt;
- Ind bb, ab, at, pt;
- Pmf f, tf;
-
- #ifdef SOCKETS
- TRepDeath( p, size );
- #endif
-
- #ifdef ERROR
- if(p < 0L || !size || p >= SoupSize)
- { sprintf(mes[0],"Tierra memory deallocation error 1");
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"system being saved to disk");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- #endif
- f = FreeMem; /* abbreviation for FreeMem */
- a = (f + SoupBot)->n; /* a will index free block above */
- b = SoupBot; /* b will index free block below */
- j = 1L;
- while(p >= (f + a)->p) /* find free block above block to be deallocated */
- { if(j > FreeBlocks) break;
- b = a; a = (f + a)->n; j++;
- }
- #ifdef ERROR
- if(p > (f + a)->p)
- { sprintf(mes[0],"Tierra memory deallocation error 2");
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"system being saved to disk");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- #endif
- bb = (f + b)->p; /* bb is address of bottom of b */
- /* bt is address of top of b */
- bt = (f + b)->p + (f + b)->s - 1L;
- ab = (f + a)->p; /* ab is address of bottom of a */
- at = (f + a)->p + (f + a)->s - 1L; /* at is address of top of a */
- pt = p + size - 1L; /* pt is address of top of p */
- if(pt > SoupSize - 1L)
- { sprintf(mes[0],"Tierra deallocation inconsistency 0");
- FEMessage(1);
- pt = SoupSize - 1L;
- size = pt - p + 1L;
- }
- if(bt > (p - 1L))
- { sprintf(mes[0],"Tierra deallocation inconsistency 1");
- FEMessage(1);
- }
- if(pt > ab - 1L)
- { sprintf(mes[0],"Tierra deallocation inconsistency 2");
- FEMessage(1);
- }
- if(bt >= p - 1L) olb = 1L; else olb = 0L; /* overlap with block below */
- if(pt >= ab - 1L) ola = 1L; else ola = 0L; /* overlap with block above */
- /* if block to be deallocated overlaps free blocks above and below: */
- if(ola && olb)
- { if(b == SoupBot)
- { FreeMemCurrent += ab - p;
- (f + a)->s = at - p + 1L;
- (f + a)->p = p; return ;
- }
- if(a == SoupTop)
- { FreeMemCurrent += pt - bt;
- (f + b)->s = pt - bb + 1L; return;
- }
- FreeMemCurrent += ab - bt - 1L;
- (f + b)->s = at - bb + 1L;
- (f + b)->n = (f + a)->n;
- /* neutralize f + a: */
- (f + a)->o = (I8s ) 0; (f + a)->p = (f + a)->s = 0L; (f + a)->n = a;
- FreeBlocks--; return;
- } /* block to be deallocated overlaps only free block above: */
- if(ola && a != SoupTop)
- { FreeMemCurrent += ab - p;
- (f + a)->s = at - p + 1L;
- (f + a)->p = p; return ;
- } /* block to be deallocated overlaps only free block below */
- if(olb && b != SoupBot)
- { FreeMemCurrent += pt - bt;
- (f + b)->s = pt - bb + 1L; return ;
- }
- j = 0L; /* block to be deallocated does not overlap any free block */
- while((FreeMem + j)->o)
- { if(++j == MaxFreeBlocks)
- { MaxFreeBlocks += 10L;
- tf = (Pmf) threalloc((I8s Hp) FreeMem,
- (I32u) MaxFreeBlocks * sizeof(struct mem_fr));
- if(tf == NULL)
- { sprintf(mes[0],"Tierra memalloc realloc error, exiting");
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"system being saved to disk");
- FEMessage(2);
- }
- while(hangup) ;
- WriteSoup(1);
- exit(0);
- }
- else f = FreeMem = tf;
- if (!hangup)
- FEMessage(1);
- else
- { sprintf(mes[1],"system being saved to disk");
- FEMessage(2);
- }
- #ifdef __TURBOC__
- sprintf(mes[0],"coreleft = %lu MemDealloc (FreeMem)",coreleft());
- FEMessage(1);
- #endif
- sprintf(mes[0],"lmemalloc: realloc, MaxFreeBlocks = %ld",
- MaxFreeBlocks);
- FEMessage(1);
- for(i = MaxFreeBlocks - 10L; i < MaxFreeBlocks; i++)
- { (f + i)->n = i;
- (f + i)->o = (I8s ) 0; (f + i)->p = (f + i)->s = 0L;
- }
- }
- }
- (f + j)->o = (I8s ) 1;
- (f + j)->n = a; (f + b)->n = j; FreeBlocks++;
- (f + j)->p = p;
- (f + j)->s = size;
- FreeMemCurrent += size;
- }
-