/* mps.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE
*
* $Id: //info.ravenbrook.com/project/mps/custom/cet/version/1.114/code/mps.h#1 $
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Portions copyright (c) 2002 Global Graphics Software.
*
* THIS HEADER IS NOT DOCUMENTATION.
* Please refer to the [MPS Manual](../manual/).
*
* But if you are a human reading this, please note:
*
* .naming: The MPS interface only uses identifiers beginning `mps_`,
* `MPS_` or `_mps_` and may use any identifiers with these prefixes in
* future.
*
* .naming.internal: Any identifier beginning with an underscore is for
* internal use within the interface and may change or be withdrawn without
* warning.
*
* .readership: compilers, MPS developers.
*
* .sources: [The design of the MPS Interface to C](../design/interface-c).
*/
#ifndef mps_h
#define mps_h
#include <stddef.h>
#include <stdarg.h>
#include <limits.h>
/* Platform Dependencies
*
* We went for over ten years without any platform ifdefs in this header.
* Then Microsoft made unsigned long shorter than a pointer on Win64. Ugh.
*/
#if defined(_MSC_VER) && defined(_WIN32) && defined(_WIN64) && defined(_M_X64)
typedef unsigned __int64 mps_word_t;
#else
typedef unsigned long mps_word_t;
#endif
/* Abstract Types */
typedef struct mps_arena_s *mps_arena_t; /* arena */
typedef struct mps_arena_class_s *mps_arena_class_t; /* arena class */
typedef struct mps_pool_s *mps_pool_t; /* pool */
typedef struct mps_chain_s *mps_chain_t; /* chain */
typedef struct mps_fmt_s *mps_fmt_t; /* object format */
typedef struct mps_root_s *mps_root_t; /* root */
typedef struct mps_class_s *mps_class_t; /* pool class */
typedef struct mps_thr_s *mps_thr_t; /* thread registration */
typedef struct mps_ap_s *mps_ap_t; /* allocation point */
typedef struct mps_ld_s *mps_ld_t; /* location dependency */
typedef struct mps_ss_s *mps_ss_t; /* scan state */
typedef struct mps_message_s
*mps_message_t; /* message */
typedef struct mps_alloc_pattern_s
*mps_alloc_pattern_t; /* allocation patterns */
typedef struct mps_frame_s
*mps_frame_t; /* allocation frames */
typedef const struct mps_key_s *mps_key_t; /* argument key */
/* Concrete Types */
typedef int mps_bool_t; /* boolean (int) */
typedef int mps_res_t; /* result code (int) */
typedef void *mps_addr_t; /* managed address (void *) */
typedef size_t mps_align_t; /* alignment (size_t) */
typedef unsigned mps_rm_t; /* root mode (unsigned) */
typedef unsigned mps_rank_t; /* ranks (unsigned) */
typedef unsigned mps_message_type_t; /* message type (unsigned) */
typedef mps_word_t mps_clock_t; /* processor time */
typedef mps_word_t mps_label_t; /* telemetry label */
/* Result Codes */
#define _mps_RES_ENUM(R, X) \
R(X, OK, "success (always zero)") \
R(X, FAIL, "unspecified failure") \
R(X, RESOURCE, "unable to obtain resources") \
R(X, MEMORY, "unable to obtain memory") \
R(X, LIMIT, "limitation reached") \
R(X, UNIMPL, "unimplemented facility") \
R(X, IO, "system I/O error") \
R(X, COMMIT_LIMIT, "arena commit limit exceeded") \
R(X, PARAM, "illegal user parameter value")
#define _mps_ENUM_DEF_ROW(prefix, ident, doc) prefix##ident,
#define _mps_ENUM_DEF(REL, prefix) \
enum { \
REL(_mps_ENUM_DEF_ROW, prefix) \
_mps_##prefix##LIMIT \
};
_mps_ENUM_DEF(_mps_RES_ENUM, MPS_RES_)
/* Format and Root Method Types */
/* see design.mps.root-interface */
/* see design.mps.format-interface */
typedef mps_res_t (*mps_root_scan_t)(mps_ss_t, void *, size_t);
typedef mps_res_t (*mps_fmt_scan_t)(mps_ss_t, mps_addr_t, mps_addr_t);
typedef mps_res_t (*mps_reg_scan_t)(mps_ss_t, mps_thr_t,
void *, size_t);
typedef mps_addr_t (*mps_fmt_skip_t)(mps_addr_t);
typedef void (*mps_fmt_copy_t)(mps_addr_t, mps_addr_t);
typedef void (*mps_fmt_fwd_t)(mps_addr_t, mps_addr_t);
typedef mps_addr_t (*mps_fmt_isfwd_t)(mps_addr_t);
typedef void (*mps_fmt_pad_t)(mps_addr_t, size_t);
typedef mps_addr_t (*mps_fmt_class_t)(mps_addr_t);
/* Keyword argument lists */
typedef void (*mps_fun_t)(void);
typedef struct mps_arg_s {
mps_key_t key;
union {
mps_bool_t b;
char c;
const char *string;
int i;
unsigned u;
long l;
unsigned long ul;
float f;
double d;
size_t size;
mps_fun_t fun;
mps_addr_t addr;
mps_fmt_t format;
mps_chain_t chain;
struct mps_pool_debug_option_s *pool_debug_options;
mps_addr_t (*addr_method)(mps_addr_t);
mps_align_t align;
mps_word_t count;
void *p;
mps_rank_t rank;
mps_fmt_scan_t fmt_scan;
mps_fmt_skip_t fmt_skip;
mps_fmt_fwd_t fmt_fwd;
mps_fmt_isfwd_t fmt_isfwd;
mps_fmt_pad_t fmt_pad;
mps_fmt_class_t fmt_class;
mps_pool_t pool;
} val;
} mps_arg_s;
extern const struct mps_key_s _mps_key_args_end;
#define MPS_KEY_ARGS_END (&_mps_key_args_end)
extern mps_arg_s mps_args_none[];
extern const struct mps_key_s _mps_key_arena_size;
#define MPS_KEY_ARENA_SIZE (&_mps_key_arena_size)
#define MPS_KEY_ARENA_SIZE_FIELD size
extern const struct mps_key_s _mps_key_arena_grain_size;
#define MPS_KEY_ARENA_GRAIN_SIZE (&_mps_key_arena_grain_size)
#define MPS_KEY_ARENA_GRAIN_SIZE_FIELD size
extern const struct mps_key_s _mps_key_arena_zoned;
#define MPS_KEY_ARENA_ZONED (&_mps_key_arena_zoned)
#define MPS_KEY_ARENA_ZONED_FIELD b
extern const struct mps_key_s _mps_key_format;
#define MPS_KEY_FORMAT (&_mps_key_format)
#define MPS_KEY_FORMAT_FIELD format
extern const struct mps_key_s _mps_key_chain;
#define MPS_KEY_CHAIN (&_mps_key_chain)
#define MPS_KEY_CHAIN_FIELD chain
extern const struct mps_key_s _mps_key_gen;
#define MPS_KEY_GEN (&_mps_key_gen)
#define MPS_KEY_GEN_FIELD u
extern const struct mps_key_s _mps_key_rank;
#define MPS_KEY_RANK (&_mps_key_rank)
#define MPS_KEY_RANK_FIELD rank
extern const struct mps_key_s _mps_key_extend_by;
#define MPS_KEY_EXTEND_BY (&_mps_key_extend_by)
#define MPS_KEY_EXTEND_BY_FIELD size
extern const struct mps_key_s _mps_key_large_size;
#define MPS_KEY_LARGE_SIZE (&_mps_key_large_size)
#define MPS_KEY_LARGE_SIZE_FIELD size
extern const struct mps_key_s _mps_key_min_size;
#define MPS_KEY_MIN_SIZE (&_mps_key_min_size)
#define MPS_KEY_MIN_SIZE_FIELD size
extern const struct mps_key_s _mps_key_mean_size;
#define MPS_KEY_MEAN_SIZE (&_mps_key_mean_size)
#define MPS_KEY_MEAN_SIZE_FIELD size
extern const struct mps_key_s _mps_key_max_size;
#define MPS_KEY_MAX_SIZE (&_mps_key_max_size)
#define MPS_KEY_MAX_SIZE_FIELD size
extern const struct mps_key_s _mps_key_align;
#define MPS_KEY_ALIGN (&_mps_key_align)
#define MPS_KEY_ALIGN_FIELD align
extern const struct mps_key_s _mps_key_spare;
#define MPS_KEY_SPARE (&_mps_key_spare)
#define MPS_KEY_SPARE_FIELD double
extern const struct mps_key_s _mps_key_interior;
#define MPS_KEY_INTERIOR (&_mps_key_interior)
#define MPS_KEY_INTERIOR_FIELD b
extern const struct mps_key_s _mps_key_vmw3_top_down;
#define MPS_KEY_VMW3_TOP_DOWN (&_mps_key_vmw3_top_down)
#define MPS_KEY_VMW3_TOP_DOWN_FIELD b
extern const struct mps_key_s _mps_key_fmt_align;
#define MPS_KEY_FMT_ALIGN (&_mps_key_fmt_align)
#define MPS_KEY_FMT_ALIGN_FIELD align
extern const struct mps_key_s _mps_key_fmt_header_size;
#define MPS_KEY_FMT_HEADER_SIZE (&_mps_key_fmt_header_size)
#define MPS_KEY_FMT_HEADER_SIZE_FIELD size
extern const struct mps_key_s _mps_key_fmt_scan;
#define MPS_KEY_FMT_SCAN (&_mps_key_fmt_scan)
#define MPS_KEY_FMT_SCAN_FIELD fmt_scan
extern const struct mps_key_s _mps_key_fmt_skip;
#define MPS_KEY_FMT_SKIP (&_mps_key_fmt_skip)
#define MPS_KEY_FMT_SKIP_FIELD fmt_skip
extern const struct mps_key_s _mps_key_fmt_fwd;
#define MPS_KEY_FMT_FWD (&_mps_key_fmt_fwd)
#define MPS_KEY_FMT_FWD_FIELD fmt_fwd
extern const struct mps_key_s _mps_key_fmt_isfwd;
#define MPS_KEY_FMT_ISFWD (&_mps_key_fmt_isfwd)
#define MPS_KEY_FMT_ISFWD_FIELD fmt_isfwd
extern const struct mps_key_s _mps_key_fmt_pad;
#define MPS_KEY_FMT_PAD (&_mps_key_fmt_pad)
#define MPS_KEY_FMT_PAD_FIELD fmt_pad
extern const struct mps_key_s _mps_key_fmt_class;
#define MPS_KEY_FMT_CLASS (&_mps_key_fmt_class)
#define MPS_KEY_FMT_CLASS_FIELD fmt_class
/* Maximum length of a keyword argument list. */
#define MPS_ARGS_MAX 32
extern void _mps_args_set_key(mps_arg_s args[MPS_ARGS_MAX], unsigned i,
mps_key_t key);
#define MPS_ARGS_BEGIN(_var) \
MPS_BEGIN \
mps_arg_s _var[MPS_ARGS_MAX]; \
unsigned _var##_i = 0; \
_mps_args_set_key(_var, _var##_i, MPS_KEY_ARGS_END); \
MPS_BEGIN
#define MPS_ARGS_ADD_FIELD(_var, _key, _field, _val) \
MPS_BEGIN \
_mps_args_set_key(_var, _var##_i, _key); \
_var[_var##_i].val._field = (_val); \
++_var##_i; \
_mps_args_set_key(_var, _var##_i, MPS_KEY_ARGS_END); \
MPS_END
#define MPS_ARGS_ADD(_var, _key, _val) \
MPS_ARGS_ADD_FIELD(_var, _key, _key##_FIELD, _val)
#define MPS_ARGS_DONE(_var) \
MPS_BEGIN \
_mps_args_set_key(_var, _var##_i, MPS_KEY_ARGS_END); \
_var##_i = MPS_ARGS_MAX; \
MPS_END
#define MPS_ARGS_END(_var) \
MPS_END; \
MPS_END
/* <a id="message.types"> Keep in sync with
* <code/mpmtypes.h#message.types> */
/* Not meant to be used by clients, they should use the macros below. */
enum {
_mps_MESSAGE_TYPE_FINALIZATION,
_mps_MESSAGE_TYPE_GC,
_mps_MESSAGE_TYPE_GC_START
};
/* Message Types
* This is what clients should use. */
#define mps_message_type_finalization() _mps_MESSAGE_TYPE_FINALIZATION
#define mps_message_type_gc() _mps_MESSAGE_TYPE_GC
#define mps_message_type_gc_start() _mps_MESSAGE_TYPE_GC_START
/* Reference Ranks
*
* See protocol.mps.reference. */
extern mps_rank_t mps_rank_ambig(void);
extern mps_rank_t mps_rank_exact(void);
extern mps_rank_t mps_rank_weak(void);
/* Root Modes */
/* .rm: Keep in sync with <code/mpmtypes.h#rm> */
#define MPS_RM_CONST (((mps_rm_t)1<<0))
#define MPS_RM_PROT (((mps_rm_t)1<<1))
/* Allocation Point */
/* .ap: Keep in sync with <code/mpmst.h#ap>. */
typedef struct mps_ap_s { /* allocation point descriptor */
mps_addr_t init; /* limit of initialized memory */
mps_addr_t alloc; /* limit of allocated memory */
mps_addr_t limit; /* limit of available memory */
mps_addr_t _frameptr; /* lightweight frame pointer */
mps_bool_t _enabled; /* lightweight frame status */
mps_bool_t _lwpoppending; /* lightweight pop pending? */
} mps_ap_s;
/* Segregated-fit Allocation Caches */
/* .sac: Keep in sync with <code/sac.h>. */
typedef struct _mps_sac_s *mps_sac_t;
#define MPS_SAC_CLASS_LIMIT ((size_t)8)
typedef struct _mps_sac_freelist_block_s {
size_t _size;
size_t _count;
size_t _count_max;
mps_addr_t _blocks;
} _mps_sac_freelist_block_s;
typedef struct _mps_sac_s {
size_t _middle;
mps_bool_t _trapped;
_mps_sac_freelist_block_s _freelists[2 * MPS_SAC_CLASS_LIMIT];
} _mps_sac_s;
/* .sacc: Keep in sync with <code/sac.h>. */
typedef struct mps_sac_class_s {
size_t mps_block_size;
size_t mps_cached_count;
unsigned mps_frequency;
} mps_sac_class_s;
#define mps_sac_classes_s mps_sac_class_s
/* Location Dependency */
/* .ld: Keep in sync with <code/mpmst.h#ld.struct>. */
typedef struct mps_ld_s { /* location dependency descriptor */
mps_word_t _epoch, _rs;
} mps_ld_s;
/* Scan State */
/* .ss: See also <code/mpmst.h#ss>. */
typedef struct mps_ss_s {
mps_word_t _zs, _w, _ufs;
} mps_ss_s;
/* Format Variants */
typedef struct mps_fmt_A_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_copy_t copy;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
} mps_fmt_A_s;
typedef struct mps_fmt_A_s *mps_fmt_A_t;
/* type-name mps_fmt_A_t is deprecated: use mps_fmt_A_s* instead */
typedef struct mps_fmt_B_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_copy_t copy;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
mps_fmt_class_t mps_class;
} mps_fmt_B_s;
typedef struct mps_fmt_B_s *mps_fmt_B_t;
/* type-name mps_fmt_B_t is deprecated: use mps_fmt_B_s* instead */
typedef struct mps_fmt_auto_header_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_skip_t skip;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
size_t mps_headerSize;
} mps_fmt_auto_header_s;
typedef struct mps_fmt_fixed_s {
mps_align_t align;
mps_fmt_scan_t scan;
mps_fmt_fwd_t fwd;
mps_fmt_isfwd_t isfwd;
mps_fmt_pad_t pad;
} mps_fmt_fixed_s;
/* Internal Definitions */
#define MPS_BEGIN do {
#define MPS_END } while(0)
/* MPS_END might cause compiler warnings about constant conditionals.
* This could be avoided with some loss of efficiency by replacing 0
* with a variable always guaranteed to be 0. In Visual C, the
* warning can be turned off using:
* #pragma warning(disable: 4127)
*/
/* arenas */
extern void mps_arena_clamp(mps_arena_t);
extern void mps_arena_release(mps_arena_t);
extern void mps_arena_park(mps_arena_t);
extern void mps_arena_expose(mps_arena_t);
extern void mps_arena_unsafe_expose_remember_protection(mps_arena_t);
extern void mps_arena_unsafe_restore_protection(mps_arena_t);
extern mps_res_t mps_arena_start_collect(mps_arena_t);
extern mps_res_t mps_arena_collect(mps_arena_t);
extern mps_bool_t mps_arena_step(mps_arena_t, double, double);
extern mps_res_t mps_arena_create(mps_arena_t *, mps_arena_class_t, ...);
extern mps_res_t mps_arena_create_v(mps_arena_t *, mps_arena_class_t, va_list);
extern mps_res_t mps_arena_create_k(mps_arena_t *, mps_arena_class_t,
mps_arg_s []);
extern void mps_arena_destroy(mps_arena_t);
extern size_t mps_arena_reserved(mps_arena_t);
extern size_t mps_arena_committed(mps_arena_t);
extern size_t mps_arena_spare_committed(mps_arena_t);
extern size_t mps_arena_commit_limit(mps_arena_t);
extern mps_res_t mps_arena_commit_limit_set(mps_arena_t, size_t);
extern void mps_arena_spare_commit_limit_set(mps_arena_t, size_t);
extern size_t mps_arena_spare_commit_limit(mps_arena_t);
extern mps_bool_t mps_arena_has_addr(mps_arena_t, mps_addr_t);
extern mps_bool_t mps_addr_pool(mps_pool_t *, mps_arena_t, mps_addr_t);
extern mps_bool_t mps_addr_fmt(mps_fmt_t *, mps_arena_t, mps_addr_t);
/* Client memory arenas */
extern mps_res_t mps_arena_extend(mps_arena_t, mps_addr_t, size_t);
#if 0
/* There's no implementation for this function. */
extern mps_res_t mps_arena_retract(mps_arena_t, mps_addr_t, size_t);
#endif
/* Object Formats */
extern mps_res_t mps_fmt_create_k(mps_fmt_t *, mps_arena_t, mps_arg_s []);
extern mps_res_t mps_fmt_create_A(mps_fmt_t *, mps_arena_t,
mps_fmt_A_s *);
extern mps_res_t mps_fmt_create_B(mps_fmt_t *, mps_arena_t,
mps_fmt_B_s *);
extern mps_res_t mps_fmt_create_auto_header(mps_fmt_t *, mps_arena_t,
mps_fmt_auto_header_s *);
extern mps_res_t mps_fmt_create_fixed(mps_fmt_t *, mps_arena_t,
mps_fmt_fixed_s *);
extern void mps_fmt_destroy(mps_fmt_t);
/* Pools */
extern mps_res_t mps_pool_create(mps_pool_t *, mps_arena_t,
mps_class_t, ...);
extern mps_res_t mps_pool_create_v(mps_pool_t *, mps_arena_t,
mps_class_t, va_list);
extern mps_res_t mps_pool_create_k(mps_pool_t *, mps_arena_t,
mps_class_t, mps_arg_s []);
extern void mps_pool_destroy(mps_pool_t);
extern size_t mps_pool_total_size(mps_pool_t);
extern size_t mps_pool_free_size(mps_pool_t);
/* Chains */
/* .gen-param: This structure must match <code/chain.h#gen-param>. */
typedef struct mps_gen_param_s {
size_t mps_capacity;
double mps_mortality;
} mps_gen_param_s;
extern mps_res_t mps_chain_create(mps_chain_t *, mps_arena_t,
size_t, mps_gen_param_s *);
extern void mps_chain_destroy(mps_chain_t);
/* Manual Allocation */
extern mps_res_t mps_alloc(mps_addr_t *, mps_pool_t, size_t);
extern mps_res_t mps_alloc_v(mps_addr_t *, mps_pool_t, size_t, va_list);
extern void mps_free(mps_pool_t, mps_addr_t, size_t);
/* Allocation Points */
extern mps_res_t mps_ap_create(mps_ap_t *, mps_pool_t, ...);
extern mps_res_t mps_ap_create_v(mps_ap_t *, mps_pool_t, va_list);
extern mps_res_t mps_ap_create_k(mps_ap_t *, mps_pool_t, mps_arg_s []);
extern void mps_ap_destroy(mps_ap_t);
extern mps_res_t (mps_reserve)(mps_addr_t *, mps_ap_t, size_t);
extern mps_bool_t (mps_commit)(mps_ap_t, mps_addr_t, size_t);
extern mps_res_t mps_ap_fill(mps_addr_t *, mps_ap_t, size_t);
extern mps_res_t mps_ap_fill_with_reservoir_permit(mps_addr_t *,
mps_ap_t,
size_t);
extern mps_res_t (mps_ap_frame_push)(mps_frame_t *, mps_ap_t);
extern mps_res_t (mps_ap_frame_pop)(mps_ap_t, mps_frame_t);
extern mps_bool_t mps_ap_trip(mps_ap_t, mps_addr_t, size_t);
extern mps_alloc_pattern_t mps_alloc_pattern_ramp(void);
extern mps_alloc_pattern_t mps_alloc_pattern_ramp_collect_all(void);
extern mps_res_t mps_ap_alloc_pattern_begin(mps_ap_t, mps_alloc_pattern_t);
extern mps_res_t mps_ap_alloc_pattern_end(mps_ap_t, mps_alloc_pattern_t);
extern mps_res_t mps_ap_alloc_pattern_reset(mps_ap_t);
/* Segregated-fit Allocation Caches */
extern mps_res_t mps_sac_create(mps_sac_t *, mps_pool_t, size_t,
mps_sac_classes_s *);
extern void mps_sac_destroy(mps_sac_t);
extern mps_res_t mps_sac_alloc(mps_addr_t *, mps_sac_t, size_t, mps_bool_t);
extern void mps_sac_free(mps_sac_t, mps_addr_t, size_t);
extern void mps_sac_flush(mps_sac_t);
/* Direct access to mps_sac_fill and mps_sac_empty is not supported. */
extern mps_res_t mps_sac_fill(mps_addr_t *, mps_sac_t, size_t, mps_bool_t);
extern void mps_sac_empty(mps_sac_t, mps_addr_t, size_t);
#define MPS_SAC_ALLOC_FAST(res_o, p_o, sac, size, has_reservoir_permit) \
MPS_BEGIN \
size_t _mps_i, _mps_s; \
\
_mps_s = (size); \
if (_mps_s > (sac)->_middle) { \
_mps_i = 0; \
while (_mps_s > (sac)->_freelists[_mps_i]._size) \
_mps_i += 2; \
} else { \
_mps_i = 1; \
while (_mps_s <= (sac)->_freelists[_mps_i]._size) \
_mps_i += 2; \
} \
if ((sac)->_freelists[_mps_i]._count != 0) { \
(p_o) = (sac)->_freelists[_mps_i]._blocks; \
(sac)->_freelists[_mps_i]._blocks = *(mps_addr_t *)(p_o); \
--(sac)->_freelists[_mps_i]._count; \
(res_o) = MPS_RES_OK; \
} else \
(res_o) = mps_sac_fill(&(p_o), sac, _mps_s, \
has_reservoir_permit); \
MPS_END
#define MPS_SAC_FREE_FAST(sac, p, size) \
MPS_BEGIN \
size_t _mps_i, _mps_s; \
\
_mps_s = (size); \
if (_mps_s > (sac)->_middle) { \
_mps_i = 0; \
while (_mps_s > (sac)->_freelists[_mps_i]._size) \
_mps_i += 2; \
} else { \
_mps_i = 1; \
while (_mps_s <= (sac)->_freelists[_mps_i]._size) \
_mps_i += 2; \
} \
if ((sac)->_freelists[_mps_i]._count \
< (sac)->_freelists[_mps_i]._count_max) { \
*(mps_addr_t *)(p) = (sac)->_freelists[_mps_i]._blocks; \
(sac)->_freelists[_mps_i]._blocks = (p); \
++(sac)->_freelists[_mps_i]._count; \
} else \
mps_sac_empty(sac, p, _mps_s); \
MPS_END
/* backward compatibility */
#define MPS_SAC_ALLOC(res_o, p_o, sac, size, has_reservoir_permit) \
MPS_SAC_ALLOC_FAST(res_o, p_o, sac, size, has_reservoir_permit)
#define MPS_SAC_FREE(sac, p, size) MPS_SAC_FREE_FAST(sac, p, size)
/* Low memory reservoir */
extern void mps_reservoir_limit_set(mps_arena_t, size_t);
extern size_t mps_reservoir_limit(mps_arena_t);
extern size_t mps_reservoir_available(mps_arena_t);
extern mps_res_t mps_reserve_with_reservoir_permit(mps_addr_t *,
mps_ap_t,
size_t);
/* Reserve Macros */
/* .reserve: Keep in sync with <code/buffer.c#reserve>. */
#define mps_reserve(_p_o, _mps_ap, _size) \
((char *)(_mps_ap)->alloc + (_size) > (char *)(_mps_ap)->alloc && \
(char *)(_mps_ap)->alloc + (_size) <= (char *)(_mps_ap)->limit ? \
((_mps_ap)->alloc = \
(mps_addr_t)((char *)(_mps_ap)->alloc + (_size)), \
*(_p_o) = (_mps_ap)->init, \
MPS_RES_OK) : \
mps_ap_fill(_p_o, _mps_ap, _size))
#define MPS_RESERVE_BLOCK(_res_v, _p_v, _mps_ap, _size) \
MPS_BEGIN \
char *_alloc = (char *)(_mps_ap)->alloc; \
char *_next = _alloc + (_size); \
if(_next > _alloc && _next <= (char *)(_mps_ap)->limit) { \
(_mps_ap)->alloc = (mps_addr_t)_next; \
(_p_v) = (_mps_ap)->init; \
(_res_v) = MPS_RES_OK; \
} else \
(_res_v) = mps_ap_fill(&(_p_v), _mps_ap, _size); \
MPS_END
#define MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK(_res_v, _p_v, _mps_ap, _size) \
MPS_BEGIN \
char *_alloc = (char *)(_mps_ap)->alloc; \
char *_next = _alloc + (_size); \
if(_next > _alloc && _next <= (char *)(_mps_ap)->limit) { \
(_mps_ap)->alloc = (mps_addr_t)_next; \
(_p_v) = (_mps_ap)->init; \
(_res_v) = MPS_RES_OK; \
} else \
(_res_v) = mps_ap_fill_with_reservoir_permit(&(_p_v), _mps_ap, _size); \
MPS_END
/* Commit Macros */
/* .commit: Keep in sync with <code/buffer.c#commit>. */
#define mps_commit(_mps_ap, _p, _size) \
((_mps_ap)->init = (_mps_ap)->alloc, \
(_mps_ap)->limit != 0 || mps_ap_trip(_mps_ap, _p, _size))
/* Root Creation and Destruction */
extern mps_res_t mps_root_create(mps_root_t *, mps_arena_t, mps_rank_t,
mps_rm_t, mps_root_scan_t,
void *, size_t);
extern mps_res_t mps_root_create_table(mps_root_t *, mps_arena_t,
mps_rank_t, mps_rm_t,
mps_addr_t *, size_t);
extern mps_res_t mps_root_create_table_masked(mps_root_t *, mps_arena_t,
mps_rank_t, mps_rm_t,
mps_addr_t *, size_t,
mps_word_t);
extern mps_res_t mps_root_create_fmt(mps_root_t *, mps_arena_t,
mps_rank_t, mps_rm_t,
mps_fmt_scan_t, mps_addr_t,
mps_addr_t);
extern mps_res_t mps_root_create_reg(mps_root_t *, mps_arena_t,
mps_rank_t, mps_rm_t, mps_thr_t,
mps_reg_scan_t, void *, size_t);
extern void mps_root_destroy(mps_root_t);
extern mps_res_t mps_stack_scan_ambig(mps_ss_t, mps_thr_t,
void *, size_t);
/* Protection Trampoline and Thread Registration */
typedef void *(*mps_tramp_t)(void *, size_t);
extern void (mps_tramp)(void **, mps_tramp_t, void *, size_t);
extern mps_res_t mps_thread_reg(mps_thr_t *, mps_arena_t);
extern void mps_thread_dereg(mps_thr_t);
/* Location Dependency */
extern void mps_ld_reset(mps_ld_t, mps_arena_t);
extern void mps_ld_add(mps_ld_t, mps_arena_t, mps_addr_t);
extern void mps_ld_merge(mps_ld_t, mps_arena_t, mps_ld_t);
extern mps_bool_t mps_ld_isstale(mps_ld_t, mps_arena_t, mps_addr_t);
extern mps_bool_t mps_ld_isstale_any(mps_ld_t, mps_arena_t);
extern mps_word_t mps_collections(mps_arena_t);
/* Messages */
extern void mps_message_type_enable(mps_arena_t, mps_message_type_t);
extern void mps_message_type_disable(mps_arena_t, mps_message_type_t);
extern mps_bool_t mps_message_poll(mps_arena_t);
extern mps_bool_t mps_message_queue_type(mps_message_type_t *, mps_arena_t);
extern mps_bool_t mps_message_get(mps_message_t *,
mps_arena_t, mps_message_type_t);
extern void mps_message_discard(mps_arena_t, mps_message_t);
/* Message Methods */
/* -- All Message Types */
extern mps_message_type_t mps_message_type(mps_arena_t, mps_message_t);
extern mps_clock_t mps_message_clock(mps_arena_t, mps_message_t);
/* -- mps_message_type_finalization */
extern void mps_message_finalization_ref(mps_addr_t *,
mps_arena_t, mps_message_t);
/* -- mps_message_type_gc */
extern size_t mps_message_gc_live_size(mps_arena_t, mps_message_t);
extern size_t mps_message_gc_condemned_size(mps_arena_t, mps_message_t);
extern size_t mps_message_gc_not_condemned_size(mps_arena_t,
mps_message_t);
/* -- mps_message_type_gc_start */
extern const char *mps_message_gc_start_why(mps_arena_t, mps_message_t);
/* Finalization */
extern mps_res_t mps_finalize(mps_arena_t, mps_addr_t *);
extern mps_res_t mps_definalize(mps_arena_t, mps_addr_t *);
/* Telemetry */
extern mps_word_t mps_telemetry_control(mps_word_t, mps_word_t);
extern void mps_telemetry_set(mps_word_t);
extern void mps_telemetry_reset(mps_word_t);
extern mps_word_t mps_telemetry_get(void);
extern mps_label_t mps_telemetry_intern(const char *);
extern void mps_telemetry_label(mps_addr_t, mps_label_t);
extern void mps_telemetry_flush(void);
/* Heap Walking */
typedef void (*mps_formatted_objects_stepper_t)(mps_addr_t, mps_fmt_t,
mps_pool_t,
void *, size_t);
extern void mps_arena_formatted_objects_walk(mps_arena_t,
mps_formatted_objects_stepper_t,
void *, size_t);
/* Root Walking */
typedef void (*mps_roots_stepper_t)(mps_addr_t *,
mps_root_t,
void *, size_t);
extern void mps_arena_roots_walk(mps_arena_t,
mps_roots_stepper_t,
void *, size_t);
/* Allocation debug options */
typedef struct mps_pool_debug_option_s {
const void *fence_template;
size_t fence_size;
const void *free_template;
size_t free_size;
} mps_pool_debug_option_s;
extern const struct mps_key_s _mps_key_pool_debug_options;
#define MPS_KEY_POOL_DEBUG_OPTIONS (&_mps_key_pool_debug_options)
#define MPS_KEY_POOL_DEBUG_OPTIONS_FIELD pool_debug_options
extern void mps_pool_check_fenceposts(mps_pool_t);
extern void mps_pool_check_free_space(mps_pool_t);
/* Scanner Support */
extern mps_res_t mps_fix(mps_ss_t, mps_addr_t *);
#define MPS_SCAN_BEGIN(ss) \
MPS_BEGIN \
mps_ss_t _ss = (ss); \
mps_word_t _mps_zs = (_ss)->_zs; \
mps_word_t _mps_w = (_ss)->_w; \
mps_word_t _mps_ufs = (_ss)->_ufs; \
mps_word_t _mps_wt; \
{
#define MPS_FIX1(ss, ref) \
(_mps_wt = (mps_word_t)1 << ((mps_word_t)(ref) >> _mps_zs \
& (sizeof(mps_word_t) * CHAR_BIT - 1)), \
_mps_ufs |= _mps_wt, \
(_mps_w & _mps_wt) != 0)
extern mps_res_t _mps_fix2(mps_ss_t, mps_addr_t *);
#define MPS_FIX2(ss, ref_io) _mps_fix2(ss, ref_io)
#define MPS_FIX12(ss, ref_io) \
(MPS_FIX1(ss, *(ref_io)) ? \
MPS_FIX2(ss, ref_io) : MPS_RES_OK)
/* MPS_FIX is deprecated */
#define MPS_FIX(ss, ref_io) MPS_FIX12(ss, ref_io)
#define MPS_FIX_CALL(ss, call) \
MPS_BEGIN \
(call); _mps_ufs |= (ss)->_ufs; \
MPS_END
#define MPS_SCAN_END(ss) \
} \
(ss)->_ufs = _mps_ufs; \
MPS_END
#endif /* mps_h */
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Redistributions in any form must be accompanied by information on how
* to obtain complete source code for this software and any accompanying
* software that uses this software. The source code must either be
* included in the distribution or be available for no more than the cost
* of distribution plus a nominal fee, and must be freely redistributable
* under reasonable conditions. For an executable file, complete source
* code means the source code for all modules it contains. It does not
* include source code for modules or files that typically accompany the
* major components of the operating system on which the executable file
* runs.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/