257 lines
8.3 KiB
C
257 lines
8.3 KiB
C
/**************************************************************************
|
|
* *
|
|
* Copyright (C) 1989-1994 Silicon Graphics, Inc. *
|
|
* *
|
|
* These coded instructions, statements, and computer programs contain *
|
|
* unpublished proprietary information of Silicon Graphics, Inc., and *
|
|
* are protected by Federal copyright law. They may not be disclosed *
|
|
* to third parties or copied or duplicated in any form, in whole or *
|
|
* in part, without the prior written consent of Silicon Graphics, Inc. *
|
|
* *
|
|
**************************************************************************/
|
|
/* Copyright (c) 1984 AT&T */
|
|
/* All Rights Reserved */
|
|
|
|
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
|
|
/* The copyright notice above does not evidence any */
|
|
/* actual or intended publication of such source code. */
|
|
|
|
#ifndef __MALLINT_H__
|
|
#define __MALLINT_H__
|
|
|
|
#ident "$Revision: 1.14 $ $Author: jwag $"
|
|
#include "ulocks.h"
|
|
|
|
/* template for the header */
|
|
struct header {
|
|
struct header *nextblk;
|
|
struct header *prevblk;
|
|
struct header *nextfree;
|
|
struct header *prevfree;
|
|
};
|
|
/*
|
|
template for a small block
|
|
*/
|
|
struct lblk {
|
|
union {
|
|
struct lblk *nextfree; /* the next free little block in this
|
|
holding block. This field is used
|
|
when the block is free */
|
|
struct holdblk *holder; /* the holding block containing this
|
|
little block. This field is used
|
|
when the block is allocated */
|
|
} header;
|
|
char byte; /* There is no telling how big this
|
|
field freally is. */
|
|
};
|
|
#define MINSMALLHEAD ((int)sizeof(struct lblk *))
|
|
|
|
/*
|
|
template for holding block
|
|
*/
|
|
struct holdblk {
|
|
struct holdblk *nexthblk; /* next holding block */
|
|
struct holdblk *prevhblk; /* previous holding block */
|
|
struct lblk *lfreeq; /* head of free queue within block */
|
|
struct lblk *unused; /* pointer to 1st little block never used */
|
|
int blksz; /* size of little blocks contained */
|
|
int holdsz; /* useful holdblk constant */
|
|
char head[MINSMALLHEAD];/* maybe header for first small block
|
|
* in hold group (depends on alignment) */
|
|
};
|
|
|
|
/*
|
|
The following manipulate the free queue
|
|
|
|
DELFREEQ will remove x from the free queue
|
|
ADDFREEQ will add an element to the head
|
|
or tail of the free queue.
|
|
MOVEHEAD will move the free pointers so that
|
|
x is at the front of the queue
|
|
COMPACTFWD - if 'n' is free, compact with 'b'
|
|
'b's nextblk must already have been CLRBUSY
|
|
COMPACTBACK - if 'b's predecessor is free coalesce
|
|
note that 'b' is changed to point to new block
|
|
*/
|
|
#define ADDFREEQ(fptr,x) if (AP(addtotail)) addtail(fptr,x); \
|
|
else addhead(fptr,x);
|
|
#define DELFREEQ(x) (x)->prevfree->nextfree = (x)->nextfree;\
|
|
(x)->nextfree->prevfree = (x)->prevfree;\
|
|
(x)->prevfree = (x)->nextfree = 0; \
|
|
assert((x)->nextfree != (x));\
|
|
assert((x)->prevfree != (x));
|
|
#define MOVEHEAD(x) AP(freeptr)[1].prevfree->nextfree = \
|
|
AP(freeptr)[0].nextfree;\
|
|
AP(freeptr)[0].nextfree->prevfree = \
|
|
AP(freeptr)[1].prevfree;\
|
|
(x)->prevfree->nextfree = &(AP(freeptr)[1]);\
|
|
AP(freeptr)[1].prevfree = (x)->prevfree;\
|
|
(x)->prevfree = &(AP(freeptr)[0]);\
|
|
AP(freeptr)[0].nextfree = (x);\
|
|
assert((x)->nextfree != (x));\
|
|
assert((x)->prevfree != (x));
|
|
|
|
#define COMPACTFWD(b,n) { \
|
|
register struct header *nextnext; \
|
|
if (!TESTBUSY(nextnext = (n)->nextblk)) { \
|
|
DELFREEQ(n); \
|
|
(b)->nextblk = nextnext; \
|
|
nextnext->prevblk = (b); \
|
|
} \
|
|
}
|
|
|
|
#define COMPACTBACK(b) { \
|
|
register struct header *next; \
|
|
if (!TESTBUSY((next = (b)->prevblk)->nextblk)) { \
|
|
DELFREEQ(next); \
|
|
next->nextblk = (b)->nextblk; \
|
|
(b)->nextblk->prevblk = next; \
|
|
(b) = next; \
|
|
} \
|
|
}
|
|
|
|
#ifndef MAX
|
|
#define MAX(a,b) (a > b ? a : b)
|
|
#endif
|
|
#define ALIGNIT(x) (((__psint_t)(x) + ALIGNSZ - 1) & ~(ALIGNSZ - 1))
|
|
#define ISALIGNED(x) (((__psint_t)(x) & (ALIGNSZ - 1)) == 0)
|
|
/*
|
|
* Determine minimum size of regular block that should be
|
|
* put on free list. Blocks smaller than this, but large
|
|
* enough to accomodate a header, are put on the ignore
|
|
* free list to be (possibly) coalesced later.
|
|
*/
|
|
#define SETIGNSZ AP(ignoresz) = (int)ALIGNIT(AP(maxfast) + 1 + AP(minhead));
|
|
/*
|
|
The following manipulate the busy flag
|
|
*/
|
|
#define BUSY 1L
|
|
#define SETBUSY(x) ((struct header *)((__psint_t)(x) | BUSY))
|
|
#define CLRBUSY(x) ((struct header *)((__psint_t)(x) & ~BUSY))
|
|
#define TESTBUSY(x) ((__psint_t)(x) & BUSY)
|
|
/*
|
|
The following manipulate the small block flag
|
|
*/
|
|
#define SMAL 2L
|
|
#define SETSMAL(x) ((struct lblk *)((__psint_t)(x) | SMAL))
|
|
#define CLRSMAL(x) ((struct lblk *)((__psint_t)(x) & ~SMAL))
|
|
#define TESTSMAL(x) ((__psint_t)(x) & SMAL)
|
|
/*
|
|
The following manipulate both flags. They must be
|
|
type coerced
|
|
*/
|
|
#define SETALL(x) ((__psint_t)(x) | (SMAL | BUSY))
|
|
#define CLRALL(x) ((__psint_t)(x) & ~(SMAL | BUSY))
|
|
/*
|
|
Other useful constants
|
|
*/
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
/* number of bytes to align to (must be at least 4, because lower 2 bits
|
|
are used for flags */
|
|
#ifdef LIBMALLOC
|
|
#if (_MIPS_SZLONG == 32)
|
|
#define ALIGNSZ 8
|
|
#else
|
|
#define ALIGNSZ 16 /* 2*(sizeof(struct header *)) Min size */
|
|
#endif /* _MIPS_SZLONG */
|
|
#else
|
|
#define ALIGNSZ 16
|
|
#endif /* LIBMALLOC */
|
|
|
|
/*
|
|
* minhead is the larger of either:
|
|
* sizeof an allocated block header OR
|
|
* the alignment factor
|
|
*/
|
|
/*#define MINHEAD 8 UNUSED - sizeof allocated block header */
|
|
|
|
#define HEADSZ ((int)sizeof(struct header)) /* size of unallocated block header */
|
|
#define MINBLKSZ HEADSZ
|
|
|
|
#define BLOCKSZ (8*1024) /* memory is gotten from sbrk in
|
|
multiples of BLOCKSZ */
|
|
#define GROUND (struct header *)0
|
|
#define LGROUND (struct lblk *)0 /* ground for a queue within a holding
|
|
block */
|
|
#define HGROUND (struct holdblk *)0 /* ground for the holding block queue */
|
|
#ifndef NULL
|
|
#define NULL 0
|
|
#endif
|
|
/*
|
|
Structures and constants describing the holding blocks
|
|
*/
|
|
#define NUMLBLKS 100 /* default # of small blocks per
|
|
holding block */
|
|
/* size of a holding block with small blocks of size blksz */
|
|
#define AHOLDSZ (ALIGNIT(sizeof(struct holdblk)))
|
|
#define HOLDSZ(blksz) (AHOLDSZ + (blksz)*AP(numlblks))
|
|
#define MAXFAST 28 /* default maximum size block for fast
|
|
allocation */
|
|
/*
|
|
* Default maximum number of blocks to check
|
|
* before giving up and calling sbrk().
|
|
*/
|
|
#define MAXCHECK 100
|
|
#if (_MIPS_SZLONG == 32)
|
|
#define MAXALLOC 0x80000000 /* maximum bytes/malloc call */
|
|
#else
|
|
#define MAXALLOC 0x8000000000000000 /* maximum bytes/malloc call */
|
|
#endif
|
|
|
|
|
|
#ifdef LIBMALLOC
|
|
#define CHECKQ if (AP(m_debug)) __checkq();
|
|
#else
|
|
#define CHECKQ if (AP(m_debug)) __checkq(ap);
|
|
#endif
|
|
|
|
/*
|
|
* declaration of arena header for multiple arena malloc
|
|
*/
|
|
typedef struct arena_s {
|
|
int a_flags; /* various flags - see malloc.h */
|
|
/*
|
|
Variables controlling algorithm, esp. how holding blocs are
|
|
used
|
|
*/
|
|
int a_numlblks;
|
|
int a_minhead;
|
|
int a_change; /* != 0, once param changes are no
|
|
longer allowed */
|
|
int a_fastct;
|
|
int a_maxfast;
|
|
int a_ignoresz;
|
|
int a_blocksz;
|
|
int a_maxcheck;
|
|
int a_addtotail;
|
|
/* number of small block sizes to map to one size */
|
|
int a_grain;
|
|
struct header a_arena[2]; /* the second word is a minimal block to
|
|
start the arena. The first is a busy
|
|
block to be pointed to by the last
|
|
block. */
|
|
struct header a_freeptr[2]; /* first and last entry in free list */
|
|
struct header a_ignorefp[2]; /* first and last entry in list of
|
|
free blocks too small to consider */
|
|
struct header *a_arenaend; /* ptr to block marking high end of arena */
|
|
struct holdblk **a_holdhead; /* pointer to array of head pointers
|
|
to holding block chains */
|
|
/* In order to save time calculating indices, the array is 1 too
|
|
large, and the first element is unused */
|
|
int a_m_debug; /* whether to check arena each action */
|
|
usptr_t *a_usptr; /* pointer to header for user sync */
|
|
ulock_t a_lock; /* lock */
|
|
void *(*a_grow)(size_t, void *); /* grow function */
|
|
size_t a_size; /* max size in bytes for arena */
|
|
void *a_brk; /* brk value for adefgrow */
|
|
int a_grain2; /* if a_grain is pow2 then this is grain-1 */
|
|
int a_grain2shift; /* if a_grain is pow2 then this is shift val */
|
|
int a_clronfree; /* if set then clear block on free */
|
|
int a_clronfreevalue; /* set to this char value */
|
|
int a_padbuf[7]; /* some padding for shared lib compatibility */
|
|
} arena_t;
|
|
|
|
#endif /*__MALLINT_H__*/
|