storage.h
/*
* storage.h -- Declarations for storage management (gc)
*
* (C) m.b (Matthias Blume); Jun 1992, HUB; Nov 1993 PU/CS
* Humboldt-University of Berlin
* Princeton University, Dept. of Computer Science
*
* $Id: storage.h,v 2.6 1994/09/01 20:11:07 blume Exp $
*/
# ifndef STORAGE_H_
# define STORAGE_H_
# include <stdio.h>
# include <time.h>
# include "align.h"
# define MEM_UNITS(n) (((n) + sizeof (MEM_align_t) - 1) / sizeof (MEM_align_t))
/*
* The implementation of the storage module never needs to access the
* ``extension'' field (see below) and never computes the size of the
* MEM_description structure. Therefore, we are free to compile the
* storage module in the absence of "storext.h" (which is supposed to
* provide the real declaration of ``MEM_extension'').
*/
# ifdef MEM_IMPLEMENTATION
typedef int MEM_extension;
# else
# include "storext.h"
# endif
typedef unsigned long MEM_cnt;
typedef MEM_cnt (* MEM_measure) (void *object);
typedef void (* MEM_visitor) (void **object_ptr, void *cd);
typedef void (* MEM_iterator) (void *object, MEM_visitor v, void *cd);
typedef void (* MEM_dumper) (void *object, FILE *file);
typedef void *(* MEM_excavator) (FILE *file);
typedef void (* MEM_revisor) (void *object);
typedef void (* MEM_task) (void);
# define MEM_NULL_measure ((MEM_measure) 0)
# define MEM_NULL_iterator ((MEM_iterator) 0)
# define MEM_NULL_dumper ((MEM_dumper) 0)
# define MEM_NULL_excavator ((MEM_excavator) 0)
# define MEM_NULL_revisor ((MEM_revisor) 0)
# define MEM_NULL_task ((MEM_task) 0)
/*
* In order to generate portable memory dumps, we use four different
* descriptions for each type:
* 1. the NORMAL type description
* 2. a descriptor that says: objects has been MARKED
* 3. a descriptor that says: objects has been marked AGAIN
* 4. : multiply marked objects has been WRITTEN out
*/
typedef enum MEM_kind {
MEM_NORMAL,
MEM_MARKED,
MEM_AGAIN,
MEM_WRITTEN
} MEM_kind;
typedef struct MEM_description {
MEM_kind kind;
int identifier; /* leading character in dump */
MEM_cnt size; /* if zero, see ``measure'' */
MEM_measure measure; /* NULL: non-heap object */
MEM_iterator iterator; /* how to show a ``visitor'' around ... */
MEM_dumper dumper; /* save all non-subs */
MEM_excavator excavator; /* inverse(dumper) */
MEM_revisor revisor; /* clean up after the visitor */
MEM_task init; /* called by init_all_modules() */
MEM_task before_gc; /* called before every gc */
MEM_task after_gc; /* called after every gc */
struct MEM_description **vector;
MEM_extension extension;
} MEM_description, *MEM_descriptor;
/* register address of a root object: */
extern void MEM_root (void *location, MEM_iterator iterator);
/* frequent special case: a root pointer */
# define MEM_root_var(var) MEM_root (&(var), MEM_NULL_iterator)
/*
* Three things private to the storage module (visible to facilitate inlining):
*/
extern MEM_align_t *MEM_free;
extern MEM_align_t *MEM_ceiling;
extern void *MEM_getmem (MEM_cnt size);
# define MEM_TYPE(obj) (*(MEM_descriptor *)(obj))
# define ScmTypeOf(obj) MEM_TYPE(obj)
/*
* Inlined storage allocation
*/
# define MEM_ALLOC(v,s) \
((v) = (void *) MEM_free, \
(MEM_free += (s)) <= MEM_ceiling ? (void) 0 : (void) ((v) = MEM_getmem (s)))
# define MEM_NEW(v,t,s) (MEM_ALLOC (v, s), MEM_TYPE (v) = (t))
# define MEM_VECTOR(n,s,m,it,d,e,r,i,b,a,ext) \
static MEM_description *MEM_ ## n ## _vector [4]; \
MEM_description MEM_ ## n ## _1 = \
{ MEM_NORMAL, n ## _IDENTIFIER, s, m, it, d, e, r, i, b, a, \
MEM_ ## n ## _vector, ext }; \
static MEM_description MEM_ ## n ## _2 = \
{ MEM_MARKED, n ## _IDENTIFIER, s, m, it, d, e, r, i, b, a, \
MEM_ ## n ## _vector, ext }; \
static MEM_description MEM_ ## n ## _3 = \
{ MEM_AGAIN, n ## _IDENTIFIER, s, m, it, d, e, r, i, b, a, \
MEM_ ## n ## _vector, ext }; \
static MEM_description MEM_ ## n ## _4 = \
{ MEM_WRITTEN, n ## _IDENTIFIER, s, m, it, d, e, r, i, b, a, \
MEM_ ## n ## _vector, ext }; \
static MEM_description * MEM_ ## n ## _vector [4] = \
{ &MEM_ ## n ## _1, &MEM_ ## n ## _2, &MEM_ ## n ## _3, &MEM_ ## n ## _4 }
# define DCL_MEM_TYPE(name) extern MEM_description MEM_ ## name ## _1
extern MEM_descriptor MEM_identifier_map [];
extern unsigned const MEM_identifier_map_length;
extern void MEM_init_all_modules (void);
/* prefix_string will be written as the first line of a dump file. */
/* It cannot contain '\n', but can otherwise be chosen arbitrarily. */
extern void MEM_dump_storage (FILE *file, const char *prefix_string);
extern void MEM_restore_storage (FILE *file);
/* where is the object now? */
extern void *MEM_new_location_of (void *);
/* The current setting of the ``minimum heap size'' */
extern MEM_cnt MEM_min_heap_size;
/*
* This function is called after every run of the garbage collector...
* (The function must be supplied by the client of the storage module.)
* The arguments are:
* n: total number of live objects on the heap
* t: total heap size
* u: size of used part of the heap
* c: time spent in this run of the collector
*/
extern void MEM_gc_statistics (MEM_cnt n, MEM_cnt t, MEM_cnt u, clock_t c);
/*
* The following two procedures, which must be implemented by the
* client of this storage module, will be called in order to announce
* the start and end of a GC-run. They must be present, but they are not
* required to do anything.
* One common use (as shown in the VSCM-Imlementation) is to supress
* instant interrupt handling during garbage collection.
*/
extern void MEM_announce_gc_start (void);
extern void MEM_announce_gc_end (void);
/* query total time spent in the GC so far */
extern clock_t MEM_total_gc_clock (void);
/* two efficient routines to read and write unsigned long */
extern void MEM_dump_ul (unsigned long l, FILE *file);
extern unsigned long MEM_restore_ul (FILE *file);
# endif