#ifndef _GC_H
#define _GC_H

#define NUMBER_OF_TREADMILLS 9
#define NOT_ENOUGH_MEM 0 /* What the allocation function should return
			    if there is not enought memory */

/* Global treadmill storage */
struct sTreadmill *treadmill_index[NUMBER_OF_TREADMILLS];

/* The two global pointers required to store information
 * about the large objects queue */
struct sLargeBlock *large_treadmill;
struct sLargeBlock *large_treadmill_tail;

/* The overhead for both large blocks and small blocks are the
 * same. */
#define OVERHEAD 16

struct sLargeBlock
{
	struct sLargeBlock *next;
	unsigned int size; 
	/* Size is the size of data without the overhead of the
	 * sLargeBlock structure. */
	
	unsigned int flags;
	unsigned int padding; /* Padding */
	char data[1];
	
};

struct sBlock
{

  struct sBlock *clockwise;
  struct sBlock *counterclockwise;
  unsigned int flags;
  unsigned int padding;
/* 
 * The data part of this structure is a placeholder.
 * The *start* of the data section begins at data[0] and
 * expands from there to the size as specified on the 
 * treadmill.  data is not actually an array of 1 character,
 * rather a placeholder so we may simply return it to the
 * function that called allocate.  It could be done by
 * some pointer manipulation, but why make life more 
 * complicated than it needs to be. 
 * Heres hoping they never fix c's ability to run over
 * the end of arrays :-) */
  char data[1];

};

struct sFreeObject
{
	int size;
	struct sFreeObject *next;
};

struct sFreeObject *FreeList;
struct sFreeObject *FreeListTail;

struct sTreadmill
{
  
  int size;
  struct sBlock *Free;
  struct sBlock *LastFree;
  struct sBlock *From;
  struct sBlock *Scan;

};

void GC_init();
unsigned char * alloc_first_page( int size );
void * alloc ( int size );
void garbage_collect();
void start_collection();

#endif
