/* fixedalloc.c
    simple allocator for allocate once and pools
    L. Stewart, March 6, 1983  2:55 PM, created
    L. Stewart, March 9, 1983  7:50 PM, Zero allocated space
    L. Stewart, March 10, 1983  11:59 AM, round up
 */

#include	"env.h"
#include	"ec.h"
#include	"Queue.h"

#define memTop 0xCFFE

struct Pool {
  struct Queue freeList;
  int owner;
  int numItems;
  int lenItem;
  };
#define lenPool (sizeof(struct Pool) / 2)

struct GFOb {
  int owner;
  int owner2;
  int length;
  int data[1];
  };
#define lenGFOb 3

extern int end;	/* See endml.asm; end of static storage */

int *endFixed;
int totAv;

/* initialize GetFixed allocator */
InitFA()
  {
  int ans;
  ans = (int) &end;
  ans = (ans + 1) & -2;  /* round up */
  endFixed = (int *) ans;
  Zero(endFixed, FixedLeft());
  };

/* how many words are available? */
int FixedLeft()
  {
  int ans;
  ans = (int) endFixed;
  totAv = (memTop - ans) >> 1;
  return (totAv);
  };

/* allocate nWords words */

int *GetFixed(nWords)
  int nWords;
  {
  struct GFOb *fp;
  /* reserve space for header for next cell as well */
  if (Ugt(endFixed + nWords + lenGFOb + lenGFOb, memTop)) CallDebugger(ecAllocate+5);
  fp = (struct GFOb *) endFixed;
  endFixed += lenGFOb;
  endFixed += nWords;
  /* zero this header and the next header as well */
  /* probably not needed */
  Zero(fp, lenGFOb + nWords + lenGFOb);
  fp->length = nWords;
  fp->owner = ReturnLoc(MyFrame());
  fp->owner2 = ReturnLoc(CallersFrame(MyFrame()));
  return(&fp->data[0]);
  };

/* use GetFixed to create a pool of items which can thereafter
    be allocated or freed using GetItem and FreeItem
 */
struct Pool *CreatePool(itemSize, nItems)
  int itemSize, nItems;
  {
  struct Pool *pool;
  int i;
  pool = (struct Pool *) GetFixed(lenPool);
  InitQueue(&pool->freeList);
  pool->owner = ReturnLoc(MyFrame());
  pool->numItems = nItems;
  pool->lenItem = itemSize;
  for (i = 0; i < nItems; i += 1) Enqueue(&pool->freeList, GetFixed(itemSize));
  };

int *GetItem(pool)
  struct Pool *pool;
  {
  return(Dequeue(&pool->freeList));
  };

FreeItem(pool, item)
  struct Pool *pool;
  int *item;
  {
  Enqueue(&pool->freeList, item);
  };