blob: 5f24c787390889b65a2da3251bfc8f4fc92a3c2e [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- An implementation of malloc/free which doesn't use sbrk. ---*/
4/*--- vg_malloc2.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000010
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
32
33#include "vg_include.h"
34
35/* Define to turn on (heavyweight) debugging machinery. */
36/* #define DEBUG_MALLOC */
37
fitzhardinge98abfc72003-12-16 02:05:15 +000038/*------------------------------------------------------------*/
39/*--- Command line options ---*/
40/*------------------------------------------------------------*/
41
42/* Round malloc sizes upwards to integral number of words? default: NO */
43Bool VG_(clo_sloppy_malloc) = False;
44
45/* DEBUG: print malloc details? default: NO */
46Bool VG_(clo_trace_malloc) = False;
47
48/* Minimum alignment in functions that don't specify alignment explicitly.
49 default: 0, i.e. use default of the machine (== 4) */
50Int VG_(clo_alignment) = 4;
51
52
53Bool VG_(replacement_malloc_process_cmd_line_option)(Char* arg)
54{
55 if (VG_CLO_STREQN(12, arg, "--alignment=")) {
56 VG_(clo_alignment) = (Int)VG_(atoll)(&arg[12]);
57
58 if (VG_(clo_alignment) < 4
59 || VG_(clo_alignment) > 4096
60 || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
61 VG_(message)(Vg_UserMsg, "");
62 VG_(message)(Vg_UserMsg,
63 "Invalid --alignment= setting. "
64 "Should be a power of 2, >= 4, <= 4096.");
65 VG_(bad_option)("--alignment");
66 }
67 }
68
69 else if (VG_CLO_STREQ(arg, "--sloppy-malloc=yes"))
70 VG_(clo_sloppy_malloc) = True;
71 else if (VG_CLO_STREQ(arg, "--sloppy-malloc=no"))
72 VG_(clo_sloppy_malloc) = False;
73
74 else if (VG_CLO_STREQ(arg, "--trace-malloc=yes"))
75 VG_(clo_trace_malloc) = True;
76 else if (VG_CLO_STREQ(arg, "--trace-malloc=no"))
77 VG_(clo_trace_malloc) = False;
78
79 else
80 return False;
81
82 return True;
83}
84
85void VG_(replacement_malloc_print_usage)(void)
86{
87 VG_(printf)(
88" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
89" --alignment=<number> set minimum alignment of allocations [4]\n"
90 );
91}
92
93void VG_(replacement_malloc_print_debug_usage)(void)
94{
95 VG_(printf)(
96" --trace-malloc=no|yes show client malloc details? [no]\n"
97 );
98}
99
sewardjde4a1d02002-03-22 01:27:54 +0000100
101/*------------------------------------------------------------*/
102/*--- Structs n stuff ---*/
103/*------------------------------------------------------------*/
104
105#define VG_REDZONE_LO_MASK 0x31415927
106#define VG_REDZONE_HI_MASK 0x14141356
107
108#define VG_N_MALLOC_LISTS 16 /* do not change this */
109
110
111typedef UInt Word;
112typedef Word WordF;
113typedef Word WordL;
114
115
116/* A superblock. */
117typedef
118 struct _Superblock {
119 struct _Superblock* next;
120 /* number of payload words in this superblock. */
121 Int n_payload_words;
122 Word payload_words[0];
123 }
124 Superblock;
125
126
127/* An arena. */
128typedef
129 struct {
130 Char* name;
fitzhardinge98abfc72003-12-16 02:05:15 +0000131 Bool clientmem; /* allocates in the client address space */
132 Int rz_szW; /* Red zone size in words */
133 Bool rz_check; /* Check red-zone on free? */
134 Int min_sblockW; /* Minimum superblock size */
sewardjde4a1d02002-03-22 01:27:54 +0000135 WordF* freelist[VG_N_MALLOC_LISTS];
136 Superblock* sblocks;
137 /* Stats only. */
138 UInt bytes_on_loan;
139 UInt bytes_mmaped;
140 UInt bytes_on_loan_max;
141 }
142 Arena;
143
144
145/* Block layout:
146
147 this block total sizeW (1 word)
148 freelist previous ptr (1 word)
149 freelist next ptr (1 word)
150 red zone words (depends on .rz_szW field of Arena)
151 (payload words)
152 red zone words (depends on .rz_szW field of Arena)
153 this block total sizeW (1 word)
154
155 Total size in words (bszW) and payload size in words (pszW)
156 are related by
157 bszW == pszW + 4 + 2 * a->rz_szW
158
159 Furthermore, both size fields in the block are negative if it is
160 not in use, and positive if it is in use. A block size of zero
161 is not possible, because a block always has at least four words
162 of overhead.
163*/
164typedef
165 struct {
166 Int bszW_lo;
167 Word* prev;
168 Word* next;
169 Word redzone[0];
170 }
171 BlockHeader;
172
173
174/*------------------------------------------------------------*/
175/*--- Forwardses ... and misc ... ---*/
176/*------------------------------------------------------------*/
177
178static Bool blockSane ( Arena* a, Word* b );
179
180/* Align ptr p upwards to an align-sized boundary. */
181static
182void* align_upwards ( void* p, Int align )
183{
184 Addr a = (Addr)p;
185 if ((a % align) == 0) return (void*)a;
186 return (void*)(a - (a % align) + align);
187}
188
189
190/*------------------------------------------------------------*/
191/*--- Arena management stuff ---*/
192/*------------------------------------------------------------*/
193
194/* The arena structures themselves. */
195static Arena vg_arena[VG_N_ARENAS];
196
197/* Functions external to this module identify arenas using ArenaIds,
198 not Arena*s. This fn converts the former to the latter. */
199static Arena* arenaId_to_ArenaP ( ArenaId arena )
200{
201 vg_assert(arena >= 0 && arena < VG_N_ARENAS);
202 return & vg_arena[arena];
203}
204
205
206/* Initialise an arena. */
207static
208void arena_init ( Arena* a, Char* name,
fitzhardinge98abfc72003-12-16 02:05:15 +0000209 Int rz_szW, Bool rz_check, Int min_sblockW, Bool client )
sewardjde4a1d02002-03-22 01:27:54 +0000210{
211 Int i;
212 vg_assert((min_sblockW % VKI_WORDS_PER_PAGE) == 0);
213 a->name = name;
fitzhardinge98abfc72003-12-16 02:05:15 +0000214 a->clientmem = client;
sewardjde4a1d02002-03-22 01:27:54 +0000215 a->rz_szW = rz_szW;
216 a->rz_check = rz_check;
217 a->min_sblockW = min_sblockW;
218 for (i = 0; i < VG_N_MALLOC_LISTS; i++) a->freelist[i] = NULL;
219 a->sblocks = NULL;
220 a->bytes_on_loan = 0;
221 a->bytes_mmaped = 0;
222 a->bytes_on_loan_max = 0;
223}
224
225
226/* Print vital stats for an arena. */
227void VG_(show_all_arena_stats) ( void )
228{
229 Int i;
230 for (i = 0; i < VG_N_ARENAS; i++) {
231 VG_(message)(Vg_DebugMsg,
232 "Arena `%s': %7d max useful, %7d mmap'd, %7d current useful",
233 vg_arena[i].name,
234 vg_arena[i].bytes_on_loan_max,
235 vg_arena[i].bytes_mmaped,
236 vg_arena[i].bytes_on_loan
237 );
238 }
239}
240
241
242/* It is important that this library is self-initialising, because it
243 may get called very early on -- as a result of C++ static
244 constructor initialisations -- before Valgrind itself is
njn25e49d8e72002-09-23 09:36:25 +0000245 initialised. Hence VG_(arena_malloc)() and VG_(arena_free)() below always
246 call ensure_mm_init() to ensure things are correctly initialised. */
sewardjde4a1d02002-03-22 01:27:54 +0000247
248static
249void ensure_mm_init ( void )
250{
251 static Bool init_done = False;
njn25e49d8e72002-09-23 09:36:25 +0000252
sewardjde4a1d02002-03-22 01:27:54 +0000253 if (init_done) return;
254
255 /* Use a checked red zone size of 1 word for our internal stuff,
256 and an unchecked zone of arbitrary size for the client. Of
njn3e884182003-04-15 13:03:23 +0000257 course the client's red zone can be checked by the skin, eg.
258 by using addressibility maps, but not by the mechanism implemented
259 here, which merely checks at the time of freeing that the red
260 zone words are unchanged. */
sewardjde4a1d02002-03-22 01:27:54 +0000261
fitzhardinge98abfc72003-12-16 02:05:15 +0000262 arena_init ( &vg_arena[VG_AR_CORE], "core", 1, True, 262144, False );
sewardjde4a1d02002-03-22 01:27:54 +0000263
fitzhardinge98abfc72003-12-16 02:05:15 +0000264 arena_init ( &vg_arena[VG_AR_SKIN], "skin", 1, True, 262144, False );
sewardjde4a1d02002-03-22 01:27:54 +0000265
fitzhardinge98abfc72003-12-16 02:05:15 +0000266 arena_init ( &vg_arena[VG_AR_SYMTAB], "symtab", 1, True, 262144, False );
njn25e49d8e72002-09-23 09:36:25 +0000267
fitzhardinge98abfc72003-12-16 02:05:15 +0000268 arena_init ( &vg_arena[VG_AR_JITTER], "JITter", 1, True, 8192, False );
njn25e49d8e72002-09-23 09:36:25 +0000269
njn3e884182003-04-15 13:03:23 +0000270 /* No particular reason for this figure, it's just smallish */
271 sk_assert(VG_(vg_malloc_redzone_szB) < 128);
272 arena_init ( &vg_arena[VG_AR_CLIENT], "client",
fitzhardinge98abfc72003-12-16 02:05:15 +0000273 VG_(vg_malloc_redzone_szB)/4, False, 262144, True );
sewardjde4a1d02002-03-22 01:27:54 +0000274
njn3e884182003-04-15 13:03:23 +0000275 arena_init ( &vg_arena[VG_AR_DEMANGLE], "demangle", 4 /*paranoid*/,
fitzhardinge98abfc72003-12-16 02:05:15 +0000276 True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000277
fitzhardinge98abfc72003-12-16 02:05:15 +0000278 arena_init ( &vg_arena[VG_AR_EXECTXT], "exectxt", 1, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000279
fitzhardinge98abfc72003-12-16 02:05:15 +0000280 arena_init ( &vg_arena[VG_AR_ERRORS], "errors", 1, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000281
fitzhardinge98abfc72003-12-16 02:05:15 +0000282 arena_init ( &vg_arena[VG_AR_TRANSIENT], "transien", 2, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000283
284 init_done = True;
285# ifdef DEBUG_MALLOC
286 VG_(mallocSanityCheckAll)();
287# endif
288}
289
290
sewardjecf8e102003-07-12 12:11:39 +0000291/* Returns True if aa is inside any segment mmap'd /dev/zero
292 by our low-level memory manager. */
293Bool VG_(is_inside_segment_mmapd_by_low_level_MM)( Addr aa )
294{
295 ArenaId ar;
296 Superblock* sb;
297
298 ensure_mm_init();
299
300 for (ar = 0; ar < VG_N_ARENAS; ar++) {
301 for (sb = vg_arena[ar].sblocks; sb; sb = sb->next) {
302 Addr sb_first_word = (Addr)sb;
303 Addr sb_last_word
304 = (Addr)&(sb->payload_words[sb->n_payload_words-1]);
305 if (aa >= sb_first_word && aa <= sb_last_word)
306 return True;
307 }
308 }
309 return False;
310}
311
312
sewardjde4a1d02002-03-22 01:27:54 +0000313/*------------------------------------------------------------*/
sewardjecf8e102003-07-12 12:11:39 +0000314/*--- Superblock management stuff ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000315/*------------------------------------------------------------*/
316
317static
318Superblock* newSuperblock ( Arena* a, Int cszW )
319{
320 Superblock* sb;
321 cszW += 2; /* Take into account sb->next and sb->n_words fields */
322 if (cszW < a->min_sblockW) cszW = a->min_sblockW;
323 while ((cszW % VKI_WORDS_PER_PAGE) > 0) cszW++;
fitzhardinge98abfc72003-12-16 02:05:15 +0000324
325 if (a->clientmem) {
326 sb = (Superblock *)VG_(client_alloc)(0, cszW * sizeof(Word),
327 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 0);
328 } else
329 sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word),
330 "newSuperblock" );
sewardjde4a1d02002-03-22 01:27:54 +0000331 sb->n_payload_words = cszW - 2;
332 a->bytes_mmaped += cszW * sizeof(Word);
333 if (0)
334 VG_(message)(Vg_DebugMsg, "newSuperblock, %d payload words",
335 sb->n_payload_words);
336 return sb;
337}
338
339
340/* Find the superblock containing the given chunk. */
341static
342Superblock* findSb ( Arena* a, UInt* ch )
343{
344 Superblock* sb;
345 for (sb = a->sblocks; sb; sb = sb->next)
346 if (&sb->payload_words[0] <= ch
347 && ch < &sb->payload_words[sb->n_payload_words])
348 return sb;
349 VG_(printf)("findSb: can't find pointer %p in arena `%s'\n",
350 ch, a->name );
njne427a662002-10-02 11:08:25 +0000351 VG_(core_panic)("findSb: vg_free() in wrong arena?");
sewardjde4a1d02002-03-22 01:27:54 +0000352 return NULL; /*NOTREACHED*/
353}
354
355
356/*------------------------------------------------------------*/
357/*--- Low-level functions for working with blocks. ---*/
358/*------------------------------------------------------------*/
359
360/* Add the not-in-use attribute to a bszW. */
361static __inline__
362Int mk_free_bszW ( Int bszW )
363{
364 vg_assert(bszW != 0);
365 return (bszW < 0) ? bszW : -bszW;
366}
367
368/* Add the in-use attribute to a bszW. */
369static __inline__
370Int mk_inuse_bszW ( Int bszW )
371{
372 vg_assert(bszW != 0);
373 return (bszW < 0) ? -bszW : bszW;
374}
375
376/* Remove the in-use/not-in-use attribute from a bszW, leaving just
377 the size. */
378static __inline__
379Int mk_plain_bszW ( Int bszW )
380{
381 vg_assert(bszW != 0);
382 return (bszW < 0) ? -bszW : bszW;
383}
384
385/* Does this bszW have the in-use attribute ? */
386static __inline__
387Bool is_inuse_bszW ( Int bszW )
388{
389 vg_assert(bszW != 0);
390 return (bszW < 0) ? False : True;
391}
392
393
394/* Given the addr of the first word of a block, return the addr of the
395 last word. */
396static __inline__
397WordL* first_to_last ( WordF* fw )
398{
399 return fw + mk_plain_bszW(fw[0]) - 1;
400}
401
402/* Given the addr of the last word of a block, return the addr of the
403 first word. */
404static __inline__
405WordF* last_to_first ( WordL* lw )
406{
407 return lw - mk_plain_bszW(lw[0]) + 1;
408}
409
410
411/* Given the addr of the first word of a block, return the addr of the
412 first word of its payload. */
413static __inline__
414Word* first_to_payload ( Arena* a, WordF* fw )
415{
416 return & fw[3 + a->rz_szW];
417}
418
njn8a6b6c02003-04-22 22:45:55 +0000419/* Given the addr of the first word of the payload of a block,
sewardjde4a1d02002-03-22 01:27:54 +0000420 return the addr of the first word of the block. */
421static __inline__
422Word* payload_to_first ( Arena* a, WordF* payload )
423{
424 return & payload[- 3 - a->rz_szW];
425}
426
427/* Set and get the lower size field of a block. */
428static __inline__
429void set_bszW_lo ( WordF* fw, Int bszW ) {
430 fw[0] = bszW;
431}
432static __inline__
433Int get_bszW_lo ( WordF* fw )
434{
435 return fw[0];
436}
437
438
439/* Set and get the next and previous link fields of a block. */
440static __inline__
441void set_prev_p ( WordF* fw, Word* prev_p ) {
442 fw[1] = (Word)prev_p;
443}
444static __inline__
445void set_next_p ( WordF* fw, Word* next_p ) {
446 fw[2] = (Word)next_p;
447}
448static __inline__
449Word* get_prev_p ( WordF* fw ) {
450 return (Word*)(fw[1]);
451}
452static __inline__
453Word* get_next_p ( WordF* fw ) {
454 return (Word*)(fw[2]);
455}
456
457
458/* Set and get the upper size field of a block. */
459static __inline__
460void set_bszW_hi ( WordF* fw, Int bszW ) {
461 WordL* lw = first_to_last(fw);
462 vg_assert(lw == fw + mk_plain_bszW(bszW) - 1);
463 lw[0] = bszW;
464}
465static __inline__
466Int get_bszW_hi ( WordF* fw ) {
467 WordL* lw = first_to_last(fw);
468 return lw[0];
469}
470
471/* Get the upper size field of a block, given a pointer to the last
472 word of it. */
473static __inline__
474Int get_bszW_hi_from_last_word ( WordL* lw ) {
475 WordF* fw = last_to_first(lw);
476 return get_bszW_lo(fw);
477}
478
479
480/* Read and write the lower and upper red-zone words of a block. */
481static __inline__
482void set_rz_lo_word ( Arena* a, WordF* fw, Int rz_wordno, Word w )
483{
484 fw[3 + rz_wordno] = w;
485}
486static __inline__
487void set_rz_hi_word ( Arena* a, WordF* fw, Int rz_wordno, Word w )
488{
489 WordL* lw = first_to_last(fw);
490 lw[-1-rz_wordno] = w;
491}
492static __inline__
493Word get_rz_lo_word ( Arena* a, WordF* fw, Int rz_wordno )
494{
495 return fw[3 + rz_wordno];
496}
497static __inline__
498Word get_rz_hi_word ( Arena* a, WordF* fw, Int rz_wordno )
499{
500 WordL* lw = first_to_last(fw);
501 return lw[-1-rz_wordno];
502}
503
504
505/* Return the lower, upper and total overhead in words for a block.
506 These are determined purely by which arena the block lives in. */
507static __inline__
508Int overhead_szW_lo ( Arena* a )
509{
510 return 3 + a->rz_szW;
511}
512static __inline__
513Int overhead_szW_hi ( Arena* a )
514{
515 return 1 + a->rz_szW;
516}
517static __inline__
518Int overhead_szW ( Arena* a )
519{
520 return overhead_szW_lo(a) + overhead_szW_hi(a);
521}
522
523
njn8a6b6c02003-04-22 22:45:55 +0000524/* Convert payload size in words to block size in words, and back. */
sewardjde4a1d02002-03-22 01:27:54 +0000525static __inline__
526Int pszW_to_bszW ( Arena* a, Int pszW )
527{
528 vg_assert(pszW >= 0);
529 return pszW + overhead_szW(a);
530}
531static __inline__
532Int bszW_to_pszW ( Arena* a, Int bszW )
533{
534 Int pszW = bszW - overhead_szW(a);
535 vg_assert(pszW >= 0);
536 return pszW;
537}
538
njn8a6b6c02003-04-22 22:45:55 +0000539Int VG_(arena_payload_szB) ( ArenaId aid, void* ptr )
540{
541 Arena* a = arenaId_to_ArenaP(aid);
542 Word* fw = payload_to_first(a, (WordF*)ptr);
543 Int pszW = bszW_to_pszW(a, get_bszW_lo(fw));
544 return VKI_BYTES_PER_WORD * pszW;
545}
546
547
sewardjde4a1d02002-03-22 01:27:54 +0000548/*------------------------------------------------------------*/
549/*--- Functions for working with freelists. ---*/
550/*------------------------------------------------------------*/
551
552/* Determination of which freelist a block lives on is based on the
553 payload size, not block size, in words. */
554
555/* Convert a payload size in words to a freelist number. */
556
557static
558Int pszW_to_listNo ( Int pszW )
559{
560 vg_assert(pszW >= 0);
561 if (pszW <= 3) return 0;
562 if (pszW <= 4) return 1;
563 if (pszW <= 5) return 2;
564 if (pszW <= 6) return 3;
565 if (pszW <= 7) return 4;
566 if (pszW <= 8) return 5;
567 if (pszW <= 9) return 6;
568 if (pszW <= 10) return 7;
569 if (pszW <= 11) return 8;
570 if (pszW <= 12) return 9;
571 if (pszW <= 16) return 10;
572 if (pszW <= 32) return 11;
573 if (pszW <= 64) return 12;
574 if (pszW <= 128) return 13;
575 if (pszW <= 256) return 14;
576 return 15;
577}
578
579
580/* What are the minimum and maximum payload sizes for a given list? */
581
582static
583Int listNo_to_pszW_min ( Int listNo )
584{
585 Int pszW = 0;
586 vg_assert(listNo >= 0 && listNo <= VG_N_MALLOC_LISTS);
587 while (pszW_to_listNo(pszW) < listNo) pszW++;
588 return pszW;
589}
590
591static
592Int listNo_to_pszW_max ( Int listNo )
593{
594 vg_assert(listNo >= 0 && listNo <= VG_N_MALLOC_LISTS);
595 if (listNo == VG_N_MALLOC_LISTS-1) {
596 return 999999999;
597 } else {
598 return listNo_to_pszW_min(listNo+1) - 1;
599 }
600}
601
602
603/* A nasty hack to try and reduce fragmentation. Try and replace
604 a->freelist[lno] with another block on the same list but with a
605 lower address, with the idea of attempting to recycle the same
606 blocks rather than cruise through the address space. */
607
608static
609void swizzle ( Arena* a, Int lno )
610{
611 UInt* p_best;
612 UInt* pp;
613 UInt* pn;
614 Int i;
615
616 p_best = a->freelist[lno];
617 if (p_best == NULL) return;
618
619 pn = pp = p_best;
620 for (i = 0; i < 20; i++) {
621 pn = get_next_p(pn);
622 pp = get_prev_p(pp);
623 if (pn < p_best) p_best = pn;
624 if (pp < p_best) p_best = pp;
625 }
626 if (p_best < a->freelist[lno]) {
627# ifdef DEBUG_MALLOC
628 VG_(printf)("retreat by %d\n",
629 ((Char*)(a->freelist[lno])) - ((Char*)p_best));
630# endif
631 a->freelist[lno] = p_best;
632 }
633}
634
635
636/*------------------------------------------------------------*/
637/*--- Creating and deleting blocks. ---*/
638/*------------------------------------------------------------*/
639
640/* Mark the words at b .. b+bszW-1 as not in use, and add them to the
641 relevant free list. */
642
643static
644void mkFreeBlock ( Arena* a, Word* b, Int bszW, Int b_lno )
645{
646 Int pszW = bszW_to_pszW(a, bszW);
647 vg_assert(pszW >= 0);
648 vg_assert(b_lno == pszW_to_listNo(pszW));
649 /* Set the size fields and indicate not-in-use. */
650 set_bszW_lo(b, mk_free_bszW(bszW));
651 set_bszW_hi(b, mk_free_bszW(bszW));
652
653 /* Add to the relevant list. */
654 if (a->freelist[b_lno] == NULL) {
655 set_prev_p(b, b);
656 set_next_p(b, b);
657 a->freelist[b_lno] = b;
658 } else {
659 Word* b_prev = get_prev_p(a->freelist[b_lno]);
660 Word* b_next = a->freelist[b_lno];
661 set_next_p(b_prev, b);
662 set_prev_p(b_next, b);
663 set_next_p(b, b_next);
664 set_prev_p(b, b_prev);
665 }
666# ifdef DEBUG_MALLOC
667 (void)blockSane(a,b);
668# endif
669}
670
671
672/* Mark the words at b .. b+bszW-1 as in use, and set up the block
673 appropriately. */
674static
675void mkInuseBlock ( Arena* a, UInt* b, UInt bszW )
676{
677 Int i;
678 set_bszW_lo(b, mk_inuse_bszW(bszW));
679 set_bszW_hi(b, mk_inuse_bszW(bszW));
680 set_prev_p(b, NULL);
681 set_next_p(b, NULL);
682 if (a->rz_check) {
683 for (i = 0; i < a->rz_szW; i++) {
684 set_rz_lo_word(a, b, i, (UInt)b ^ VG_REDZONE_LO_MASK);
685 set_rz_hi_word(a, b, i, (UInt)b ^ VG_REDZONE_HI_MASK);
686 }
687 }
688# ifdef DEBUG_MALLOC
689 (void)blockSane(a,b);
690# endif
691}
692
693
694/* Remove a block from a given list. Does no sanity checking. */
695static
696void unlinkBlock ( Arena* a, UInt* b, Int listno )
697{
698 vg_assert(listno >= 0 && listno < VG_N_MALLOC_LISTS);
699 if (get_prev_p(b) == b) {
700 /* Only one element in the list; treat it specially. */
701 vg_assert(get_next_p(b) == b);
702 a->freelist[listno] = NULL;
703 } else {
704 UInt* b_prev = get_prev_p(b);
705 UInt* b_next = get_next_p(b);
706 a->freelist[listno] = b_prev;
707 set_next_p(b_prev, b_next);
708 set_prev_p(b_next, b_prev);
709 swizzle ( a, listno );
710 }
711 set_prev_p(b, NULL);
712 set_next_p(b, NULL);
713}
714
715
716/* Split an existing free block into two pieces, and put the fragment
717 (the second one along in memory) onto the relevant free list.
718 req_bszW is the required size of the block which isn't the
719 fragment. */
720static
721void splitChunk ( Arena* a, UInt* b, Int b_listno, UInt req_bszW )
722{
sewardj05bcdcb2003-05-18 10:05:38 +0000723 UInt b_bszW;
724 Int frag_bszW;
725 b_bszW = (UInt)mk_plain_bszW(get_bszW_lo(b));
sewardjde4a1d02002-03-22 01:27:54 +0000726 vg_assert(req_bszW < b_bszW);
727 frag_bszW = b_bszW - req_bszW;
728 vg_assert(frag_bszW >= overhead_szW(a));
729 /*
730 printf( "split %d into %d and %d\n",
731 b_bszW,req_bszW,frag_bszW );
732 */
733 vg_assert(bszW_to_pszW(a, frag_bszW) > 0);
734 unlinkBlock(a, b, b_listno);
735 mkInuseBlock(a, b, req_bszW);
736 mkFreeBlock(a, &b[req_bszW], frag_bszW,
737 pszW_to_listNo(bszW_to_pszW(a, frag_bszW)));
738}
739
740
741/*------------------------------------------------------------*/
742/*--- Sanity-check/debugging machinery. ---*/
743/*------------------------------------------------------------*/
744
745/* Do some crude sanity checks on a chunk. */
746static
747Bool blockSane ( Arena* a, Word* b )
748{
749# define BLEAT(str) VG_(printf)("blockSane: fail -- %s\n",str)
750 Int i;
751 if (get_bszW_lo(b) != get_bszW_hi(b))
752 {BLEAT("sizes");return False;}
753 if (a->rz_check && is_inuse_bszW(get_bszW_lo(b))) {
754 for (i = 0; i < a->rz_szW; i++) {
755 if (get_rz_lo_word(a, b, i) != ((Word)b ^ VG_REDZONE_LO_MASK))
756 {BLEAT("redzone-lo");return False;}
757 if (get_rz_hi_word(a, b, i) != ((Word)b ^ VG_REDZONE_HI_MASK))
758 {BLEAT("redzone-hi");return False;}
759 }
760 }
761 return True;
762# undef BLEAT
763}
764
765
766/* Print superblocks (only for debugging). */
767static
768void ppSuperblocks ( Arena* a )
769{
770 Int i, ch_bszW, blockno;
771 UInt* ch;
772 Superblock* sb = a->sblocks;
773 blockno = 1;
774
775 while (sb) {
776 VG_(printf)( "\n" );
777 VG_(printf)( "superblock %d at %p, sb->n_pl_ws = %d, next = %p\n",
778 blockno++, sb, sb->n_payload_words, sb->next );
779 i = 0;
780 while (True) {
781 if (i >= sb->n_payload_words) break;
782 ch = &sb->payload_words[i];
783 ch_bszW = get_bszW_lo(ch);
784 VG_(printf)( " block at %d, bszW %d: ", i, mk_plain_bszW(ch_bszW) );
785 VG_(printf)( "%s, ", is_inuse_bszW(ch_bszW) ? "inuse" : "free" );
786 VG_(printf)( "%s\n", blockSane(a,ch) ? "ok" : "BAD" );
787 i += mk_plain_bszW(ch_bszW);
788 }
789 if (i > sb->n_payload_words)
790 VG_(printf)( " last block overshoots end of SB\n");
791 sb = sb->next;
792 }
793 VG_(printf)( "end of superblocks\n\n" );
794}
795
796
797/* Sanity check both the superblocks and the chains. */
njn25e49d8e72002-09-23 09:36:25 +0000798static void mallocSanityCheckArena ( ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000799{
800 Int i, superblockctr, b_bszW, b_pszW, blockctr_sb, blockctr_li;
801 Int blockctr_sb_free, listno, list_min_pszW, list_max_pszW;
802 Superblock* sb;
803 Bool thisFree, lastWasFree;
804 Word* b;
805 Word* b_prev;
806 UInt arena_bytes_on_loan;
807 Arena* a;
808
njne427a662002-10-02 11:08:25 +0000809# define BOMB VG_(core_panic)("mallocSanityCheckArena")
sewardjde4a1d02002-03-22 01:27:54 +0000810
811 a = arenaId_to_ArenaP(aid);
812
813 /* First, traverse all the superblocks, inspecting the chunks in
814 each. */
815 superblockctr = blockctr_sb = blockctr_sb_free = 0;
816 arena_bytes_on_loan = 0;
817 sb = a->sblocks;
818 while (sb) {
819 lastWasFree = False;
820 superblockctr++;
821 i = 0;
822 while (True) {
823 if (i >= sb->n_payload_words) break;
824 blockctr_sb++;
825 b = &sb->payload_words[i];
826 b_bszW = get_bszW_lo(b);
827 if (!blockSane(a, b)) {
njn25e49d8e72002-09-23 09:36:25 +0000828 VG_(printf)("mallocSanityCheckArena: sb %p, block %d (bszW %d): "
829 " BAD\n",
sewardjde4a1d02002-03-22 01:27:54 +0000830 sb, i, b_bszW );
831 BOMB;
832 }
833 thisFree = !is_inuse_bszW(b_bszW);
834 if (thisFree && lastWasFree) {
njn25e49d8e72002-09-23 09:36:25 +0000835 VG_(printf)("mallocSanityCheckArena: sb %p, block %d (bszW %d): "
836 "UNMERGED FREES\n",
sewardjde4a1d02002-03-22 01:27:54 +0000837 sb, i, b_bszW );
838 BOMB;
839 }
840 lastWasFree = thisFree;
841 if (thisFree) blockctr_sb_free++;
842 if (!thisFree)
843 arena_bytes_on_loan += sizeof(Word) * bszW_to_pszW(a, b_bszW);
844 i += mk_plain_bszW(b_bszW);
845 }
846 if (i > sb->n_payload_words) {
njn25e49d8e72002-09-23 09:36:25 +0000847 VG_(printf)( "mallocSanityCheckArena: sb %p: last block "
sewardjde4a1d02002-03-22 01:27:54 +0000848 "overshoots end\n", sb);
849 BOMB;
850 }
851 sb = sb->next;
852 }
853
854 if (arena_bytes_on_loan != a->bytes_on_loan) {
855 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +0000856 "mallocSanityCheckArena: a->bytes_on_loan %d, "
sewardjde4a1d02002-03-22 01:27:54 +0000857 "arena_bytes_on_loan %d: "
858 "MISMATCH\n", a->bytes_on_loan, arena_bytes_on_loan);
859 ppSuperblocks(a);
860 BOMB;
861 }
862
863 /* Second, traverse each list, checking that the back pointers make
864 sense, counting blocks encountered, and checking that each block
865 is an appropriate size for this list. */
866 blockctr_li = 0;
867 for (listno = 0; listno < VG_N_MALLOC_LISTS; listno++) {
868 list_min_pszW = listNo_to_pszW_min(listno);
869 list_max_pszW = listNo_to_pszW_max(listno);
870 b = a->freelist[listno];
871 if (b == NULL) continue;
872 while (True) {
873 b_prev = b;
874 b = get_next_p(b);
875 if (get_prev_p(b) != b_prev) {
njn25e49d8e72002-09-23 09:36:25 +0000876 VG_(printf)( "mallocSanityCheckArena: list %d at %p: "
sewardjde4a1d02002-03-22 01:27:54 +0000877 "BAD LINKAGE\n",
878 listno, b );
879 BOMB;
880 }
881 b_pszW = bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(b)));
882 if (b_pszW < list_min_pszW || b_pszW > list_max_pszW) {
883 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +0000884 "mallocSanityCheckArena: list %d at %p: "
sewardjde4a1d02002-03-22 01:27:54 +0000885 "WRONG CHAIN SIZE %d (%d, %d)\n",
886 listno, b, b_pszW, list_min_pszW, list_max_pszW );
887 BOMB;
888 }
889 blockctr_li++;
890 if (b == a->freelist[listno]) break;
891 }
892 }
893
894 if (blockctr_sb_free != blockctr_li) {
895 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +0000896 "mallocSanityCheckArena: BLOCK COUNT MISMATCH "
sewardjde4a1d02002-03-22 01:27:54 +0000897 "(via sbs %d, via lists %d)\n",
898 blockctr_sb_free, blockctr_li );
899 ppSuperblocks(a);
900 BOMB;
901 }
902
903 VG_(message)(Vg_DebugMsg,
njn3e884182003-04-15 13:03:23 +0000904 "mSC [%8s]: %2d sbs, %5d tot bs, %4d/%-4d free bs, "
sewardjde4a1d02002-03-22 01:27:54 +0000905 "%2d lists, %7d mmap, %7d loan",
906 a->name,
907 superblockctr,
908 blockctr_sb, blockctr_sb_free, blockctr_li,
909 VG_N_MALLOC_LISTS,
910 a->bytes_mmaped, a->bytes_on_loan);
911# undef BOMB
912}
913
914
915void VG_(mallocSanityCheckAll) ( void )
916{
917 Int i;
918 for (i = 0; i < VG_N_ARENAS; i++)
njn25e49d8e72002-09-23 09:36:25 +0000919 mallocSanityCheckArena ( i );
sewardjde4a1d02002-03-22 01:27:54 +0000920}
921
922
923/* Really, this isn't the right place for this. Nevertheless: find
924 out if an arena is empty -- currently has no bytes on loan. This
925 is useful for checking for memory leaks (of valgrind, not the
926 client.)
927*/
928Bool VG_(is_empty_arena) ( ArenaId aid )
929{
930 Arena* a;
931 Superblock* sb;
932 WordF* b;
933 Int b_bszW;
njn25e49d8e72002-09-23 09:36:25 +0000934
sewardjde4a1d02002-03-22 01:27:54 +0000935 ensure_mm_init();
936 a = arenaId_to_ArenaP(aid);
937 for (sb = a->sblocks; sb != NULL; sb = sb->next) {
938 /* If the superblock is empty, it should contain a single free
939 block, of the right size. */
940 b = &(sb->payload_words[0]);
941 b_bszW = get_bszW_lo(b);
942 if (is_inuse_bszW(b_bszW)) return False;
943 if (mk_plain_bszW(b_bszW) != sb->n_payload_words) return False;
944 /* So this block is not in use and is of the right size. Keep
945 going. */
946 }
947 return True;
948}
949
950
951/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000952/*--- Core-visible functions. ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000953/*------------------------------------------------------------*/
954
njn25e49d8e72002-09-23 09:36:25 +0000955void* VG_(arena_malloc) ( ArenaId aid, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +0000956{
957 Int req_pszW, req_bszW, frag_bszW, b_bszW, lno;
958 Superblock* new_sb;
959 Word* b;
960 Arena* a;
961
962 VGP_PUSHCC(VgpMalloc);
963
964 ensure_mm_init();
965 a = arenaId_to_ArenaP(aid);
966
967 vg_assert(req_pszB >= 0);
968 vg_assert(req_pszB < 0x7FFFFFF0);
969
970 req_pszW = (req_pszB + VKI_BYTES_PER_WORD - 1) / VKI_BYTES_PER_WORD;
971
972 /* Keep gcc -O happy: */
973 b = NULL;
974
975 /* Start searching at this list. */
976 lno = pszW_to_listNo(req_pszW);
977
978 /* This loop finds a list which has a block big enough, or sets
979 req_listno to N_LISTS if no such block exists. */
980 while (True) {
981 if (lno == VG_N_MALLOC_LISTS) break;
982 /* If this list is empty, try the next one. */
983 if (a->freelist[lno] == NULL) {
984 lno++;
985 continue;
986 }
987 /* Scan a->list[lno] to find a big-enough chunk. */
988 b = a->freelist[lno];
989 b_bszW = mk_plain_bszW(get_bszW_lo(b));
990 while (True) {
991 if (bszW_to_pszW(a, b_bszW) >= req_pszW) break;
992 b = get_next_p(b);
993 b_bszW = mk_plain_bszW(get_bszW_lo(b));
994 if (b == a->freelist[lno]) break;
995 }
996 if (bszW_to_pszW(a, b_bszW) >= req_pszW) break;
997 /* No luck? Try a larger list. */
998 lno++;
999 }
1000
1001 /* Either lno < VG_N_MALLOC_LISTS and b points to the selected
1002 block, or lno == VG_N_MALLOC_LISTS, and we have to allocate a
1003 new superblock. */
1004
1005 if (lno == VG_N_MALLOC_LISTS) {
1006 req_bszW = pszW_to_bszW(a, req_pszW);
1007 new_sb = newSuperblock(a, req_bszW);
1008 vg_assert(new_sb != NULL);
1009 new_sb->next = a->sblocks;
1010 a->sblocks = new_sb;
1011 b = &(new_sb->payload_words[0]);
1012 lno = pszW_to_listNo(bszW_to_pszW(a, new_sb->n_payload_words));
1013 mkFreeBlock ( a, b, new_sb->n_payload_words, lno);
1014 }
1015
1016 /* Ok, we can allocate from b, which lives in list req_listno. */
1017 vg_assert(b != NULL);
1018 vg_assert(lno >= 0 && lno < VG_N_MALLOC_LISTS);
1019 vg_assert(a->freelist[lno] != NULL);
1020 b_bszW = mk_plain_bszW(get_bszW_lo(b));
1021 req_bszW = pszW_to_bszW(a, req_pszW);
1022 /* req_bszW is the size of the block we are after. b_bszW is the
1023 size of what we've actually got. */
1024 vg_assert(b_bszW >= req_bszW);
1025
1026 /* Could we split this block and still get a useful fragment?
1027 Where "useful" means that the payload size of the frag is at
1028 least one word. */
1029 frag_bszW = b_bszW - req_bszW;
1030 if (frag_bszW > overhead_szW(a)) {
1031 splitChunk(a, b, lno, req_bszW);
1032 } else {
1033 /* No, mark as in use and use as-is. */
1034 unlinkBlock(a, b, lno);
1035 /*
1036 set_bszW_lo(b, mk_inuse_bszW(b_bszW));
1037 set_bszW_hi(b, mk_inuse_bszW(b_bszW));
1038 */
1039 mkInuseBlock(a, b, b_bszW);
1040 }
1041 vg_assert(req_bszW <= mk_plain_bszW(get_bszW_lo(b)));
1042
1043 a->bytes_on_loan
1044 += sizeof(Word)
1045 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(b)));
1046 if (a->bytes_on_loan > a->bytes_on_loan_max)
1047 a->bytes_on_loan_max = a->bytes_on_loan;
1048
1049# ifdef DEBUG_MALLOC
njn25e49d8e72002-09-23 09:36:25 +00001050 mallocSanityCheckArena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001051# endif
1052
njn25e49d8e72002-09-23 09:36:25 +00001053 VGP_POPCC(VgpMalloc);
sewardjde4a1d02002-03-22 01:27:54 +00001054 return first_to_payload(a, b);
1055}
1056
1057
njn25e49d8e72002-09-23 09:36:25 +00001058void VG_(arena_free) ( ArenaId aid, void* ptr )
sewardjde4a1d02002-03-22 01:27:54 +00001059{
1060 Superblock* sb;
1061 UInt* sb_payl_firstw;
1062 UInt* sb_payl_lastw;
1063 UInt* other;
1064 UInt* ch;
1065 Int ch_bszW, ch_pszW, other_bszW, ch_listno;
1066 Arena* a;
1067
1068 VGP_PUSHCC(VgpMalloc);
1069
1070 ensure_mm_init();
1071 a = arenaId_to_ArenaP(aid);
1072
njn25e49d8e72002-09-23 09:36:25 +00001073 if (ptr == NULL) {
1074 VGP_POPCC(VgpMalloc);
1075 return;
1076 }
1077
sewardjde4a1d02002-03-22 01:27:54 +00001078 ch = payload_to_first(a, ptr);
1079
1080# ifdef DEBUG_MALLOC
1081 vg_assert(blockSane(a,ch));
1082# endif
1083
1084 a->bytes_on_loan
1085 -= sizeof(Word)
1086 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(ch)));
1087
1088 sb = findSb( a, ch );
1089 sb_payl_firstw = &(sb->payload_words[0]);
1090 sb_payl_lastw = &(sb->payload_words[sb->n_payload_words-1]);
1091
1092 /* Put this chunk back on a list somewhere. */
1093 ch_bszW = get_bszW_lo(ch);
1094 ch_pszW = bszW_to_pszW(a, ch_bszW);
1095 ch_listno = pszW_to_listNo(ch_pszW);
1096 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1097
1098 /* See if this block can be merged with the following one. */
1099 other = ch + ch_bszW;
1100 /* overhead_szW(a) is the smallest possible bszW for this arena.
1101 So the nearest possible end to the block beginning at other is
1102 other+overhead_szW(a)-1. Hence the test below. */
1103 if (other+overhead_szW(a)-1 <= sb_payl_lastw) {
1104 other_bszW = get_bszW_lo(other);
1105 if (!is_inuse_bszW(other_bszW)) {
1106 /* VG_(printf)( "merge-successor\n"); */
1107 other_bszW = mk_plain_bszW(other_bszW);
1108# ifdef DEBUG_MALLOC
1109 vg_assert(blockSane(a, other));
1110# endif
1111 unlinkBlock( a, ch, ch_listno );
1112 unlinkBlock( a, other, pszW_to_listNo(bszW_to_pszW(a,other_bszW)) );
1113 ch_bszW += other_bszW;
1114 ch_listno = pszW_to_listNo(bszW_to_pszW(a, ch_bszW));
1115 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1116 }
1117 }
1118
1119 /* See if this block can be merged with its predecessor. */
1120 if (ch-overhead_szW(a) >= sb_payl_firstw) {
1121 other_bszW = get_bszW_hi_from_last_word( ch-1 );
1122 if (!is_inuse_bszW(other_bszW)) {
1123 /* VG_(printf)( "merge-predecessor\n"); */
1124 other = last_to_first( ch-1 );
1125 other_bszW = mk_plain_bszW(other_bszW);
1126 unlinkBlock( a, ch, ch_listno );
1127 unlinkBlock( a, other, pszW_to_listNo(bszW_to_pszW(a, other_bszW)) );
1128 ch = other;
1129 ch_bszW += other_bszW;
1130 ch_listno = pszW_to_listNo(bszW_to_pszW(a, ch_bszW));
1131 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1132 }
1133 }
1134
1135# ifdef DEBUG_MALLOC
njn25e49d8e72002-09-23 09:36:25 +00001136 mallocSanityCheckArena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001137# endif
1138
njn25e49d8e72002-09-23 09:36:25 +00001139 VGP_POPCC(VgpMalloc);
sewardjde4a1d02002-03-22 01:27:54 +00001140}
1141
1142
1143/*
1144 The idea for malloc_aligned() is to allocate a big block, base, and
1145 then split it into two parts: frag, which is returned to the the
1146 free pool, and align, which is the bit we're really after. Here's
1147 a picture. L and H denote the block lower and upper overheads, in
1148 words. The details are gruesome. Note it is slightly complicated
1149 because the initial request to generate base may return a bigger
1150 block than we asked for, so it is important to distinguish the base
1151 request size and the base actual size.
1152
1153 frag_b align_b
1154 | |
1155 | frag_p | align_p
1156 | | | |
1157 v v v v
1158
1159 +---+ +---+---+ +---+
1160 | L |----------------| H | L |---------------| H |
1161 +---+ +---+---+ +---+
1162
1163 ^ ^ ^
1164 | | :
1165 | base_p this addr must be aligned
1166 |
1167 base_b
1168
1169 . . . . . . .
1170 <------ frag_bszW -------> . . .
1171 . <------------- base_pszW_act -----------> .
1172 . . . . . . .
1173
1174*/
njn25e49d8e72002-09-23 09:36:25 +00001175void* VG_(arena_malloc_aligned) ( ArenaId aid, Int req_alignB, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +00001176{
1177 Int req_alignW, req_pszW, base_pszW_req, base_pszW_act, frag_bszW;
1178 Word *base_b, *base_p, *align_p;
1179 UInt saved_bytes_on_loan;
1180 Arena* a;
1181
njn25e49d8e72002-09-23 09:36:25 +00001182 VGP_PUSHCC(VgpMalloc);
1183
sewardjde4a1d02002-03-22 01:27:54 +00001184 ensure_mm_init();
1185 a = arenaId_to_ArenaP(aid);
1186
1187 vg_assert(req_pszB >= 0);
1188 vg_assert(req_pszB < 0x7FFFFFF0);
1189
1190 /* Check that the requested alignment seems reasonable; that is, is
sewardjb5045ef2002-06-04 16:48:29 +00001191 a power of 2. */
sewardjde4a1d02002-03-22 01:27:54 +00001192 switch (req_alignB) {
sewardjc76be292002-04-24 20:32:50 +00001193 case 4:
sewardjde4a1d02002-03-22 01:27:54 +00001194 case 8: case 16: case 32: case 64: case 128: case 256:
1195 case 512: case 1024: case 2048: case 4096: case 8192:
1196 case 16384: case 32768: case 65536: case 131072:
sewardjb5045ef2002-06-04 16:48:29 +00001197 case 262144:
sewardjde4a1d02002-03-22 01:27:54 +00001198 case 1048576:
1199 /* can't be bothered to calculate larger ones */
1200 break;
1201 default:
1202 VG_(printf)("vg_malloc_aligned(%p, %d, %d)\nbad alignment request",
njn25e49d8e72002-09-23 09:36:25 +00001203 a, req_alignB, req_pszB );
njne427a662002-10-02 11:08:25 +00001204 VG_(core_panic)("vg_malloc_aligned");
sewardjde4a1d02002-03-22 01:27:54 +00001205 /*NOTREACHED*/
1206 }
1207
1208 /* Required alignment, in words. Since it's constrained to be a
1209 power of 2 >= word size, no need to align the alignment. Still,
1210 we check. */
1211 req_alignW = req_alignB / VKI_BYTES_PER_WORD;
1212 vg_assert(req_alignB == req_alignW * VKI_BYTES_PER_WORD);
1213
1214 /* Required payload size for the aligned chunk. */
1215 req_pszW = (req_pszB + VKI_BYTES_PER_WORD - 1) / VKI_BYTES_PER_WORD;
1216
1217 /* Payload size to request for the big block that we will split
1218 up. */
1219 base_pszW_req = req_pszW + overhead_szW(a) + req_alignW;
1220
1221 /* Payload ptr for the block we are going to split. Note this
1222 changes a->bytes_on_loan; we save and restore it ourselves. */
1223 saved_bytes_on_loan = a->bytes_on_loan;
njn25e49d8e72002-09-23 09:36:25 +00001224 base_p = VG_(arena_malloc) ( aid, base_pszW_req * VKI_BYTES_PER_WORD );
sewardjde4a1d02002-03-22 01:27:54 +00001225 a->bytes_on_loan = saved_bytes_on_loan;
1226
1227 /* Block ptr for the block we are going to split. */
1228 base_b = payload_to_first ( a, base_p );
1229
1230 /* Pointer to the payload of the aligned block we are going to
1231 return. This has to be suitably aligned. */
1232 align_p = align_upwards ( base_b + 2 * overhead_szW_lo(a)
1233 + overhead_szW_hi(a),
1234 req_alignB );
1235
1236 /* The block size of the fragment we will create. This must be big
1237 enough to actually create a fragment. */
1238 frag_bszW = align_p - overhead_szW_lo(a) - base_b;
1239 vg_assert(frag_bszW >= overhead_szW(a));
1240
1241 /* The actual payload size of the block we are going to split. */
1242 base_pszW_act = bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(base_b)));
1243
1244 /* Create the fragment block, and put it back on the relevant free
1245 list. */
1246 mkFreeBlock ( a, base_b, frag_bszW,
1247 pszW_to_listNo(bszW_to_pszW(a, frag_bszW)) );
1248
1249 /* Create the aligned block. */
1250 mkInuseBlock ( a,
1251 align_p - overhead_szW_lo(a),
1252 base_p + base_pszW_act
1253 + overhead_szW_hi(a)
1254 - (align_p - overhead_szW_lo(a)) );
1255
1256 /* Final sanity checks. */
1257 vg_assert(( (UInt)align_p % req_alignB) == 0);
1258
1259 vg_assert(is_inuse_bszW(get_bszW_lo(payload_to_first(a, align_p))));
1260
1261 vg_assert(req_pszW
1262 <=
1263 bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(
1264 payload_to_first(a, align_p))))
1265 );
1266
1267 a->bytes_on_loan
1268 += sizeof(Word)
1269 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(
1270 payload_to_first(a, align_p))));
1271 if (a->bytes_on_loan > a->bytes_on_loan_max)
1272 a->bytes_on_loan_max = a->bytes_on_loan;
1273
1274# ifdef DEBUG_MALLOC
njn25e49d8e72002-09-23 09:36:25 +00001275 mallocSanityCheckArena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001276# endif
1277
njn25e49d8e72002-09-23 09:36:25 +00001278 VGP_POPCC(VgpMalloc);
1279
sewardjde4a1d02002-03-22 01:27:54 +00001280 return align_p;
1281}
1282
1283
1284/*------------------------------------------------------------*/
1285/*--- Services layered on top of malloc/free. ---*/
1286/*------------------------------------------------------------*/
1287
njn3e884182003-04-15 13:03:23 +00001288void* VG_(arena_calloc) ( ArenaId aid, Int alignB, Int nmemb, Int nbytes )
sewardjde4a1d02002-03-22 01:27:54 +00001289{
1290 Int i, size;
1291 UChar* p;
njn25e49d8e72002-09-23 09:36:25 +00001292
1293 VGP_PUSHCC(VgpMalloc);
1294
sewardjde4a1d02002-03-22 01:27:54 +00001295 size = nmemb * nbytes;
sewardjd0b9ac32002-05-01 00:10:28 +00001296 vg_assert(size >= 0);
njn3e884182003-04-15 13:03:23 +00001297
1298 if (alignB == 4)
1299 p = VG_(arena_malloc) ( aid, size );
1300 else
1301 p = VG_(arena_malloc_aligned) ( aid, alignB, size );
1302
sewardjde4a1d02002-03-22 01:27:54 +00001303 for (i = 0; i < size; i++) p[i] = 0;
njn25e49d8e72002-09-23 09:36:25 +00001304
1305 VGP_POPCC(VgpMalloc);
1306
sewardjde4a1d02002-03-22 01:27:54 +00001307 return p;
1308}
1309
1310
njn25e49d8e72002-09-23 09:36:25 +00001311void* VG_(arena_realloc) ( ArenaId aid, void* ptr,
1312 Int req_alignB, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +00001313{
1314 Arena* a;
1315 Int old_bszW, old_pszW, old_pszB, i;
1316 UChar *p_old, *p_new;
1317 UInt* ch;
1318
njn25e49d8e72002-09-23 09:36:25 +00001319 VGP_PUSHCC(VgpMalloc);
1320
sewardjde4a1d02002-03-22 01:27:54 +00001321 ensure_mm_init();
1322 a = arenaId_to_ArenaP(aid);
1323
1324 vg_assert(req_pszB >= 0);
1325 vg_assert(req_pszB < 0x7FFFFFF0);
1326
1327 ch = payload_to_first(a, ptr);
1328 vg_assert(blockSane(a, ch));
1329
1330 old_bszW = get_bszW_lo(ch);
1331 vg_assert(is_inuse_bszW(old_bszW));
1332 old_bszW = mk_plain_bszW(old_bszW);
1333 old_pszW = bszW_to_pszW(a, old_bszW);
1334 old_pszB = old_pszW * VKI_BYTES_PER_WORD;
1335
njn25e49d8e72002-09-23 09:36:25 +00001336 if (req_pszB <= old_pszB) {
1337 VGP_POPCC(VgpMalloc);
1338 return ptr;
1339 }
sewardjde4a1d02002-03-22 01:27:54 +00001340
njn25e49d8e72002-09-23 09:36:25 +00001341 if (req_alignB == 4)
1342 p_new = VG_(arena_malloc) ( aid, req_pszB );
1343 else
1344 p_new = VG_(arena_malloc_aligned) ( aid, req_alignB, req_pszB );
1345
sewardjde4a1d02002-03-22 01:27:54 +00001346 p_old = (UChar*)ptr;
1347 for (i = 0; i < old_pszB; i++)
1348 p_new[i] = p_old[i];
1349
njn25e49d8e72002-09-23 09:36:25 +00001350 VG_(arena_free)(aid, p_old);
1351
1352 VGP_POPCC(VgpMalloc);
sewardjde4a1d02002-03-22 01:27:54 +00001353 return p_new;
1354}
1355
1356
1357/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001358/*--- Skin-visible functions. ---*/
1359/*------------------------------------------------------------*/
1360
1361/* All just wrappers to avoid exposing arenas to skins */
1362
1363void* VG_(malloc) ( Int nbytes )
1364{
1365 return VG_(arena_malloc) ( VG_AR_SKIN, nbytes );
1366}
1367
1368void VG_(free) ( void* ptr )
1369{
1370 VG_(arena_free) ( VG_AR_SKIN, ptr );
1371}
1372
1373void* VG_(calloc) ( Int nmemb, Int nbytes )
1374{
njn3e884182003-04-15 13:03:23 +00001375 return VG_(arena_calloc) ( VG_AR_SKIN, /*alignment*/4, nmemb, nbytes );
njn25e49d8e72002-09-23 09:36:25 +00001376}
1377
1378void* VG_(realloc) ( void* ptr, Int size )
1379{
1380 return VG_(arena_realloc) ( VG_AR_SKIN, ptr, /*alignment*/4, size );
1381}
1382
1383void* VG_(malloc_aligned) ( Int req_alignB, Int req_pszB )
1384{
1385 return VG_(arena_malloc_aligned) ( VG_AR_SKIN, req_alignB, req_pszB );
1386}
1387
1388
njn3e884182003-04-15 13:03:23 +00001389void* VG_(cli_malloc) ( UInt align, Int nbytes )
1390{
1391 vg_assert(align >= 4);
1392 if (4 == align)
1393 return VG_(arena_malloc) ( VG_AR_CLIENT, nbytes );
1394 else
sewardjf1accbc2003-07-12 01:26:52 +00001395 return VG_(arena_malloc_aligned) ( VG_AR_CLIENT, align, nbytes );
njn3e884182003-04-15 13:03:23 +00001396}
1397
1398void VG_(cli_free) ( void* p )
1399{
1400 VG_(arena_free) ( VG_AR_CLIENT, p );
1401}
1402
1403
1404Bool VG_(addr_is_in_block)( Addr a, Addr start, UInt size )
1405{
1406 return (start - VG_(vg_malloc_redzone_szB) <= a
1407 && a < start + size + VG_(vg_malloc_redzone_szB));
1408}
1409
1410
njn25e49d8e72002-09-23 09:36:25 +00001411/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00001412/*--- The original test driver machinery. ---*/
1413/*------------------------------------------------------------*/
1414
1415#if 0
1416
1417#if 1
1418#define N_TEST_TRANSACTIONS 100000000
1419#define N_TEST_ARR 200000
1420#define M_TEST_MALLOC 1000
1421#else
1422#define N_TEST_TRANSACTIONS 500000
1423#define N_TEST_ARR 30000
1424#define M_TEST_MALLOC 500
1425#endif
1426
1427
1428void* test_arr[N_TEST_ARR];
1429
1430int main ( int argc, char** argv )
1431{
1432 Int i, j, k, nbytes, qq;
1433 unsigned char* chp;
njn25e49d8e72002-09-23 09:36:25 +00001434 Arena* a = &arena[VG_AR_CORE];
sewardjde4a1d02002-03-22 01:27:54 +00001435 srandom(1);
1436 for (i = 0; i < N_TEST_ARR; i++)
1437 test_arr[i] = NULL;
1438
1439 for (i = 0; i < N_TEST_TRANSACTIONS; i++) {
1440 if (i % 50000 == 0) mallocSanityCheck(a);
1441 j = random() % N_TEST_ARR;
1442 if (test_arr[j]) {
1443 vg_free(a, test_arr[j]);
1444 test_arr[j] = NULL;
1445 } else {
1446 nbytes = 1 + random() % M_TEST_MALLOC;
1447 qq = random()%64;
1448 if (qq == 32)
1449 nbytes *= 17;
1450 else if (qq == 33)
1451 nbytes = 0;
1452 test_arr[j]
1453 = (i % 17) == 0
1454 ? vg_memalign(a, nbytes, 1<< (3+(random()%10)))
1455 : vg_malloc( a, nbytes );
1456 chp = test_arr[j];
1457 for (k = 0; k < nbytes; k++)
1458 chp[k] = (unsigned char)(k + 99);
1459 }
1460 }
1461
1462
1463 for (i = 0; i < N_TEST_ARR; i++) {
1464 if (test_arr[i]) {
1465 vg_free(a, test_arr[i]);
1466 test_arr[i] = NULL;
1467 }
1468 }
1469 mallocSanityCheck(a);
1470
1471 fprintf(stderr, "ALL DONE\n");
1472
1473 show_arena_stats(a);
1474 fprintf(stderr, "%d max useful, %d bytes mmap'd (%4.1f%%), %d useful\n",
1475 a->bytes_on_loan_max,
1476 a->bytes_mmaped,
1477 100.0 * (double)a->bytes_on_loan_max / (double)a->bytes_mmaped,
1478 a->bytes_on_loan );
1479
1480 return 0;
1481}
1482#endif /* 0 */
1483
1484
1485/*--------------------------------------------------------------------*/
1486/*--- end vg_malloc2.c ---*/
1487/*--------------------------------------------------------------------*/