/* begincopyright
Copyright (c) 1988,1990 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
Parts of this software were derived from code bearing the copyright notice:
Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
This material may be freely distributed, provided this notice is retained.
This material is provided as is, with no warranty expressed or implied.
Use at your own risk.
endcopyright */
/*
* XR←GC.h
*
* Basic public type definitions for Xerox Runtime
* storage managment package.
*
* Mark Weiser, October 18, 1989
* Alan Ishigo, November 14, 1988 4:38:01 pm PST
* Demers, July 20, 1992 6:00:09 pm PDT
* Boehm, July 28, 1992 4:07:59 pm PDT
*
*/
#ifndef ←←XR←GC←h
#define ←←XR←GC←h 1
#include <stddef.h>
#include <xr/XR←Basics.h>
/* The garbage collector used to assume sizeof (bool) = sizeof (long) */
/* It may still. */
#include <xr/XR←Threads.h>
/* Public variables. May be altered by client. */
/* Public variables. Read only for the client. Set by collector. */
/* Publically readable variables that may not remain meaningful */
/* if the collector changes. Should be used only in disposable code. */
/* The following are meaningful for any collector, but can only be */
/* maintained at significant expense, and may thus eventually disappear. */
/* The object counts are more likely to disappear, since they are */
/* useless to the collector itself. */
/***** Informational Routines *****/
extern unsigned
XR←GCCurrentByteCount(void);
/* Return the current number of bytes allocated.
This number increases continuously (at each allocation) but shrinks
only after collections. */
extern unsigned
XR←GCCurrentObjectCount(void);
/* Return the current number of objects allocated.
This number increases continuously (at each allocation) but shrinks
only after collections.
*/
extern unsigned
XR←GCTotalByteCount(void);
/* Return the current number of bytes allocated. This number increases
continuously.
*/
extern unsigned
XR←GCTotalObjectCount(void);
/* Return the current number of bytes allocated.
This number increases continuously.
*/
/***** Routines to Control Behavior *****/
/* The ...Set... routines always return the old value. */
extern unsigned
XR←GCHeapSize(void);
/* Returns the size of the heap in bytes. */
extern unsigned
XR←SetBytesAfterWhichToCollect(unsigned);
extern unsigned
XR←GetBytesAfterWhichToCollect(void);
/* A non-zero value causes a collection whenever this many bytes have
been allocated since the last collection.
*/
/***** Routines to cause behavior. *****/
/* These routines are all monitored and safe to call at any time.
They are the basic interfaces into storage management.
*/
extern void
XR←GCollect(void);
/* initiate a garbage collection. */
/* general purpose allocation routines: */
extern void *
GC←malloc(size←t ObjectSizeInBytes);
/* Allocates a new object of at least the specified length. The object is
cleared. It will be aligned on at least a 4 byte boundary. If the
architecture requires n byte alignment for certain objects, then it will
be n byte aligned unless the requested size is less than n. If the
requested size is a multiple of n, where n is a power of 2 no larger than
16, then the object will also be n byte aligned. No space is implicitly
reserved for type tags or the like. Returns (XR←Pointer)0 if no memory
is available.
*/
extern void *
GC←malloc←atomic(size←t ObjectSizeInBytes);
/* Identical to GC←malloc, except that the object is assumed to contain no
pointers, amd the object is not cleared. Is faster than, and results in
faster collections than GC←malloc.
*/
extern void *
GC←realloc(void * old←object, size←t ObjectSizeInBytes);
/* Return a new object with indicated size, and contents of the old object.
The new object is assumed to not contain any pointers if the old object
was known not to contain pointers. The new object is identical to the old
object whenever this can be easily arranged. May be much faster than
a new allocation followed by a copy, but this probably happens only if the
client program uses a stupid algorithm. Unfortunately, such clients are
common, at least in the C world.
*/
extern void
GC←free(void * object);
/* Explicitly deallocate an object. The object should have been allocated by
one of the above routines, NOT by one of those below. Results in disaster
if the object is subsequently accessed.
*/
extern void
XR←free(XR←Pointer p);
/* Similar to GC←free, but p may point to the interior of an object. May */
/* be used with any allocated object. */
extern XR←Pointer
XR←valloc(unsigned ObjectSizeInbytes);
/* allocates an object of size at least ObjectSizeInbytes, whose
first address is at a system page boundary. The object is also
made noncollectable, and can be made collectable by calling valloc←free.
The object is assumed to contain NO pointers, and is not cleared.
*/
extern void
XR←valloc←free(XR←Pointer ObjectAddress);
/* permits an object allocated by valloc to be collected if there
are no pointers to it.
*/
extern void
XR←make←uncollectable(XR←Pointer RealObjectAddress,
XR←Pointer AlternateAddressForRelease);
/* prevents the object pointed to by ObjectAddress from ever being collected. */
extern void
XR←unmake←uncollectable(XR←Pointer ObjectAddress);
/* permits an object made uncollectable by a call on XR←make←uncollectable
to again enter the possible collection pool. ObjectAddress can
be either the RealObjectAddress or the AlternateAddressForRelease give
to XR←make←uncollectable.
*/
/* The following routines are OBSOLETE. They return pointers into the
middle of objects, leaving room for 8 byte headers.
*/
extern XR←Pointer
XR←calloc(unsigned ObjectCount, unsigned ObjectSizeInBytes);
/* allocates a new object of length at least ObjectCount * ObjectSizeInBytes.
The object is assumed to contain pointers, and is cleared to all zeros.
OBSOLETE */
extern XR←Pointer
XR←clear←new(unsigned ObjectCount, unsigned ObjectSizeInBytes);
/* allocates a new object of length at least ObjectCount * ObjectSizeInBytes.
The object is assumed to contain pointers, and is cleared to all zeros.
OBSOLETE*/
extern XR←Pointer
XR←new(unsigned ObjectSizeInBytes);
/* allocates a new object at least ObjectSizeInBytes.
The object is assumed to contain pointers, and is cleared to all zeros.
*/
extern XR←Pointer
XR←pointerfree←new(unsigned ObjectSizeInBytes);
/* allocates a new object at least ObjectSizeInBytes.
The object is assumed to contain NO pointers, and is not cleared.
OBSOLETE */
extern XR←Pointer
XR←ralloc(unsigned ObjectSizeIn32BitWords);
/* allocates a new object of at least ObjectSizeIn32BitWords.
The object is assumed to contain NO pointers, and is not cleared.
OBSOLETE */
extern XR←Pointer
XR←ralloc←comp(unsigned ObjectSizeIn32BitWords);
/* allocates a new object of at least ObjectSizeIn32BitWords.
The object is assumed to contain pointers, and is cleared to zeros.
OBSOLETE */
extern XR←Pointer
XR←realloc(unsigned ObjectAddress, unsigned ObjectSizeInBytes);
/* allocates a new object of size at least ObjectSizeInBytes, and
copies the bytes at ObjectAddress into the new object.
ObjectSizeInBytes are always copied, so XR←realloc only makes
sense for growing, not shrinking, objects. The object is assumed
to contain pointers, and any additional space is cleared to zeros.
OBSOLETE */
extern XR←Pointer
XR←malloc(unsigned ObjectSizeInBytes);
/* allocates an object of size at least ObjectSizeInBytes, and
return the address. The object is assumed to contain pointers,
and is cleared to zeros.
OBSOLETE */
extern void
XR←unsafe←free(XR←Pointer);
/* Alias for XR←free. */
/* Routines below are not for casual users */
extern void
GC←register←displacement(unsigned DisplacementInBytes);
/* Register the given displacement as a valid displacement of a pointer
to an object into an object. All values equal to an object address
plus the given displacement will henceforth be treated as pointers.
Ignored if the collector is not compiled to keep track of
such things. Calling this after allocation has taken place is more
expensive, but still safe. We claim it is unreasonable to ever
unregister a displacement. Thus there is no way to do it.
*/
/***** Finalization *****/
/*
The finalization described here is the innermost level, and is not
indended for direct use. Rather, language implementors are expected
to wrap their own layers around this. For instance, there is a
different Cedar layer for use by Cedar/Mesa programmers.
*/
/*
* Finalizable Object structures and Finalization Queues:
*
* Invariants:
*
* firstword, secondword - encode a pointer to an object
* (a) disguised as pair < ptr&0xffff, (ptr>>16)&0xffff >
* if it's finalizable
* (b) undisguised as < ptr , nil > if it's not finalizable
* N.B. since first 64K of address space isn't in heap, this
* means (secondword == 0) iff the pointer is undisguised.
* associatedFQ - pointer to a FinalizationQueueStructure
* non-NIL iff the object is finalizable or on the finalization queue
*
* Thus, finalization states can be determined by:
* enabled: (secondword != 0)
* disabled: (associatedFQ == NIL)
* onFQ: otherwise
*/
typedef struct XR←FinalizationQueueStructure {
struct XR←FinalizableObjectStructure * head;
struct XR←FinalizableObjectStructure * tail;
struct XR←CVRep fqNonempty;
} * XR←FinalizationQueue;
typedef struct XR←FinalizableObjectStructure {
unsigned long firstword;
unsigned long secondword;
XR←FinalizationQueue associatedFQ;
struct XR←FinalizableObjectStructure *next;
} * XR←FinalizationHandle;
#define XR←IsDisguised(h) ((h)->secondword != 0)
#define XR←FetchFromDisguised(h) ( ((h)->firstword) | ((h)->secondword << 16) )
#define XR←FetchFromUndisguised(h) ( (h)->firstword )
#define XR←StoreDisguised(w,h) { \
(h)->firstword = ((unsigned long)(w)) & 0xffff; \
(h)->secondword = (((unsigned long)(w)) >> 16) & 0xffff; \
}
#define XR←StoreUndisguised(w,h) { \
(h)->firstword = ((unsigned long)(w)); \
(h)->secondword = 0; \
}
typedef enum {
fzsEnabled = 0,
fzsOnFQ = 1,
fzsDisabled = 2,
fzsError = 0x7fffffff /* force to 32 bits */
} XR←FinalizationState;
extern XR←FinalizationQueue
XR←NewFQ(void);
/* return a new, empty, initialized finalization queue. */
extern XR←FinalizationHandle
XR←FQNextNoAbort(XR←FinalizationQueue fq);
/* return the next handle on queue 'fq', waiting on a condition variable
until there is an item if necessary. If there is no item, or the
wait is interrupted, return NIL */
extern bool
XR←FQEmpty(XR←FinalizationQueue fq);
extern XR←FinalizationHandle
XR←NewFinalizationHandle(void);
/* return a new, empty, initialized handle for an object to be finalized. */
extern void
XR←EnableFinalization(XR←Pointer object,
XR←FinalizationQueue fq,
XR←FinalizationHandle h);
/* Cause the object to be enabled for finalization.
'h' is updated to describe the object. When the time comes,
fq will be the finalization queue on which the object is placed.
*/
extern XR←FinalizationState
XR←DisableFinalization(XR←FinalizationHandle h);
/* Disable the object described by 'h' for finalization. Return its
prior XR←FinalizationState. If it is already on a finalize q, remove it.
*/
extern XR←FinalizationState
XR←ReenableFinalization(XR←FinalizationHandle h,
XR←FinalizationQueue fq);
/* Causes an object which was once finalizable to be so again, now
on queue 'fq'. If it is on some other queue, it is removed first.
Prior state is returned.
*/
extern XR←FinalizationState
XR←GetFinalizationState(XR←FinalizationHandle h);
/* get the finalization state of the object */
extern XR←Pointer
XR←HandleToObject(XR←FinalizationHandle h);
/* Get the pointer to the real object, given its handle */
#endif /* ←←XR←GC←h */