/* Declaration for malloc, free, etc
   Copyright 1993 Tristan Gingold
		  Written September 1993 by Tristan Gingold

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License 
along with this program; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   The author may be reached (Email) at the address marc@david.saclay.cea.fr,
   or (US/French mail) as Tristan Gingold 
   			  8 rue Parmentier
   			  F91120 PALAISEAU
   			  FRANCE
*/

#ifndef _MALLOC_H
#define _MALLOC_H	1

/* configuration file */
#include "config.h"
#include "../checker.h"

#ifdef	__cplusplus
extern "C"
{
#endif

/* ANSI-C is assumed */
#ifndef __ptr_t
#define	__ptr_t void *		/* Yes, a typedef will be better */
#endif

#ifndef	NULL
#define	NULL	0
#endif

#include <stddef.h>

/* Allocate 'size' bytes of memory.  */
extern __ptr_t malloc(size_t __size);
extern __ptr_t _malloc(size_t __size);	/* for internal use only */
/* Re-allocate the previously allocated block
   in __ptr_t, making the new block 'size' bytes long.  */
extern __ptr_t realloc(__ptr_t __ptr, size_t __size);
/* Allocate 'nmemb' elements of 'size' bytes each, all initialized to 0.  */
extern __ptr_t calloc(size_t __nmemb, size_t __size);
/* Free a block allocated by `malloc', `realloc' or `calloc'.  */
extern void free(__ptr_t __ptr);
extern void _free(__ptr_t __ptr);

/* Allocate 'size' bytes allocated to 'alignment' bytes.  */
extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
extern __ptr_t _memalign __P ((size_t __alignment, size_t __size));

/* Allocate 'size' bytes on a page boundary.  */
extern __ptr_t valloc __P ((size_t __size));


#ifdef _MALLOC_INTERNAL

#include <chkrlib.h>

struct malloc_header;

struct malloc_header
{
  struct malloc_header *prev;	/* the next malloc_header, or NULL_HEADER */
  struct malloc_header *next;	/* the previous malloc_header, or NULL_HEADER */
  size_t size;			/* the total size */
  char state;			/* state, see MD* */
  char garbage_t;		/* type of garbage, see POINT_* */
  char g_flag;			/* a flag, for garbage */
  char s_diff;			/* size - info.busy.real_size */
  union
  {
    struct			/* used if state == MDFREE */
    {
      struct malloc_header *prev;	/* the next free block, in the free list */
      struct malloc_header *next;	/*     previous                          */
    } free;
    struct			/* used if state == MDAGED */
    {
      struct malloc_header *prev;	/* the next aged block, in the aged list */
      struct malloc_header *next;
    } aged;    
    struct			/* used if state == MDBUSY */
    {
      union 
      {
        struct malloc_header *g_parent;		/* common group */
        unsigned int g_number;			/* number of 'brother' */
      } g_link;	/* looking for a better name */
      int real_size;		/* value of malloc */
    } busy;
  } info;
};

/* Size of the hash table. If you change it, see bitops.h */
#define HASH_SIZE 20
#define NO_HEAPINDEX 	/* heapindex was a bad optimization */
extern struct malloc_header *_heapinfo[HASH_SIZE];	/* hash table for free blocks */
#ifndef NO_HEAPINDEX
extern unsigned int _heapindex;
#endif
extern struct malloc_header *_firstblock;	/* first block in the memory */
extern struct malloc_header *_lastblock;	/* last block in the mem */
extern struct malloc_header *_youngerblock;
extern struct malloc_header *_olderblock;
extern unsigned int _agedblock;			/* number of block in the aged list */

#define NULL_HEADER (struct malloc_header*)0
#define HEADER_SIZE (sizeof(struct malloc_header))
/* The smallest space that malloc can allocate. Is it useful ? */
#define LITTLE_SPACE (sizeof(int)) /* must be a power of 2 */

/* state possibilities */
#define MDFREE 1	/* block is free */
#define MDBUSY 2	/* block is busy */
#define MDAGED 3	/* block is in the aged list */
#define MDINTRN 4	/* block is reserved for internal used */
#define MDBRK 5		/* block is used by brk */
#define MDCHECK 128	/* a flag, used while checking */
/* Numbers of bytes at the end before they will be returned to the system */
#define FINAL_FREE_SIZE 0x2000	/* 8 kb */
/* Max age of a block: a block can't be alloced before n calls to free. */
#define BLOCK_AGE 10

/* Used to calculate the hash index */
#include "bitops.h"

void _internal_free(struct malloc_header *block);
struct malloc_header *find_header(const __ptr_t ptr);
int get_age(struct malloc_header *block);

#ifdef CHKR_GARBAGE
/* Sizes of red zones */
extern unsigned int be_red_zone;	/* bytes, but must be a multiple of sizeof(int) */
extern unsigned int af_red_zone;
/* Values of garbage_t */
#define POINT_NOT   0	/* no pointer on it */
#define POINT_SURE  1	/* a pointer on the begin */
#define POINT_MAYBE 2	/* a pointer inside */
#define POINT_LEAK  3   /* This is a leak */
#define POINT_SEEN  4	/* already seen (for new zones) */
#define POINT_JUST_SEEN  5	/* to avoid infinitely recursive calls */

/* Values of g_flag */
#define G_ALONE 0	/* no brothers */
#define G_CHILD 2	/* a child. g_group points to its parents */
#define G_PARENT 3	/* a parent. g_number is the number of childs */
#else	/* !CHKR_GARBAGE */
#define be_red_zone 0
#define af_red_zone 0
#endif	/* CHKR_GARBAGE */

void *morecore(int size);
extern int __malloc_initialized;

#endif /* _MALLOC_INTERNAL */

void __chkr_check_intern(void);
void __chkr_dump_busy(void);
void __chkr_dump_free(void);

#ifdef __cplusplus
}
#endif

#endif /* _MALLOC_H */
