mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
fa20edc44d
- Remove most __ASSEMBLER__ __LINKER__ ifdefs - Rename libc/intrin/bits.h to libc/serialize.h - Block pthread cancelation in fchmodat() polyfill - Remove `clang-format off` statements in third_party
136 lines
4.6 KiB
C++
136 lines
4.6 KiB
C++
|
|
/* ------------------ Operations on head and foot fields ----------------- */
|
|
|
|
/*
|
|
The head field of a chunk is or'ed with PINUSE_BIT when previous
|
|
adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in
|
|
use, unless mmapped, in which case both bits are cleared.
|
|
|
|
FLAG4_BIT is not used by this malloc, but might be useful in extensions.
|
|
*/
|
|
|
|
#define PINUSE_BIT (SIZE_T_ONE)
|
|
#define CINUSE_BIT (SIZE_T_TWO)
|
|
#define FLAG4_BIT (SIZE_T_FOUR)
|
|
#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
|
|
#define FLAG_BITS (PINUSE_BIT|CINUSE_BIT|FLAG4_BIT)
|
|
|
|
/* Head value for fenceposts */
|
|
#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
|
|
|
|
/* extraction of fields from head words */
|
|
#define cinuse(p) ((p)->head & CINUSE_BIT)
|
|
#define pinuse(p) ((p)->head & PINUSE_BIT)
|
|
#define flag4inuse(p) ((p)->head & FLAG4_BIT)
|
|
#define is_inuse(p) (((p)->head & INUSE_BITS) != PINUSE_BIT)
|
|
#define is_mmapped(p) (((p)->head & INUSE_BITS) == 0)
|
|
|
|
#define chunksize(p) ((p)->head & ~(FLAG_BITS))
|
|
|
|
#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
|
|
#define set_flag4(p) ((p)->head |= FLAG4_BIT)
|
|
#define clear_flag4(p) ((p)->head &= ~FLAG4_BIT)
|
|
|
|
/* Treat space at ptr +/- offset as a chunk */
|
|
#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
|
|
#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s)))
|
|
|
|
/* Ptr to next or previous physical malloc_chunk. */
|
|
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~FLAG_BITS)))
|
|
#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) ))
|
|
|
|
/* extract next chunk's pinuse bit */
|
|
#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
|
|
|
|
/* Get/set size at footer */
|
|
#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot)
|
|
#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s))
|
|
|
|
/* Set size, pinuse bit, and foot */
|
|
#define set_size_and_pinuse_of_free_chunk(p, s)\
|
|
((p)->head = (s|PINUSE_BIT), set_foot(p, s))
|
|
|
|
/* Set size, pinuse bit, foot, and clear next pinuse */
|
|
#define set_free_with_pinuse(p, s, n)\
|
|
(clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
|
|
|
|
/* Get the internal overhead associated with chunk p */
|
|
#define overhead_for(p)\
|
|
(is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
|
|
|
|
/* Return true if malloced space is not necessarily cleared */
|
|
#if MMAP_CLEARS
|
|
#define calloc_must_clear(p) (!is_mmapped(p))
|
|
#else /* MMAP_CLEARS */
|
|
#define calloc_must_clear(p) (1)
|
|
#endif /* MMAP_CLEARS */
|
|
|
|
|
|
struct malloc_tree_chunk {
|
|
/* The first four fields must be compatible with malloc_chunk */
|
|
size_t prev_foot;
|
|
size_t head;
|
|
struct malloc_tree_chunk* fd;
|
|
struct malloc_tree_chunk* bk;
|
|
|
|
struct malloc_tree_chunk* child[2];
|
|
struct malloc_tree_chunk* parent;
|
|
bindex_t index;
|
|
};
|
|
|
|
typedef struct malloc_tree_chunk tchunk;
|
|
typedef struct malloc_tree_chunk* tchunkptr;
|
|
typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */
|
|
|
|
/* A little helper macro for trees */
|
|
#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
|
|
|
|
struct malloc_segment {
|
|
char* base; /* base address */
|
|
size_t size; /* allocated size */
|
|
struct malloc_segment* next; /* ptr to next segment */
|
|
flag_t sflags; /* mmap and extern flag */
|
|
};
|
|
|
|
#define is_mmapped_segment(S) ((S)->sflags & USE_MMAP_BIT)
|
|
#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT)
|
|
|
|
typedef struct malloc_segment msegment;
|
|
typedef struct malloc_segment* msegmentptr;
|
|
|
|
/* Bin types, widths and sizes */
|
|
#define NSMALLBINS (32U)
|
|
#define NTREEBINS (32U)
|
|
#define SMALLBIN_SHIFT (3U)
|
|
#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
|
|
#define TREEBIN_SHIFT (8U)
|
|
#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
|
|
#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
|
|
#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
|
|
|
|
struct malloc_state {
|
|
binmap_t smallmap;
|
|
binmap_t treemap;
|
|
size_t dvsize;
|
|
size_t topsize;
|
|
char* least_addr;
|
|
mchunkptr dv;
|
|
mchunkptr top;
|
|
size_t trim_check;
|
|
size_t release_checks;
|
|
size_t magic;
|
|
mchunkptr smallbins[(NSMALLBINS+1)*2];
|
|
tbinptr treebins[NTREEBINS];
|
|
size_t footprint;
|
|
size_t max_footprint;
|
|
size_t footprint_limit; /* zero means no limit */
|
|
flag_t mflags;
|
|
#if USE_LOCKS
|
|
MLOCK_T mutex; /* locate lock among fields that rarely change */
|
|
#endif /* USE_LOCKS */
|
|
msegment seg;
|
|
void* extp; /* Unused but available for extensions */
|
|
size_t exts;
|
|
};
|
|
|
|
typedef struct malloc_state* mstate;
|