/*
    Copyright 2001 (c) by Boris Lutz,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/VMemory/Attic/HeapAllocator.h,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/


#ifndef __MEMORYMANAGER_H__ /* XXX */
#define __MEMORYMANAGER_H__

#include "Topsy.h"
#include "types.h"
#include "Lock.h"


#include "MemoryLayout.h"

#define FRAGBITS            4
#define FRAGSIZE            (1 << FRAGBITS)
#define FRAGMASK            (FRAGSIZE - 1)
#define FRAGFRAMEMASK       (~FRAGMASK)
#define SUBROUND(x) 				(((x) + FRAGMASK) & FRAGFRAMEMASK)

#define NUMBEROFFRAGS		16

/* #define FRAGCHUNKSIZE = ( FRAGSIZE + sizeof(address_t) ) * NUMBEROFFRAGS */
#define FRAGCHUNKSIZE		320
/* #define FRAGDATASIZE = FRAGSIZE * NUMBEROFFRAGS */
#define FRAGDATASIZE		256
/* LARGESTSUBSIZE must be equal or smaller than FRAGDATASIZE - FRAGSIZE */
#define LARGESTSUBSIZE	(FRAGDATASIZE - (FRAGSIZE << 1))

#define GET_FRAGMENT		1
#define GET_CONTINOUS		0
// // don't change the mask bits
#define FREE_MASK				0x0
#define SINGLE_MASK			0x2	/* 10 */
#define STARTCONT_MASK	0x1	/* 01 */
#define CONTELEM_MASK		0x3	/* 11 */
#define CUTTER_MASK			0xFFFFFFFC
#define MAGIC_NUMBER		0xD5C1E950
// flags
#define IS_FRAGMENTED_M	0x1
#define LOCKED_MASK			0x4

#define NO_LOCK					0
#define USE_LOCK				1

#define HA_OK						0
#define HA_FAILED				1
#define HA_NOMEM				2
#define HA_NONFATAL			3
#define HA_WOULDBLOCK		4

#define LOCK_OK					0
#define LOCK_FAILED			1
#define LOCK_ERROR			2
#define LOCK_WOULDBLOCK		4

// enable extra checking to see if pointer given to free is correct
#define WITHMAGIC

// if enabled returns the first match when looking for a fragment
// otherwise the best match is returned
//#define FRAG_FIRST_MATCH

// marks empty fragment chunks as continous and makes them eglible
// for concatenating
#define RM_EMPTY_FRAG


/* The main structure are chunks containing a header linked by next & prev */
typedef struct MemChunkHeadEntry
{
  struct MemChunkHeadEntry*	prev;					// Pointer to the previos chunk
  struct MemChunkHeadEntry*	end;					// Pointer to the end of the chunk + 1
  // that's usually the next header except
  // for the last header!!!
  struct MemChunkHeadEntry*	tree_smaller;	// pointer to next smaller element if free
  struct MemChunkHeadEntry*	tree_larger;	// pointer to next larger or equal element if free
  struct MemChunkHeadEntry*	tree_prev;		// pointer to the previous tree element if free
  size_t		tree_fsize;		// free size
#ifdef WITHMAGIC

  uint32		magic;				// for sanity checks
#endif

  uint32		flags;				// for marking fragmented, locking and future use :)
  address_t	head;					// pointer to top of this header
}
MemChunkHeadEntry_t;
typedef MemChunkHeadEntry_t *MemChunkHeadPtr_t;

/* The context structure stores all information used by the allocator */
struct HeapAllocator_ctxt
{
  MemChunkHeadPtr_t		TopOfMemSeg;
  MemChunkHeadPtr_t		LastHeader;
  MemChunkHeadPtr_t		FreeTree;			// points to the root of the tree
  LockDesc						FlagLock;
  LockDesc						AppendLock;
  LockDesc            TreeLock;
};

/* The smallest chunk is LARGESTSUBSIZE + 1 for smaller chunks we do         *
 * allocate a FRAGSIZE * (16 + 4) + 4 Bytes large chunk containing a mask    *
 * in the first four Bytes describing the usage of the entries and a pointer *
 * to the header in front of each element to be able to find it fast.        */
typedef uint32	mask_t;			// mask (for each element 2 bits
// 00 = free,  10 = single 16Byte element
// 01 = start of continous, 11 = element of continous

/* Function prototypes */
Error HeapAllocator_init (struct HeapAllocator_ctxt* ctxt, address_t address, size_t size);
Error HeapAllocator_alloc(struct HeapAllocator_ctxt* ctxt, address_t *addressPtr, size_t size);
Error HeapAllocator_free (struct HeapAllocator_ctxt* ctxt, address_t address);
int heap_resize(struct HeapAllocator_ctxt* ctxt, size_t size);

#endif
