Files
QNX/lib/c/alloc/malloc-lib.h
2025-08-20 19:02:58 +08:00

263 lines
7.6 KiB
C

/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
/*-
* internal definitions for allocation library.
*/
#ifndef malloc_lib_h
#define malloc_lib_h
#include <sys/types.h>
#include <assert.h>
#include <stdlib.h>
#include <limits.h>
/*-
* UNITS partitions n modulo m.
* ROUND rounds(up) a number to a multiple of m.
* TRUNC truncates a number mod m.
*/
#define __UNITS(n,m) (((n)+((m)-1))/(m))
#define __ROUND(n,m) ((m)*__UNITS(((ulong_t)(n)),(m)))
#define __TRUNC(n,m) ((m)*(((ulong_t)(n))/(m)))
#define PSIZ 4096
/*
* Define to gather statistics (used by the tools)
*/
#define STATISTICS 1
typedef struct Arena Arena;
typedef struct Dhead Dhead;
typedef struct Dtail Dtail;
typedef struct Flink Flink;
/*
* Data structure used to link all data blocks within and Arena.
*
* The high bits of d_size indicate the size of the buffer, including
* the size of Dhead and its bookend structure Dtail. If the buffer
* is available, the low bit will be free, and the buffer will be
* queued on a free list (see Flink below).
*/
struct Dhead {
ssize_t d_size; /* size of this block, inc Dhead */
#ifdef MALLOC_PC
unsigned int * d_callerpc; /* caller's id */
#endif
#ifdef MALLOC_GUARD
ssize_t d_usize; /* user-requested size */
#endif
};
/*
* Data structure appended to allocated buffer.
*
* The Dtail structure is the bookend for the Dhead structure.
* First element must match Flink.
*
* d_size low bit is set when buffer is allocated.
*/
struct Dtail {
ssize_t d_tail; /* encoded size & busy-bit */
};
/*
* Data structure to link free blocks. First element must match Dhead.
*/
struct Flink {
ssize_t f_size; /* size of this block, inc Flink */
Flink * f_next; /* next free block */
Flink * f_prev; /* prev free block */
};
/*
* Data structure used to link discontiguous memory arenas.
* Arenas are are always page aligned and multiples of pages in size.
*/
struct Arena {
Arena * a_next; /* next arena */
Arena * a_prev; /* prev free block */
int a_size; /* size of arena in bytes */
struct Dtail a_dtail; /* mimic dtail */
};
/*
* Dhead & Dtail low bit is set to indicate busy.
* The DH_ macros are cast so they can be called for Flink pointers, too.
*/
#define DH_BUSY(dh) (((Dhead *)(dh))->d_size |= 1)
#define DH_UNBUSY(dh) (((Dhead *)(dh))->d_size &= ~1)
#define DH_ISBUSY(dh) (((Dhead *)(dh))->d_size & 1)
#define DH_ISFREE(dh) !DH_ISBUSY(dh)
#define DH_LEN(dh) (((Dhead *)(dh))->d_size & ~1)
#define DH_ISARENA(dh) (((Dhead *)(dh))->d_size == 1)
#ifdef MALLOC_GUARD
#define DH_ULEN(dh) (((Dhead *)(d))->d_usize)
#else
#define DH_ULEN(dh) (0)
#endif
#define D_OVERHEAD() (sizeof(Dhead) + sizeof(Dtail))
/*
* We xor Dhead d_size to create Dtail bits. We do this instead of
* just copying Dhead->d_size so that we don't get fooled by a process
* errantly copying the same pattern over an entire Dlist block.
* We still or-in the low bit _before_ setting d_tail, so a free block
* has a dtail with the low bit _set_.
*/
#define DTSZ(sz) ((sz) ^ 0xffffffff)
#define DT_SET(dt,sz) ((dt)->d_tail = DTSZ(sz))
#define DT_LEN(dt) (((dt)->d_tail ^ 0xffffffff) & ~1)
#define DT_ISFREE(dt) ((dt)->d_tail & 1)
#define DT_ISBUSY(dt) !DT_ISFREE(dt)
#define DT_ISARENA(dt) (DT_LEN(dt) == 0)
#define HEAD_TO_DT(dh) (Dtail *)((char *)(dh) + DH_LEN(dh)) - 1
#define DT_TO_HEAD(dt) (Dtail *)((char *)(dt) - DT_LEN(dt)) + 1
#define DT_TO_DHEAD(dt) (Dhead *)(DT_TO_HEAD(dt))
#define DT_TO_FLINK(dt) (Flink *)(DT_TO_HEAD(dt))
#define _ADJACENT(x) ((void *)((char *)x + DH_LEN(x)))
/* extra padding to ensure alignment is on _MALLOC_ALIGN */
#define MA_PADDING (__ROUND(sizeof(Dhead), _MALLOC_ALIGN)-sizeof(Dhead))
#define SET_DTAIL(dh) DT_SET(HEAD_TO_DT(dh), (dh)->d_size | 1)
#define ARENA_OVERHEAD() (sizeof(Arena) + sizeof(Dtail))
#define TOTAL_ARENA_OVERHEAD() (ARENA_OVERHEAD() + MA_PADDING)
#define _MIN_FSIZE() (sizeof(Flink) + sizeof(Dtail))
extern void _list_release(Dhead *);
extern void *_list_alloc(ssize_t);
extern void *_list_memalign(size_t __align, ssize_t __size);
extern void *_list_resize(void *, unsigned);
extern void _list_gc(void);
/*
* Small-block allocator.
*/
typedef union ListNode ListNode;
typedef struct Band Band;
typedef struct Block Block;
union ListNode {
ListNode * ln_next; /* when free, next entry */
ssize_t ln_offset; /* when allocate, offset */
Dhead ln_head; /* when allocated, for GUARD, PC */
};
struct Band {
// the order of the first three elements is important
// they must be in this order, and must be the first 3
short nbpe; /* element size */
short nalloc; /* elements per block */
size_t slurp;
size_t esize;
size_t mem;
size_t rem;
unsigned nalloc_stats;
/*- private: */
Block * alist; /* Blocks that have data to allocate */
Block * dlist; /* completely allocated (depleted) Blocks */
#ifdef STATISTICS
unsigned blk_alloced; /* #blocks allocated */
unsigned blk_freed; /* #blocks freed */
unsigned alloc_counter; /* allocs */
unsigned free_counter; /* frees */
unsigned blk_size; /* size of allocated blocks */
#endif
};
#ifdef __GNUC__
# define BLOCK_MAGIC (unsigned)0x594f484e
#else
# define BLOCK_MAGIC (unsigned)'YOHN'
#endif
struct Block {
unsigned magic; /* guard */
char * bend; /* pointer to end of list */
Block *next; /* next block in Band */
Block *prev; /* previous block in Band */
Band *band; /* this block's band */
short nbpe; /* cached Band nbpe */
short navail; /* number of free units in block */
ListNode *head; /* freelist in block */
};
#define CORESIZE(n) __ROUND((n), PSIZ)
extern char * morecore(unsigned nbytes, int fixed, int *rsize);
extern int donecore(void *p, unsigned nbytes);
extern void * _band_get(Band *p, size_t);
extern void * _band_get_aligned(Band *p, size_t __align, size_t __size);
extern void _band_rlse(Block *p, void *up);
extern Band *__static_Bands[];
extern unsigned __static_nband;
extern Band **__pBands;
extern unsigned *__pnband;
extern int __mallocsizes_inited;
#define MAX_BAND_SIZE() (__pBands[(*__pnband)-1]->nbpe)
/*-
* watcom carry overs: amblksiz is the allocation request size.
* (defined in <stdlib.h>)
* amhiwater is the threshold to release at.
*/
extern unsigned _amhiwater; /* minsize to release to system */
extern struct malloc_stats _malloc_stats;
/*
* miscellany
*/
#ifndef NDEBUG
extern void _malloc_error(const char *file, unsigned int lineno, const char *msg);
#define panic(x) _malloc_error(__FILE__, __LINE__, (x))
#else
#define panic(x)
#endif
extern void (*_malloc_abort)(enum mcheck_status);
extern enum mcheck_status _malloc_guard_status (void *, Dhead *, ssize_t);
extern void malloc_abort (enum mcheck_status);
#ifdef MALLOC_GUARD
extern void _malloc_check_guard (void *, Dhead *, ssize_t);
#endif
extern int malloc_opts(int cmd, void *arg2);
#include <malloc-common.h>
#endif /* malloc_lib_h */
/* __SRCVERSION("malloc-lib.h $Rev: 153052 $"); */