summaryrefslogblamecommitdiffstats
path: root/private/crt32/h/heap.h
blob: 2650fe8b20b3346bcc1d683903609560b0696437 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
















































































































































































































































































































































































































































                                                                                    
/***
* heap.h - Heap code include file
*
*       Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       Contains information needed by the C library heap code.
*       [Internal]
*
*Revision History:
*       05-16-89  JCR   Module created
*       06-02-89  GJF   Removed naming conflict
*       06-29-89  JCR   Completely new for "New heap - rev 2"
*       06-29-89  GJF   Added _HDRSIZE, fixed some minor glitches.
*       06-29-89  GJF   Added _BLKSIZE(), fixed more minor bugs.
*       06-30-89  GJF   Changed several macros to operate on a pointer to a
*                       descriptor, rather than a descriptor itself.
*       06-30-89  JCR   Corrected/updated several macros
*       07-06-89  JCR   Added region support, misc improvements, etc.
*       07-07-89  GJF   Minor bug in _ROUND() macro
*       07-07-89  JCR   Added _DUMMY status
*       07-19-89  GJF   Removed _PBACKPTR macro
*       07-20-89  JCR   Region routine prototypes, _HEAPFIND values
*       07-21-89  JCR   #define _heap_growsize to _amblksiz for compatibility
*       07-25-89  GJF   Added prototypes for calloc, free and malloc
*       07-28-89  GJF   Added prototype for _msize
*       08-28-89  JCR   Added _HEAP_COALESCE value
*       10-30-89  GJF   Fixed copyright
*       11-03-89  GJF   Added _DISTTOBNDRY(), _NEXTSEGBNDRY() macros and
*                       prototypes for _flat_malloc(), _heap_advance_rover(),
*                       _heap_split_block() functions
*       11-07-89  GJF   Added _SEGSIZE_, added prototype for _heap_search()
*                       restored function prototype for_heap_grow_region()
*       11-08-89  JCR   Added non-pow2 rounding macro
*       11-10-89  JCR   Added _heap_free_region prototype
*       11-10-89  GJF   Added prototypes and macros for multi-thread support
*       11-16-89  JCR   If DEBUG defined include <assert.h>, added sanity check
*       12-13-89  GJF   Removed prototypes duplicated in malloc.h
*       12-20-89  GJF   Removed plastdesc from _heap_desc_ struct, removed
*                       _DELHEAP and _ADDHEAP macros (unused and wrong), added
*                       explicit _cdecl to function prototypes
*       01-08-89  GJF   Use assert macro from assertm.h instead of assert.h
*       03-01-90  GJF   Added #ifndef _INC_HEAP and #include <cruntime.h>
*                       stuff. Also, removed some unused DEBUG286 stuff.
*       03-22-90  GJF   Replaced _cdecl with _CALLTYPE1 in prototypes.
*       07-25-90  SBM   Replaced <assertm.h> by <assert.h>
*       08-13-90  SBM   Added casts to macros for clean compiles at -W3
*       12-28-90  SRW   Fixed _heap_split_block prototype to match code
*       12-28-90  SRW   Changed _HEAP_GROWSIZE to be 0x10000 [_WIN32_]
*       03-05-91  GJF   Added decl for _heap_resetsize, removed proto for
*                       _heap_advance_rover (both conditioned on _OLDROVER_
*                       not being #define-d).
*       03-13-91  GJF   Made _HEAP_GROWSIZE 32K for [_CRUISER_].
*       04-09-91  PNT   Added _MAC_ definitions
*       08-20-91  JCR   C++ and ANSI naming
*       03-30-92  DJM   POSIX support.
*       08-06-92  GJF   Function calling type and variable type macros.
*       01-21-93  GJF   Removed support for C6-386's _cdecl.
*
*******************************************************************************/

#ifdef _POSIX_ /* Since the heap routines are the same as WIN32 under
                  POSIX, define _WIN32_ if we are in POSIX */

#define _WIN32_
#endif

#ifndef _INC_HEAP

#ifdef __cplusplus
extern "C" {
#endif

#include <cruntime.h>

#ifdef DEBUG
#include <assert.h>
#endif

/*
 * Conditional macro definition for function calling type and variable type
 * qualifiers.
 */
#if   ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )

/*
 * Definitions for MS C8-32 (386/486) compiler
 */
#define _CRTAPI1 __cdecl
#define _CRTAPI2 __cdecl

#else

/*
 * Other compilers (e.g., MIPS)
 */
#define _CRTAPI1
#define _CRTAPI2

#endif


/*
 * Heap block descriptor
 */

struct _block_descriptor {
        struct _block_descriptor *pnextdesc;    /* ptr to next descriptor */
        void *pblock;                           /* ptr to memory block */
};

#define _BLKDESC        struct _block_descriptor
#define _PBLKDESC       struct _block_descriptor *


/*
 * Useful Constants
 */

/* size of the header in a memory block */
#define _HDRSIZE        sizeof(void *)

/* _heapchk/_heapset parameter */
#define _HEAP_NOFILL    0x7FFFFFF


/*
 * Descriptor status values
 */

#define _INUSE          0
#define _FREE           1
#define _DUMMY          2


#if (_INUSE != 0)
#error *** Heap code assumes _INUSE value is 0! ***
#endif


/*
 * Macros for manipulating heap memory block descriptors
 *      stat = one of the status values
 *      addr = user-visible address of a heap block
 */

#define _STATUS_MASK    0x3     /* last 2 bits are status */

#define _ADDRESS(pdesc)         ( (void *) ((unsigned)((pdesc)->pblock) & \
                                (~_STATUS_MASK)) )
#define _STATUS(pdesc)          ( (unsigned) ((unsigned)((pdesc)->pblock) & \
                                _STATUS_MASK) )

#define _SET_INUSE(pdesc)       ( pdesc->pblock = (void *) \
                                   ((unsigned)_ADDRESS(pdesc) | _INUSE) )
#define _SET_FREE(pdesc)        ( pdesc->pblock = (void *) \
                                   ((unsigned)_ADDRESS(pdesc) | _FREE) )
#define _SET_DUMMY(pdesc)       ( pdesc->pblock = (void *) \
                                   ((unsigned)_ADDRESS(pdesc) | _DUMMY) )

#define _IS_INUSE(pdesc)        ( _STATUS(pdesc) == _INUSE )
#define _IS_FREE(pdesc)         ( _STATUS(pdesc) == _FREE )
#define _IS_DUMMY(pdesc)        ( _STATUS(pdesc) == _DUMMY )

#define _BLKSIZE(pdesc)         ( (unsigned) ( \
                                  (char *)_ADDRESS(pdesc->pnextdesc) - \
                                  (char *)_ADDRESS(pdesc) - _HDRSIZE ) )

#define _MEMSIZE(pdesc)         ( (char *)_ADDRESS(pdesc->pnextdesc) - \
                                  (char *)_ADDRESS(pdesc) )

#define _BACKPTR(addr)          ( *(_PBLKDESC*)((char *)(addr) - _HDRSIZE) )

#define _CHECK_PDESC(pdesc)     ( (*(_PBLKDESC*) (_ADDRESS(pdesc))) == pdesc )

#define _CHECK_BACKPTR(addr)    ( ((char *)(_BACKPTR(addr)->pblock) + _HDRSIZE) \
                                == addr)


/*
 * Heap descriptor
 */

struct _heap_desc_ {

        _PBLKDESC pfirstdesc;   /* pointer to first descriptor */
        _PBLKDESC proverdesc;   /* rover pointer */
        _PBLKDESC emptylist;    /* pointer to empty list */

        _BLKDESC  sentinel;     /* Sentinel block for end of heap list */

};

extern struct _heap_desc_ _heap_desc;


/*
 * Region descriptor and heap grow data
 */

struct _heap_region_ {
        void * _regbase;        /* base address of region */
        unsigned _currsize;     /* current size of region */
        unsigned _totalsize;    /* total size of region */
        };

#ifndef _OLDROVER_
extern unsigned int _heap_resetsize;
#endif  /* _OLDROVER_ */
#define _heap_growsize _amblksiz
extern unsigned int _heap_regionsize;
extern struct _heap_region_ _heap_regions[];

#ifdef _M_ALPHA
#define _PAGESIZE_              0x2000          /* Alpha has 8k pages */
#else
#define _PAGESIZE_              0x1000          /* one page */
#endif

#define _SEGSIZE_               0x10000         /* one segment (i.e., 64 Kb) */
#define _HEAP_REGIONMAX         0x10            /* Max number of regions */
#define _HEAP_REGIONSIZE        0x400000        /* Default region size (4 meg) */

#ifdef  _CRUISER_       /* CRUISER TARGET */
#define _HEAP_GROWSIZE          0x8000          /* Default grow increment (32K) */
#else   /* ndef _CRUISER_ */

#ifdef  _WIN32_
#define _HEAP_GROWSIZE          0x10000         /* Default grow increment (64K) */
#else   /* ndef _WIN32_ */

#ifdef  _MAC_
#define _HEAP_GROWSIZE          0x8000          /* Default grow increment (32K) */
#else   /* ndef _MAC_ */

#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!

#endif  /* _MAC_ */

#endif  /* _WIN32_ */

#endif  /* _CRUISER_ */

#define _HEAP_GROWMIN           _PAGESIZE_      /* Minimum grow inc (1 page) */
#define _HEAP_GROWSTART         _PAGESIZE_      /* Startup grow increment */
#define _HEAP_COALESCE          -1              /* Coalesce heap value */

/*
 * Values returned by _heap_findaddr() routine
 */

#define _HEAPFIND_EXACT         0       /* found address exactly */
#define _HEAPFIND_WITHIN        1       /* address is within a block */
#define _HEAPFIND_BEFORE        -1      /* address before beginning of heap */
#define _HEAPFIND_AFTER         -2      /* address after end of heap */
#define _HEAPFIND_EMPTY         -3      /* address not found: empty heap */

/*
 * Arguments to _heap_param
 */

#define _HP_GETPARAM    0               /* get heap parameter value */
#define _HP_SETPARAM    1               /* set heap parameter value */

#define _HP_AMBLKSIZ    1               /* get/set _amblksiz value (aka */
#define _HP_GROWSIZE    _HP_AMBLKSIZ    /* _heap_growsize */
#define _HP_RESETSIZE   2               /* get/set _heap_resetsize value */


/*
 * Macros to round numbers
 *
 * _ROUND2 = rounds a number up to a power of 2
 * _ROUND = rounds a number up to any other numer
 *
 * n = number to be rounded
 * pow2 = must be a power of two value
 * r = any number
 */

#define _ROUND2(n,pow2) \
        ( ( n + pow2 - 1) & ~(pow2 - 1) )

#define _ROUND(n,r) \
        ( ( (n/r) + ((n%r)?1:0) ) * r)

/*

   Macros for accessing heap descriptor lists:

        _GETEMPTY(x) = Returns a pointer to an empty heap desc
        _PUTEMPTY(x) = Puts an empty heap desc on the empty list

        (x = _PBLKDESC = pointer to heap block descriptor)
*/

#ifdef DEBUG

#define _GETEMPTY(x) \
{                                                       \
        if (_heap_desc.emptylist == NULL)               \
                _heap_grow_emptylist();                 \
                                                        \
        x = _heap_desc.emptylist;                       \
                                                        \
        assert(("bad descriptor in empty list", x->pblock == NULL)); \
                                                        \
        _heap_desc.emptylist = _heap_desc.emptylist->pnextdesc; \
}

#define _PUTEMPTY(x) \
{                                                       \
        x->pnextdesc = _heap_desc.emptylist;            \
                                                        \
        x->pblock = NULL;                               \
                                                        \
        _heap_desc.emptylist = x;                       \
}

#else

#define _GETEMPTY(x) \
{                                                       \
        if (_heap_desc.emptylist == NULL)               \
                _heap_grow_emptylist();                 \
                                                        \
        x = _heap_desc.emptylist;                       \
                                                        \
        _heap_desc.emptylist = _heap_desc.emptylist->pnextdesc; \
}

#define _PUTEMPTY(x) \
{                                                       \
        x->pnextdesc = _heap_desc.emptylist;            \
                                                        \
        _heap_desc.emptylist = x;                       \
}

#endif


/*
 * Macros for finding the next 64 Kb boundary from a pointer
 */

#define _NXTSEGBNDRY(p)         ((void *)((unsigned)(p) & 0xffff0000 + 0x10000))

#define _DISTTOBNDRY(p)         ((unsigned)(0x10000 - (0x0000ffff & (unsigned)(p))))


/*
 * Define size_t type (if necessary)
 */

#ifndef _SIZE_T_DEFINED
typedef unsigned int size_t;
#define _SIZE_T_DEFINED
#endif


/*
 * Prototypes
 */

void * _CRTAPI1 _flat_malloc(size_t);
void _CRTAPI1 _heap_abort(void);
int _CRTAPI1 _heap_addblock(void *, unsigned int);

#ifdef  _OLDROVER_
void _CRTAPI1 _heap_advance_rover(void);
#endif  /* _OLDROVER_ */

void _CRTAPI1 _heap_free_region(int);
int _CRTAPI1 _heap_findaddr(void *, _PBLKDESC *);
int _CRTAPI1 _heap_grow(unsigned int);
void _CRTAPI1 _heap_grow_emptylist(void);
int _CRTAPI1 _heap_grow_region(unsigned, size_t);
void _CRTAPI1 _heap_init(void);

#ifndef _OLDROVER_
int _CRTAPI1 _heap_param(int, int, void *);
#endif  /* _OLDROVER_ */

_PBLKDESC _CRTAPI1 _heap_search(unsigned size);
void _CRTAPI1 _heap_split_block(_PBLKDESC, size_t);

#ifdef DEBUG
void _CRTAPI1 _heap_print_all(void);
void _CRTAPI1 _heap_print_regions(void);
void _CRTAPI1 _heap_print_desc(void);
void _CRTAPI1 _heap_print_emptylist(void);
void _CRTAPI1 _heap_print_heaplist(void);
#endif


/*
 * Prototypes and macros for multi-thread support
 */

#ifdef  MTHREAD

void _CRTAPI1 _free_lk(void *);
void * _CRTAPI1 _malloc_lk(size_t);
size_t _CRTAPI1 _msize_lk(void *);

#ifdef  DEBUG
void _CRTAPI1 _heap_print_regions_lk(void);
void _CRTAPI1 _heap_print_desc_lk(void);
void _CRTAPI1 _heap_print_emptylist_lk(void);
void _CRTAPI1 _heap_print_heaplist_lk(void);
#endif

#else   /* ndef MTHREAD */

#define _malloc_lk(s)   malloc(s)
#define _free_lk(p)     free(p)
#define _msize_lk(p)    _msize(p)

#ifdef  DEBUG
#define _heap_print_regions_lk()        _heap_print_regions()
#define _heap_print_desc_lk()           _heap_print_desc()
#define _heap_print_emptylist_lk()      _heap_print_emptylist()
#define _heap_print_heaplist_lk()       _heap_print_heaplist()
#endif

#endif  /* MTHREAD */

#ifdef __cplusplus
}
#endif

#define _INC_HEAP
#endif  /* _INC_HEAP */