1 #define malloc mm_malloc
3 #define calloc mm_calloc
5 #define realloc mm_realloc
6 #define memalign mm_memalign
7 #define valloc mm_valloc
10 extern CMK_TYPEDEF_UINT8 _memory_allocated
;
11 extern CMK_TYPEDEF_UINT8 _memory_allocated_max
;
12 extern CMK_TYPEDEF_UINT8 _memory_allocated_min
;
14 #undef sun /* I don't care if it's a sun, dangit. No special treatment. */
15 #undef BSD /* I don't care if it's BSD. Same thing. */
16 #if CMK_GETPAGESIZE_AVAILABLE
17 #define HAVE_GETPAGESIZE
22 - static linkage qualifiers by Orion
23 - bugfix by Josh (fixed sbrk alignment)
26 A version of malloc/free/realloc written by Doug Lea and released to the
30 (Mon Jun 12 07:45:17 1995: Changed status from unreleased to
31 released to reflect reality!)
34 Based loosely on libg++-1.2X malloc. (It retains some of the overall
35 structure of old version, but most details differ.)
37 Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu)
38 V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu)
39 * removed potential for odd address access in prev_chunk
40 * removed dependency on getpagesize.h
41 * misc cosmetics and a bit more internal documentation
42 * anticosmetics: mangled names in macros to evade debugger strangeness
43 * tested on sparc, hp-700, dec-mips, rs6000
44 with gcc & native cc (hp, dec only) allowing
45 Detlefs & Zorn comparison study (to appear, SIGPLAN Notices.)
47 V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g)
48 * faster bin computation & slightly different binning
49 * merged all consolidations to one part of malloc proper
50 (eliminating old malloc_find_space & malloc_clean_bin)
51 * Scan 2 returns chunks (not just 1)
53 Sat Apr 2 06:51:25 1994 Doug Lea (dl at g)
54 * Propagate failure in realloc if malloc returns 0
55 * Add stuff to allow compilation on non-ANSI compilers
56 from kpv@research.att.com
58 V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g)
59 * realloc: try to expand in both directions
60 * malloc: swap order of clean-bin strategy;
61 * realloc: only conditionally expand backwards
62 * Try not to scavenge used bins
63 * Use bin counts as a guide to preallocation
64 * Occasionally bin return list chunks in first scan
65 * Add a few optimizations from colin@nyx10.cs.du.edu
67 V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g)
71 This malloc, like any other, is a compromised design.
73 Chunks of memory are maintained using a `boundary tag' method as
74 described in e.g., Knuth or Standish. The size of the chunk is
75 stored both in the front of the chunk and at the end. This makes
76 consolidating fragmented chunks into bigger chunks very fast. The
77 size field also hold a bit representing whether a chunk is free or
80 Malloced chunks have space overhead of 8 bytes: The preceding and
81 trailing size fields. When a chunk is freed, 8 additional bytes are
82 needed for free list pointers. Thus, the minimum allocatable size is
83 16 bytes. 8 byte alignment is currently hardwired into the design.
84 This seems to suffice for all current machines and C compilers.
85 Calling memalign will return a chunk that is both 8-byte aligned
86 and meets the requested (power of two) alignment.
88 It is assumed that 32 bits suffice to represent chunk sizes. The
89 maximum size chunk is 2^31 - 8 bytes. malloc(0) returns a pointer
90 to something of the minimum allocatable size. Requests for negative
91 sizes (when size_t is signed) or with the highest bit set (when
92 unsigned) will also return a minimum-sized chunk.
94 Available chunks are kept in doubly linked lists. The lists are
95 maintained in an array of bins using approximately proportionally
96 spaced bins. There are a lot of bins (128). This may look
97 excessive, but works very well in practice. The use of very fine
98 bin sizes closely approximates the use of one bin per actually used
99 size, without necessitating the overhead of locating such bins. It
100 is especially desirable in common applications where large numbers
101 of identically-sized blocks are malloced/freed in some dynamic
102 manner, and then later are all freed. The finer bin sizes make
103 finding blocks fast, with little wasted overallocation. The
104 consolidation methods ensure that once the collection of blocks is
105 no longer useful, fragments are gathered into bigger chunks awaiting
108 The bins av[i] serve as heads of the lists. Bins contain a dummy
109 header for the chunk lists. Each bin has two lists. The `dirty' list
110 holds chunks that have been returned (freed) and not yet either
111 re-malloc'ed or consolidated. (A third free-standing list `returns'
112 contains returned chunks that have not yet been processed at all;
113 they must be kept with their `inuse' bits set.) The `clean' list
114 holds split-off fragments and consolidated space. All procedures
115 maintain the invariant that no clean chunk physically borders
116 another clean chunk. Thus, clean chunks never need to be scanned
117 during consolidation. Also, dirty chunks of bad sizes (even if too
118 big) are never used without being first consolidated:
120 The otherwise unused size field of the bin heads are used to record
121 preallocation use. When a chunk is preallocated, an approximation of
122 the number of preallocated chunks is recorded. Other scans try to
123 avoid `stealing' such chunks, but also decrement these counts so
124 that they age down across time.
130 This is a very heavily disguised first-fit algorithm.
131 Most of the heuristics are designed to maximize the likelihood
132 that a usable chunk will most often be found very quickly,
133 while still minimizing fragmentation and overhead.
135 The allocation strategy has several phases.
137 0. Convert the request size into a usable form. This currently
138 means to add 8 bytes overhead plus possibly more to obtain
139 8-byte alignment. Call this size `nb'.
142 1. Check if either of the last 2 returned (free()'d) or
143 preallocated chunk are of the exact size nb. If so, use one.
144 `Exact' means no more than MINSIZE (currently 16) bytes
145 larger than nb. This cannot be reduced, since a chunk with
146 size < MINSIZE cannot be created to hold the remainder.
148 This check need not fire very often to be effective. It
149 reduces overhead for sequences of requests for the same
150 preallocated size to a dead minimum. Exactly 2 peeks of the
151 return list is empirically the best tradeoff between wasting
152 time scanning unusaable chunks and the high temporal
153 correlation of chunk sizes in user programs.
156 2. Look for a chunk in the bin associated with nb.
158 If a chunk was found here but not in return list, and the
159 same thing happened previously, then place the first chunk on
160 the return list in its bin. (This tends to prevent future
161 useless rescans in cases where step 3 is not hit often enough
162 because chunks are found in in bins.)
164 3. Pull other requests off the returned chunk list, using one if
165 it is of exact size, else distributing into the appropriate
168 4. Look in the last scavenged bigger bin found in a previous
169 step 5, and proceed to possibly split it in step 10.
171 5. Scan through the clean lists of all larger bins, selecting
172 any chunk at all. (It will surely be big enough since it is
173 in a bigger bin.). The scan goes upward from small bins to
174 large to avoid fragmenting big bins we might need later.
176 6. Try to use a chunk remaindered during a previous malloc.
177 These chunks are kept separately in `last_remainder' to avoid
178 useless re-binning during repeated splits. Its use also tends
179 to make the scan in step 5 shorter. It must be binned prior
180 to any other consolidation.
182 If the chunk is usable, proceed to split, else bin it.
184 7. (No longer a step 7!)
186 8. Consolidate chunks in other dirty bins until a large enough
187 chunk is created. Break out and split when one is found.
189 Bins are selected for consolidation in a circular fashion
190 spanning across malloc calls. This very crudely approximates
191 LRU scanning -- it is an effective enough approximation for
194 After consolidating a bin, its use count decremented.
196 Step 9 is taken if all else fails:
198 9. Get space from the system using sbrk.
200 Memory is gathered from the system (via sbrk) in a way that
201 allows chunks obtained across different sbrk calls to be
202 consolidated, but does not require contiguous memory. Thus,
203 it should be safe to intersperse mallocs with other sbrk
206 Step 10 can be hit from any of steps 2,4-9:
208 10. If the selected chunk is too big, then:
210 * If this is the second split request for a size in a row or
211 for a size not recently found in return lists, then use
212 this chunk to preallocate up to min {bin_use(bin)+1,
213 MAX_PREALLOCS} additional chunks of size nb and place them
214 on the returned chunk list. (Placing them here rather than
215 in bins speeds up the most common case where the user
216 program requests an uninterrupted series of identically
217 sized chunks. If this is not true, the chunks will be
218 binned in step 4 soon.)
220 The actual number to prealloc depends on the available space
221 in a selected victim, so typical numbers will be less than
224 * Split off the remainder and place in last_remainder
225 (first binning the old one, if applicable.)
228 10. Return the chunk.
232 Deallocation (free) consists only of placing the chunk on a list
233 of returned chunks. free(0) has no effect. Because freed chunks
234 may be overwritten with link fields, this malloc will often die
235 when freed memory is overwritten by user programs. This can be
236 very effective (albeit in an annoying way) in helping users track
237 down dangling pointers.
240 Reallocation proceeds in the usual way. If a chunk can be extended,
241 it is, else a malloc-copy-free sequence is taken.
243 The old unix realloc convention of allowing the last-free'd chunk
244 to be used as an argument to realloc is half-heartedly supported.
245 It may in fact be used, but may have some old contents overwritten.
248 memalign arequests more than enough space from malloc, finds a spot
249 within that chunk that meets the alignment request, and then
250 possibly frees the leading and trailing space. Overreliance on
251 memalign is a sure way to fragment space.
253 * Other implementation notes
255 This malloc is NOT designed to work in multiprocessing applications.
256 No semaphores or other concurrency control are provided to ensure
257 that multiple malloc or free calls don't run at the same time, which
258 could be disasterous. A single semaphore could be used across malloc,
259 realloc, and free. It would be hard to obtain finer granularity.
261 The implementation is in straight, hand-tuned ANSI C. Among other
262 consequences, it uses a lot of macros. These would be nicer as
263 inlinable procedures, but using macros allows use with non-inlining
264 compilers, and also makes it a bit easier to control when they
265 should be expanded out by selectively embedding them in other macros
266 and procedures. (According to profile information, it is almost, but
267 not quite always best to expand.) Also, because there are so many
268 different twisty paths through malloc steps, the code is not exactly
275 /* TUNABLE PARAMETERS */
278 SBRK_UNIT is a good power of two to call sbrk with. It should
279 normally be system page size or a multiple thereof. If sbrk is very
280 slow on a system, it pays to increase this. Otherwise, it should
281 not matter too much. Also, if a program needs a certain minimum
282 amount of memory, this amount can be malloc'ed then immediately
283 free'd before starting to avoid calling sbrk so often.
286 #define SBRK_UNIT 8192
289 MAX_PREALLOCS is the maximum number of chunks to preallocate.
290 Overrides bin use stats to avoid ridiculous preallocations.
293 #define MAX_PREALLOCS 64
305 #endif /*__cplusplus*/
309 #ifndef _BEGIN_EXTERNS_
311 #define _BEGIN_EXTERNS_ extern "C" {
312 #define _END_EXTERNS_ }
314 #define _BEGIN_EXTERNS_
315 #define _END_EXTERNS_
317 #endif /*_BEGIN_EXTERNS_*/
338 #define NIL(type) ((type)0)
342 #include <stddef.h> /* for size_t */
344 #include <sys/types.h>
347 #include <stdio.h> /* needed for malloc_stats */
353 /* mechanics for getpagesize; adapted from bsd/gnu getpagesize.h */
355 #if defined(BSD) || defined(DGUX) || defined(sun) || defined(_WIN32) || defined(HAVE_GETPAGESIZE)
356 # define malloc_getpagesize getpagesize()
358 # include <sys/param.h>
359 # ifdef EXEC_PAGESIZE
360 # define malloc_getpagesize EXEC_PAGESIZE
364 # define malloc_getpagesize NBPG
366 # define malloc_getpagesize (NBPG * CLSIZE)
370 # define malloc_getpagesize NBPC
372 # define malloc_getpagesize SBRK_UNIT /* just guess */
379 }; /* end of extern "C" */
389 size_t size
; /* Size in bytes, including overhead. */
390 /* Or'ed with INUSE if in use. */
392 struct malloc_chunk
* fd
; /* double links -- used only if free. */
393 struct malloc_chunk
* bk
;
397 typedef struct malloc_chunk
* mchunkptr
;
399 /* sizes, alignments */
401 #define SIZE_SZ (sizeof(size_t))
402 #define MALLOC_MIN_OVERHEAD (SIZE_SZ + SIZE_SZ)
403 #define MALLOC_ALIGN_MASK (MALLOC_MIN_OVERHEAD - 1)
404 #define MINSIZE (sizeof(struct malloc_chunk) + SIZE_SZ)
407 /* pad request bytes into a usable size */
409 #define request2size(req) \
410 (((long)(req) <= 0) ? MINSIZE : \
411 (((req) + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) \
412 & ~(MALLOC_ALIGN_MASK)))
414 #define fastrequest2size(req) \
415 ((req) + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK) \
416 & ~(MALLOC_ALIGN_MASK)
419 /* Check if a chunk is immediately usable */
421 #define exact_fit(ptr, req) ((unsigned long)((ptr)->size - (req)) < MINSIZE)
423 /* maintaining INUSE via size field */
425 #define INUSE 0x1 /* size field is or'd with INUSE when in use */
426 /* INUSE must be exactly 1, so can coexist with size */
428 #define inuse(p) ((p)->size & INUSE)
429 #define set_inuse(p) ((p)->size |= INUSE)
430 #define clear_inuse(p) ((p)->size &= ~INUSE)
434 /* Physical chunk operations */
436 /* Ptr to next physical malloc_chunk. */
438 #define next_chunk(p)\
439 ((mchunkptr)( ((char*)(p)) + ((p)->size & ~INUSE) ))
441 /* Ptr to previous physical malloc_chunk */
443 #define prev_chunk(p)\
444 ((mchunkptr)( ((char*)(p)) - ( *((size_t*)((char*)(p) - SIZE_SZ)) & ~INUSE)))
446 /* place size at front and back of chunk */
448 #define set_size(P, Sz) \
451 (P)->size = *((size_t*)((char*)(P) + Sss - SIZE_SZ)) = Sss; \
454 /* set size & inuse at same time */
455 #define set_inuse_size(P, Sz) \
458 *((size_t*)((char*)(P) + Sss - SIZE_SZ)) = Sss; \
459 (P)->size = Sss | INUSE; \
463 /* conversion from malloc headers to user pointers, and back */
465 #define chunk2mem(p) ((Void_t*)((char*)(p) + SIZE_SZ))
466 #define mem2chunk(mem) ((mchunkptr)((char*)(mem) - SIZE_SZ))
475 struct malloc_chunk dhd
; /* dirty list header */
476 struct malloc_chunk chd
; /* clean list header */
479 typedef struct malloc_bin
* mbinptr
;
482 /* field-extraction macros */
484 #define clean_head(b) (&((b)->chd))
485 #define first_clean(b) ((b)->chd.fd)
486 #define last_clean(b) ((b)->chd.bk)
488 #define dirty_head(b) (&((b)->dhd))
489 #define first_dirty(b) ((b)->dhd.fd)
490 #define last_dirty(b) ((b)->dhd.bk)
492 /* size field of dirty head tracks whether bin is used */
494 #define bin_use(b) ((b)->dhd.size)
495 #define add_bin_use(b, nu) ((b)->dhd.size += (nu))
496 #define inc_bin_use(b) ((b)->dhd.size++)
497 #define halve_bin_use(b) ((b)->dhd.size=(unsigned long)((b)->dhd.size) >> 1)
498 #define clr_bin_use(b) ((b)->dhd.size = 0)
499 #define set_bin_use(b) ((b)->dhd.size = 1)
501 #define prealloc_size(b) ((b)->chd.size)
502 #define set_prealloc_size(b, sz) ((b)->chd.size = (sz))
506 /* The bins, initialized to have null double linked lists */
509 /* first 2 and last 1 bin unused but simplify indexing */
510 #define FIRSTBIN (&(av[2]))
511 #define LASTBIN (&(av[NBINS-2]))
513 #define PRE_FIRSTBIN (&(av[1]))
514 #define POST_LASTBIN (&(av[NBINS-1]))
517 /* sizes < MAX_SMALLBIN_SIZE are special-cased since bins are 8 bytes apart */
519 #define MAX_SMALLBIN_SIZE 512
520 #define SMALLBIN_SIZE 8
522 /* Helper macro to initialize bins */
524 {{ 0, &(av[i].dhd), &(av[i].dhd) }, { 0, &(av[i].chd), &(av[i].chd) }}
526 static struct malloc_bin av
[NBINS
] =
528 IAV(0), IAV(1), IAV(2), IAV(3), IAV(4),
529 IAV(5), IAV(6), IAV(7), IAV(8), IAV(9),
530 IAV(10), IAV(11), IAV(12), IAV(13), IAV(14),
531 IAV(15), IAV(16), IAV(17), IAV(18), IAV(19),
532 IAV(20), IAV(21), IAV(22), IAV(23), IAV(24),
533 IAV(25), IAV(26), IAV(27), IAV(28), IAV(29),
534 IAV(30), IAV(31), IAV(32), IAV(33), IAV(34),
535 IAV(35), IAV(36), IAV(37), IAV(38), IAV(39),
536 IAV(40), IAV(41), IAV(42), IAV(43), IAV(44),
537 IAV(45), IAV(46), IAV(47), IAV(48), IAV(49),
538 IAV(50), IAV(51), IAV(52), IAV(53), IAV(54),
539 IAV(55), IAV(56), IAV(57), IAV(58), IAV(59),
540 IAV(60), IAV(61), IAV(62), IAV(63), IAV(64),
541 IAV(65), IAV(66), IAV(67), IAV(68), IAV(69),
542 IAV(70), IAV(71), IAV(72), IAV(73), IAV(74),
543 IAV(75), IAV(76), IAV(77), IAV(78), IAV(79),
544 IAV(80), IAV(81), IAV(82), IAV(83), IAV(84),
545 IAV(85), IAV(86), IAV(87), IAV(88), IAV(89),
546 IAV(90), IAV(91), IAV(92), IAV(93), IAV(94),
547 IAV(95), IAV(96), IAV(97), IAV(98), IAV(99),
548 IAV(100), IAV(101), IAV(102), IAV(103), IAV(104),
549 IAV(105), IAV(106), IAV(107), IAV(108), IAV(109),
550 IAV(110), IAV(111), IAV(112), IAV(113), IAV(114),
551 IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
552 IAV(120), IAV(121), IAV(122), IAV(123), IAV(124),
553 IAV(125), IAV(126), IAV(127)
561 Returns hold list of (unbinned) returned chunks
563 Even though it uses bk/fd ptrs, returns is NOT doubly linked!
564 It is singly-linked and null-terminated it is only they are
565 accessed sequentially.
569 static mchunkptr returns
= 0;
572 last_remainder holds for the remainder of the most recently split chunk
576 static mchunkptr last_remainder
= 0;
581 minClean and maxClean keep track of the minimum/maximum actually used
582 clean bin, to make loops faster
585 static mbinptr maxClean
= PRE_FIRSTBIN
;
586 static mbinptr minClean
= POST_LASTBIN
;
601 2 bins of size 262144
602 1 bin of size what's left
604 There is actually a little bit of slop in the numbers in findbin()
605 for the sake of speed. This makes no difference elsewhere.
608 #define findbin(Sizefb, Bfb) \
610 unsigned long Ofb = (Sizefb) >> 3; \
611 unsigned long Nfb = Ofb >> 6; \
613 if (Nfb < 5) Ofb = (Ofb >> 3) + 56; \
614 else if (Nfb < 21) Ofb = (Ofb >> 6) + 91; \
615 else if (Nfb < 85) Ofb = (Ofb >> 9) + 110; \
616 else if (Nfb < 341) Ofb = (Ofb >> 12) + 119; \
617 else if (Nfb < 1365) Ofb = (Ofb >> 15) + 124; \
623 /* Special case for known small bins */
625 #define smallfindbin(Sizefb, Bfb) (Bfb) = av + ((unsigned long)(Sizefb) >> 3)
633 /* Macros for linking and unlinking chunks */
635 /* take a chunk off a list */
637 #define unlink(Qul) \
639 mchunkptr Bul = (Qul)->bk; \
640 mchunkptr Ful = (Qul)->fd; \
641 Ful->bk = Bul; Bul->fd = Ful; \
645 /* place a chunk on the dirty list of its bin */
647 #define dirtylink(Qdl) \
649 mchunkptr Pdl = (Qdl); \
651 mchunkptr Hdl, Fdl; \
653 findbin(Pdl->size, Bndl); \
654 Hdl = dirty_head(Bndl); \
656 Pdl->bk = Hdl; Pdl->fd = Fdl; Fdl->bk = Hdl->fd = Pdl; \
660 /* Place a consolidated chunk on a clean list */
662 #define cleanlink(Qcl) \
664 mchunkptr Pcl = (Qcl); \
666 mchunkptr Hcl, Fcl; \
668 findbin(Qcl->size, Bcl); \
669 Hcl = clean_head(Bcl); \
672 if (Bcl < minClean) minClean = Bcl; \
673 if (Bcl > maxClean) maxClean = Bcl; \
675 Pcl->bk = Hcl; Pcl->fd = Fcl; Fcl->bk = Hcl->fd = Pcl; \
680 static void callcleanlink(mchunkptr p
)
682 static void callcleanlink(p
) mchunkptr p
;
690 /* consolidate one chunk */
692 #define consolidate(Qc) \
696 mchunkptr Pc = prev_chunk(Qc); \
700 set_size(Pc, Pc->size + (Qc)->size); \
707 mchunkptr Nc = next_chunk(Qc); \
711 set_size((Qc), (Qc)->size + Nc->size); \
718 /* Place a freed chunk on the returns */
720 #define returnlink(Prc) \
722 (Prc)->fd = returns; \
730 /* A helper for realloc */
732 static void clear_aux_lists()
734 if (last_remainder
!= 0)
736 cleanlink(last_remainder
);
742 mchunkptr p
= returns
;
751 /* Dealing with sbrk */
752 /* This is one step of malloc; broken out for simplicity */
754 static size_t sbrked_mem
= 0; /* Keep track of total mem for malloc_stats */
757 static mchunkptr
malloc_from_sys(size_t nb
)
759 static mchunkptr
malloc_from_sys(nb
) size_t nb
;
763 /* The end of memory returned from previous sbrk call */
764 static size_t* last_sbrk_end
= 0;
766 mchunkptr p
; /* Will hold a usable chunk */
767 size_t* ip
; /* to traverse sbrk ptr in size_t units */
768 char* cp
; /* result of sbrk call */
769 int offs
; /* bytes must add for alignment */
771 /* Find a good size to ask sbrk for. */
772 /* Minimally, we need to pad with enough space */
773 /* to place dummy size/use fields to ends if needed */
775 size_t sbrk_size
= ((nb
+ SBRK_UNIT
- 1 + SIZE_SZ
+ SIZE_SZ
)
776 / SBRK_UNIT
) * SBRK_UNIT
;
778 cp
= (char*)(sbrk(sbrk_size
));
779 if (cp
== (char*)(-1)) /* sbrk returns -1 on failure */
781 sbrked_mem
+= sbrk_size
;
783 if (((size_t)cp
) & MALLOC_ALIGN_MASK
) {
784 offs
= ((size_t)cp
) & MALLOC_ALIGN_MASK
;
785 cp
+= MALLOC_MIN_OVERHEAD
- offs
;
786 sbrk_size
-= MALLOC_MIN_OVERHEAD
;
792 if (last_sbrk_end
!= &ip
[-1]) /* Is this chunk continguous with last? */
794 /* It's either first time through or someone else called sbrk. */
795 /* Arrange end-markers at front & back */
797 /* Mark the front as in use to prevent merging. (End done below.) */
798 /* Note we can get away with only 1 word, not MINSIZE overhead here */
800 *ip
++ = SIZE_SZ
| INUSE
;
803 set_size(p
,sbrk_size
- (SIZE_SZ
+ SIZE_SZ
));
810 /* We can safely make the header start at end of prev sbrked chunk. */
811 /* We will still have space left at the end from a previous call */
812 /* to place the end marker, below */
814 p
= (mchunkptr
)(last_sbrk_end
);
815 set_size(p
, sbrk_size
);
817 /* Even better, maybe we can merge with last fragment: */
823 set_size(l
, p
->size
+ l
->size
);
829 /* mark the end of sbrked space as in use to prevent merging */
831 last_sbrk_end
= (size_t*)((char*)p
+ p
->size
);
832 *last_sbrk_end
= SIZE_SZ
| INUSE
;
839 /* The less-frequent steps of malloc broken out as a procedure. */
840 /* (Allows compilers to better optimize main steps.) */
843 static mchunkptr
malloc_consolidate(size_t nb
)
845 static mchunkptr
malloc_consolidate(nb
) size_t nb
;
848 static mbinptr rover
= LASTBIN
; /* Circular ptr for consolidation */
852 /* Consolidate last remainder first. */
853 /* It must be binned before any other consolidations, so might as well */
854 /* consolidate it too. This also helps make up for false-alarm */
857 mchunkptr victim
= last_remainder
;
864 if (victim
->size
>= nb
)
870 /* -------------- Sweep through and consolidate other dirty bins */
872 origin
= rover
; /* Start where left off last time. */
876 halve_bin_use(b
); /* decr use counts while traversing */
878 while ( (victim
= last_dirty(b
)) != dirty_head(b
))
883 if (victim
->size
>= nb
)
893 b
= (b
<= FIRSTBIN
)? LASTBIN
: b
- 1; /* circularly sweep */
895 } while (b
!= origin
);
898 /* ------------- Nothing available; get some from sys */
900 return malloc_from_sys(nb
);
905 MM_LINK Void_t
* malloc(size_t bytes
)
907 MM_LINK Void_t
* malloc(bytes
) size_t bytes
;
910 static mchunkptr bad_rl_chunk
= 0; /* last scanned return-list chunk */
911 static mbinptr prevClean
= FIRSTBIN
; /* likely clean bin to use */
913 mchunkptr victim
; /* will hold selected chunk */
914 mbinptr bin
; /* corresponding bin */
916 /* ----------- Peek (twice) at returns; hope for luck */
918 mchunkptr rl
= returns
; /* local for speed/simplicity */
919 size_t nb
= request2size(bytes
) ; /* padded request size; */
921 _memory_allocated
+= nb
;
923 if(_memory_allocated
> _memory_allocated_max
)
924 _memory_allocated_max
=_memory_allocated
;
925 if(_memory_allocated
< _memory_allocated_min
)
926 _memory_allocated_min
=_memory_allocated
;
930 mchunkptr snd
= rl
->fd
;
931 if (exact_fit(rl
, nb
)) /* size check works even though INUSE set */
934 return chunk2mem(rl
);
936 else if (snd
!= 0 && exact_fit(snd
, nb
))
938 returns
->fd
= snd
->fd
;
939 return chunk2mem(snd
);
941 else if (rl
== bad_rl_chunk
) /* If we keep failing, bin one */
951 /* ---------- Scan own dirty bin */
953 if (nb
< (MAX_SMALLBIN_SIZE
- SMALLBIN_SIZE
))
955 /* Small bins special-cased since no size check or traversal needed. */
956 /* Also because of MINSIZE slop, next dirty bin is exact fit too */
958 smallfindbin(nb
, bin
);
960 if ( ((victim
= last_dirty(bin
)) != dirty_head(bin
)) ||
961 ((victim
= last_clean(bin
)) != clean_head(bin
)) ||
962 ((victim
= last_dirty(bin
+1)) != dirty_head(bin
+1)))
966 return chunk2mem(victim
);
974 for (victim
=last_dirty(bin
); victim
!= dirty_head(bin
); victim
=victim
->bk
)
976 if (exact_fit(victim
, nb
)) /* Can use exact matches only here */
980 return chunk2mem(victim
);
984 for (victim
=last_clean(bin
); victim
!= clean_head(bin
); victim
=victim
->bk
)
986 if (victim
->size
>= nb
)
995 /* ------------ Search return list, placing unusable chunks in their bins */
1012 if (exact_fit(victim
, nb
))
1014 bad_rl_chunk
= returns
= rl
;
1015 return chunk2mem(victim
);
1024 /* -------------- First try last successful clean bin */
1026 if (bin
< prevClean
)
1028 if ( (victim
= last_clean(prevClean
)) != clean_head(prevClean
) )
1036 /* -------------- Scan others */
1038 for (b
= (bin
< minClean
)? minClean
: (bin
+ 1); b
<= maxClean
; ++b
)
1040 if ( (victim
= last_clean(b
)) != clean_head(b
) )
1042 /* If more, record */
1043 if (bin_use(b
) == 0 && victim
->bk
!= clean_head(b
)) prevClean
= b
;
1044 else { halve_bin_use(b
); prevClean
= FIRSTBIN
; }
1047 if (bin
< minClean
) minClean
= b
; /* b must be <= true min */
1052 /* -------------- If fall through, recompute bounds for next time */
1054 while (maxClean
>= FIRSTBIN
&& clean_head(maxClean
)==last_clean(maxClean
))
1056 if (maxClean
< FIRSTBIN
) /* reset at endpoints if no clean bins */
1057 minClean
= POST_LASTBIN
;
1060 while (minClean
< maxClean
&& clean_head(minClean
)==last_clean(minClean
))
1064 prevClean
= FIRSTBIN
;
1069 /* -------------- Try remainder from previous split */
1071 if ( (victim
= last_remainder
) != 0)
1073 if (victim
->size
>= nb
)
1081 /* -------------- Other steps called via malloc_consolidate */
1083 victim
= malloc_consolidate(nb
);
1084 if (victim
== 0) return 0; /* propagate failure */
1087 /* -------------- Possibly split victim chunk */
1091 size_t room
= victim
->size
- nb
;
1096 return chunk2mem(victim
);
1098 else /* must create remainder */
1100 mchunkptr remainder
;
1103 set_inuse_size(victim
, nb
);
1104 remainder
= (mchunkptr
)((char*)(victim
) + nb
);
1106 desired
= inc_bin_use(bin
);
1108 /* ---------- Preallocate more of this size */
1110 if (nb
< MAX_SMALLBIN_SIZE
&& room
>= nb
+ MINSIZE
&& desired
!= 0)
1114 /* place in ascending order on ret list */
1115 mchunkptr first
= remainder
;
1116 mchunkptr last
= remainder
;
1117 set_inuse_size(remainder
, nb
);
1118 remainder
= (mchunkptr
)((char*)(remainder
) + nb
);
1120 if (desired
> MAX_PREALLOCS
) desired
= MAX_PREALLOCS
;
1122 while ( (room
-= nb
) >= nb
+ MINSIZE
&& actual
< desired
)
1125 set_inuse_size(remainder
, nb
);
1126 last
->fd
= remainder
;
1128 remainder
= (mchunkptr
)((char*)(remainder
) + nb
);
1134 add_bin_use(bin
, actual
);
1137 /* ---------- Put away remainder chunk */
1139 set_size(remainder
, room
);
1141 /* get rid of old one */
1142 if (last_remainder
!= 0) callcleanlink(last_remainder
);
1143 last_remainder
= remainder
;
1145 return chunk2mem(victim
);
1155 MM_LINK
void free(Void_t
* mem
)
1157 MM_LINK
void free(mem
) Void_t
* mem
;
1162 mchunkptr p
= mem2chunk(mem
);
1163 _memory_allocated
-= p
->size
;
1171 /* Special-purpose copy for realloc */
1172 /* Copy bytes in size_t units, adjusting for chunk header */
1174 #define SCopy(SCs,SCd,SCc) \
1176 size_t * SCsrc = (size_t*) SCs; \
1177 size_t * SCdst = (size_t*) SCd; \
1178 size_t SCcount = (SCc - SIZE_SZ) / sizeof(size_t); \
1179 do { *SCdst++ = *SCsrc++; } while (--SCcount > 0); \
1184 MM_LINK Void_t
* realloc(Void_t
* mem
, size_t bytes
)
1186 MM_LINK Void_t
* realloc(mem
, bytes
) Void_t
* mem
; size_t bytes
;
1190 return malloc(bytes
);
1193 size_t nb
= request2size(bytes
);
1194 mchunkptr p
= mem2chunk(mem
);
1198 int back_expanded
= 0;
1200 if (p
== returns
) /* sorta support realloc-last-freed-chunk idiocy */
1201 returns
= returns
->fd
;
1206 /* try to expand. */
1208 clear_aux_lists(); /* make freed chunks available to consolidate */
1210 if (p
->size
< nb
) /* forward as far as possible */
1214 mchunkptr nxt
= next_chunk(p
);
1218 set_size(p
, p
->size
+ nxt
->size
);
1224 while (p
->size
< nb
) /* backward only if and as far as necessary */
1226 mchunkptr prv
= prev_chunk(p
);
1231 set_size(prv
, prv
->size
+ p
->size
);
1237 if (p
->size
< nb
) /* Could not expand. Get another chunk. */
1241 set_inuse(p
); /* don't let malloc consolidate p yet! */
1242 newmem
= malloc(nb
);
1243 newp
= mem2chunk(newmem
);
1245 /* Avoid copy if newp is next chunk after oldp. */
1246 /* This can only happen when new chunk is sbrk'ed, */
1247 /* which is common enough in reallocs to deal with here. */
1249 if (newp
== next_chunk(p
))
1252 if (back_expanded
) /* Must copy first anyway; still worth it */
1253 SCopy(mem
, chunk2mem(p
), oldsize
);
1257 set_size(p
, p
->size
+ newp
->size
);
1259 room
= p
->size
- nb
;
1260 if (room
>= MINSIZE
) /* give some back */
1262 mchunkptr remainder
= (mchunkptr
)((char*)(p
) + nb
);
1263 set_size(remainder
, room
);
1266 /* clean up remainder; it must be start of new sbrked space */
1267 clear_aux_lists(); /* Clear, in case malloc preallocated */
1270 mchunkptr nxt
= next_chunk(remainder
);
1274 set_size(remainder
, remainder
->size
+ nxt
->size
);
1278 last_remainder
= remainder
;
1282 return chunk2mem(p
);
1286 if (newmem
!= 0) SCopy(mem
, newmem
, oldsize
);
1293 room
= p
->size
- nb
;
1294 newmem
= chunk2mem(p
);
1296 if (back_expanded
) SCopy(mem
, newmem
, oldsize
);
1298 if (room
>= MINSIZE
) /* give some back if possible */
1300 mchunkptr remainder
= (mchunkptr
)((char*)(p
) + nb
);
1301 set_size(remainder
, room
);
1302 dirtylink(remainder
); /* not sure; be safe */
1307 return chunk2mem(p
);
1314 /* Return a pointer to space with at least the alignment requested */
1315 /* Alignment argument should be a power of two */
1318 MM_LINK Void_t
* memalign(size_t alignment
, size_t bytes
)
1320 MM_LINK Void_t
* memalign(alignment
, bytes
) size_t alignment
; size_t bytes
;
1324 size_t nb
= request2size(bytes
);
1327 /* find an alignment that both we and the user can live with: */
1329 size_t align
= (alignment
> MALLOC_MIN_OVERHEAD
) ?
1330 alignment
: MALLOC_MIN_OVERHEAD
;
1332 /* call malloc with worst case padding to hit alignment; */
1333 /* we will give back extra */
1335 size_t req
= nb
+ align
+ MINSIZE
;
1336 Void_t
* m
= malloc(req
);
1338 if (m
== 0) return 0; /* propagate failure */
1344 if (((size_t)(m
) % align
) != 0) /* misaligned */
1347 /* find an aligned spot inside chunk */
1349 mchunkptr ap
= (mchunkptr
)((((size_t)(m
) + align
-1) & -align
) - SIZE_SZ
);
1351 size_t gap
= (size_t)(ap
) - (size_t)(p
);
1353 /* we need to give back leading space in a chunk of at least MINSIZE */
1357 /* This works since align >= MINSIZE */
1358 /* and we've malloc'd enough total room */
1360 ap
= (mchunkptr
)( (size_t)(ap
) + align
);
1364 room
= p
->size
- gap
;
1366 /* give back leader */
1375 /* also give back spare room at the end */
1377 room
= p
->size
- nb
;
1378 if (room
>= MINSIZE
)
1380 mchunkptr remainder
= (mchunkptr
)((char*)(p
) + nb
);
1381 set_size(remainder
, room
);
1382 dirtylink(remainder
);
1387 return chunk2mem(p
);
1396 MM_LINK Void_t
* valloc(size_t bytes
)
1398 MM_LINK Void_t
* valloc(bytes
) size_t bytes
;
1401 /* Cache result of getpagesize */
1402 static size_t malloc_pagesize
= 0;
1404 if (malloc_pagesize
== 0) malloc_pagesize
= malloc_getpagesize
;
1405 return memalign (malloc_pagesize
, bytes
);
1410 MM_LINK Void_t
* calloc(size_t n
, size_t elem_size
)
1412 MM_LINK Void_t
* calloc(n
, elem_size
) size_t n
; size_t elem_size
;
1415 size_t sz
= n
* elem_size
;
1416 Void_t
* p
= malloc(sz
);
1417 char* q
= (char*) p
;
1418 while (sz
-- > 0) *q
++ = 0;
1423 MM_LINK
void cfree(Void_t
*mem
)
1425 MM_LINK
void cfree(mem
) Void_t
*mem
;
1432 size_t malloc_usable_size(Void_t
* mem
)
1434 size_t malloc_usable_size(mem
) Void_t
* mem
;
1441 mchunkptr p
= mem2chunk(mem
);
1442 size_t sz
= p
->size
& ~(INUSE
);
1443 /* report zero if not in use or detectably corrupt */
1444 if (p
->size
== sz
|| sz
!= *((size_t*)((char*)(p
) + sz
- SIZE_SZ
)))
1447 return sz
- MALLOC_MIN_OVERHEAD
;
1455 /* Traverse through and count all sizes of all chunks */
1458 size_t malloced_mem
;
1464 for (b
= FIRSTBIN
; b
<= LASTBIN
; ++b
)
1468 for (p
= first_dirty(b
); p
!= dirty_head(b
); p
= p
->fd
)
1471 for (p
= first_clean(b
); p
!= clean_head(b
); p
= p
->fd
)
1475 malloced_mem
= sbrked_mem
- avail
;
1477 fprintf(stderr
, "total mem = %10u\n", (unsigned int)sbrked_mem
);
1478 fprintf(stderr
, "in use = %10u\n", (unsigned int)malloced_mem
);