blob: aadc4061248935740ef12a78db838f8aa4cb0b5a [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
nethercotebb1c9912004-01-04 16:43:23 +000011 Copyright (C) 2000-2004 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.
mueller273d1d72004-03-13 02:49:49 +000049 default: 0, i.e. use default of the machine (== 8) */
fitzhardinge26f33082004-03-13 02:38:33 +000050Int VG_(clo_alignment) = 8;
fitzhardinge98abfc72003-12-16 02:05:15 +000051
52
53Bool VG_(replacement_malloc_process_cmd_line_option)(Char* arg)
54{
jsewardb1a26ae2004-03-14 03:06:37 +000055 if (VG_CLO_STREQN(12, arg, "--alignment=")) {
fitzhardinge98abfc72003-12-16 02:05:15 +000056 VG_(clo_alignment) = (Int)VG_(atoll)(&arg[12]);
57
jsewardb1a26ae2004-03-14 03:06:37 +000058 if (VG_(clo_alignment) < 8
fitzhardinge98abfc72003-12-16 02:05:15 +000059 || 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. "
jsewardb1a26ae2004-03-14 03:06:37 +000064 "Should be a power of 2, >= 8, <= 4096.");
fitzhardinge98abfc72003-12-16 02:05:15 +000065 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"
mueller273d1d72004-03-13 02:49:49 +000089" --alignment=<number> set minimum alignment of allocations [8]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +000090 );
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)
sewardjde4a1d02002-03-22 01:27:54 +0000149 red zone words (depends on .rz_szW field of Arena)
150 (payload words)
151 red zone words (depends on .rz_szW field of Arena)
jsewardb1a26ae2004-03-14 03:06:37 +0000152 freelist next ptr (1 word)
153 this block total sizeW (1 word)
sewardjde4a1d02002-03-22 01:27:54 +0000154
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.
jsewardb1a26ae2004-03-14 03:06:37 +0000163
164 8-byte payload alignment is ensured by requiring the number
165 of words in the red zones and the number of payload words
166 to both be even (% 2 == 0).
sewardjde4a1d02002-03-22 01:27:54 +0000167*/
168typedef
169 struct {
170 Int bszW_lo;
171 Word* prev;
172 Word* next;
173 Word redzone[0];
174 }
175 BlockHeader;
176
177
178/*------------------------------------------------------------*/
179/*--- Forwardses ... and misc ... ---*/
180/*------------------------------------------------------------*/
181
182static Bool blockSane ( Arena* a, Word* b );
183
184/* Align ptr p upwards to an align-sized boundary. */
185static
186void* align_upwards ( void* p, Int align )
187{
188 Addr a = (Addr)p;
189 if ((a % align) == 0) return (void*)a;
190 return (void*)(a - (a % align) + align);
191}
192
193
194/*------------------------------------------------------------*/
195/*--- Arena management stuff ---*/
196/*------------------------------------------------------------*/
197
198/* The arena structures themselves. */
199static Arena vg_arena[VG_N_ARENAS];
200
201/* Functions external to this module identify arenas using ArenaIds,
202 not Arena*s. This fn converts the former to the latter. */
203static Arena* arenaId_to_ArenaP ( ArenaId arena )
204{
205 vg_assert(arena >= 0 && arena < VG_N_ARENAS);
206 return & vg_arena[arena];
207}
208
209
210/* Initialise an arena. */
211static
212void arena_init ( Arena* a, Char* name,
fitzhardinge98abfc72003-12-16 02:05:15 +0000213 Int rz_szW, Bool rz_check, Int min_sblockW, Bool client )
sewardjde4a1d02002-03-22 01:27:54 +0000214{
215 Int i;
jsewardb1a26ae2004-03-14 03:06:37 +0000216 vg_assert(rz_szW >= 0);
217 vg_assert(rz_szW % 2 == 0);
sewardjde4a1d02002-03-22 01:27:54 +0000218 vg_assert((min_sblockW % VKI_WORDS_PER_PAGE) == 0);
219 a->name = name;
fitzhardinge98abfc72003-12-16 02:05:15 +0000220 a->clientmem = client;
sewardjde4a1d02002-03-22 01:27:54 +0000221 a->rz_szW = rz_szW;
222 a->rz_check = rz_check;
223 a->min_sblockW = min_sblockW;
224 for (i = 0; i < VG_N_MALLOC_LISTS; i++) a->freelist[i] = NULL;
225 a->sblocks = NULL;
226 a->bytes_on_loan = 0;
227 a->bytes_mmaped = 0;
228 a->bytes_on_loan_max = 0;
229}
230
231
232/* Print vital stats for an arena. */
233void VG_(show_all_arena_stats) ( void )
234{
235 Int i;
236 for (i = 0; i < VG_N_ARENAS; i++) {
237 VG_(message)(Vg_DebugMsg,
238 "Arena `%s': %7d max useful, %7d mmap'd, %7d current useful",
239 vg_arena[i].name,
240 vg_arena[i].bytes_on_loan_max,
241 vg_arena[i].bytes_mmaped,
242 vg_arena[i].bytes_on_loan
243 );
244 }
245}
246
247
248/* It is important that this library is self-initialising, because it
249 may get called very early on -- as a result of C++ static
250 constructor initialisations -- before Valgrind itself is
njn25e49d8e72002-09-23 09:36:25 +0000251 initialised. Hence VG_(arena_malloc)() and VG_(arena_free)() below always
252 call ensure_mm_init() to ensure things are correctly initialised. */
sewardjde4a1d02002-03-22 01:27:54 +0000253
254static
255void ensure_mm_init ( void )
256{
jsewardb1a26ae2004-03-14 03:06:37 +0000257 Int client_rz_szW;
sewardjde4a1d02002-03-22 01:27:54 +0000258 static Bool init_done = False;
jsewardb1a26ae2004-03-14 03:06:37 +0000259
sewardjde4a1d02002-03-22 01:27:54 +0000260 if (init_done) return;
261
262 /* Use a checked red zone size of 1 word for our internal stuff,
263 and an unchecked zone of arbitrary size for the client. Of
nethercote7cc9c232004-01-21 15:08:04 +0000264 course the client's red zone can be checked by the tool, eg.
njn3e884182003-04-15 13:03:23 +0000265 by using addressibility maps, but not by the mechanism implemented
266 here, which merely checks at the time of freeing that the red
267 zone words are unchanged. */
sewardjde4a1d02002-03-22 01:27:54 +0000268
jsewardb1a26ae2004-03-14 03:06:37 +0000269 arena_init ( &vg_arena[VG_AR_CORE], "core", 2, True, 262144, False );
sewardjde4a1d02002-03-22 01:27:54 +0000270
jsewardb1a26ae2004-03-14 03:06:37 +0000271 arena_init ( &vg_arena[VG_AR_TOOL], "tool", 2, True, 262144, False );
sewardjde4a1d02002-03-22 01:27:54 +0000272
jsewardb1a26ae2004-03-14 03:06:37 +0000273 arena_init ( &vg_arena[VG_AR_SYMTAB], "symtab", 2, True, 262144, False );
njn25e49d8e72002-09-23 09:36:25 +0000274
jsewardb1a26ae2004-03-14 03:06:37 +0000275 arena_init ( &vg_arena[VG_AR_JITTER], "JITter", 2, True, 8192, False );
njn25e49d8e72002-09-23 09:36:25 +0000276
njn3e884182003-04-15 13:03:23 +0000277 /* No particular reason for this figure, it's just smallish */
278 sk_assert(VG_(vg_malloc_redzone_szB) < 128);
jsewardb1a26ae2004-03-14 03:06:37 +0000279 sk_assert(VG_(vg_malloc_redzone_szB) >= 0);
280 client_rz_szW = VG_(vg_malloc_redzone_szB)/4;
281 if (client_rz_szW % 2 == 1) client_rz_szW++;
282
njn3e884182003-04-15 13:03:23 +0000283 arena_init ( &vg_arena[VG_AR_CLIENT], "client",
jsewardb1a26ae2004-03-14 03:06:37 +0000284 client_rz_szW, False, 262144, True );
sewardjde4a1d02002-03-22 01:27:54 +0000285
njn3e884182003-04-15 13:03:23 +0000286 arena_init ( &vg_arena[VG_AR_DEMANGLE], "demangle", 4 /*paranoid*/,
fitzhardinge98abfc72003-12-16 02:05:15 +0000287 True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000288
jsewardb1a26ae2004-03-14 03:06:37 +0000289 arena_init ( &vg_arena[VG_AR_EXECTXT], "exectxt", 2, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000290
jsewardb1a26ae2004-03-14 03:06:37 +0000291 arena_init ( &vg_arena[VG_AR_ERRORS], "errors", 2, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000292
fitzhardinge98abfc72003-12-16 02:05:15 +0000293 arena_init ( &vg_arena[VG_AR_TRANSIENT], "transien", 2, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000294
295 init_done = True;
296# ifdef DEBUG_MALLOC
297 VG_(mallocSanityCheckAll)();
298# endif
299}
300
301
sewardjecf8e102003-07-12 12:11:39 +0000302/* Returns True if aa is inside any segment mmap'd /dev/zero
303 by our low-level memory manager. */
304Bool VG_(is_inside_segment_mmapd_by_low_level_MM)( Addr aa )
305{
306 ArenaId ar;
307 Superblock* sb;
308
309 ensure_mm_init();
310
311 for (ar = 0; ar < VG_N_ARENAS; ar++) {
312 for (sb = vg_arena[ar].sblocks; sb; sb = sb->next) {
313 Addr sb_first_word = (Addr)sb;
314 Addr sb_last_word
315 = (Addr)&(sb->payload_words[sb->n_payload_words-1]);
316 if (aa >= sb_first_word && aa <= sb_last_word)
317 return True;
318 }
319 }
320 return False;
321}
322
323
sewardjde4a1d02002-03-22 01:27:54 +0000324/*------------------------------------------------------------*/
sewardjecf8e102003-07-12 12:11:39 +0000325/*--- Superblock management stuff ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000326/*------------------------------------------------------------*/
327
328static
329Superblock* newSuperblock ( Arena* a, Int cszW )
330{
331 Superblock* sb;
332 cszW += 2; /* Take into account sb->next and sb->n_words fields */
333 if (cszW < a->min_sblockW) cszW = a->min_sblockW;
334 while ((cszW % VKI_WORDS_PER_PAGE) > 0) cszW++;
fitzhardinge98abfc72003-12-16 02:05:15 +0000335
336 if (a->clientmem) {
jsewardb1a26ae2004-03-14 03:06:37 +0000337 sb = (Superblock *)
338 VG_(client_alloc)(0, cszW * sizeof(Word),
339 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 0);
fitzhardinge98abfc72003-12-16 02:05:15 +0000340 } else
341 sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word),
342 "newSuperblock" );
sewardjde4a1d02002-03-22 01:27:54 +0000343 sb->n_payload_words = cszW - 2;
344 a->bytes_mmaped += cszW * sizeof(Word);
345 if (0)
346 VG_(message)(Vg_DebugMsg, "newSuperblock, %d payload words",
347 sb->n_payload_words);
348 return sb;
349}
350
351
352/* Find the superblock containing the given chunk. */
353static
354Superblock* findSb ( Arena* a, UInt* ch )
355{
356 Superblock* sb;
357 for (sb = a->sblocks; sb; sb = sb->next)
358 if (&sb->payload_words[0] <= ch
359 && ch < &sb->payload_words[sb->n_payload_words])
360 return sb;
361 VG_(printf)("findSb: can't find pointer %p in arena `%s'\n",
362 ch, a->name );
njne427a662002-10-02 11:08:25 +0000363 VG_(core_panic)("findSb: vg_free() in wrong arena?");
sewardjde4a1d02002-03-22 01:27:54 +0000364 return NULL; /*NOTREACHED*/
365}
366
367
368/*------------------------------------------------------------*/
369/*--- Low-level functions for working with blocks. ---*/
370/*------------------------------------------------------------*/
371
372/* Add the not-in-use attribute to a bszW. */
373static __inline__
374Int mk_free_bszW ( Int bszW )
375{
376 vg_assert(bszW != 0);
377 return (bszW < 0) ? bszW : -bszW;
378}
379
380/* Add the in-use attribute to a bszW. */
381static __inline__
382Int mk_inuse_bszW ( Int bszW )
383{
384 vg_assert(bszW != 0);
385 return (bszW < 0) ? -bszW : bszW;
386}
387
388/* Remove the in-use/not-in-use attribute from a bszW, leaving just
389 the size. */
390static __inline__
391Int mk_plain_bszW ( Int bszW )
392{
393 vg_assert(bszW != 0);
394 return (bszW < 0) ? -bszW : bszW;
395}
396
397/* Does this bszW have the in-use attribute ? */
398static __inline__
399Bool is_inuse_bszW ( Int bszW )
400{
401 vg_assert(bszW != 0);
402 return (bszW < 0) ? False : True;
403}
404
405
406/* Given the addr of the first word of a block, return the addr of the
407 last word. */
408static __inline__
409WordL* first_to_last ( WordF* fw )
410{
411 return fw + mk_plain_bszW(fw[0]) - 1;
412}
413
414/* Given the addr of the last word of a block, return the addr of the
415 first word. */
416static __inline__
417WordF* last_to_first ( WordL* lw )
418{
419 return lw - mk_plain_bszW(lw[0]) + 1;
420}
421
422
423/* Given the addr of the first word of a block, return the addr of the
424 first word of its payload. */
425static __inline__
426Word* first_to_payload ( Arena* a, WordF* fw )
427{
jsewardb1a26ae2004-03-14 03:06:37 +0000428 return & fw[2 + a->rz_szW];
sewardjde4a1d02002-03-22 01:27:54 +0000429}
430
njn8a6b6c02003-04-22 22:45:55 +0000431/* Given the addr of the first word of the payload of a block,
sewardjde4a1d02002-03-22 01:27:54 +0000432 return the addr of the first word of the block. */
433static __inline__
434Word* payload_to_first ( Arena* a, WordF* payload )
435{
jsewardb1a26ae2004-03-14 03:06:37 +0000436 return & payload[- (2 + a->rz_szW)];
sewardjde4a1d02002-03-22 01:27:54 +0000437}
438
439/* Set and get the lower size field of a block. */
440static __inline__
441void set_bszW_lo ( WordF* fw, Int bszW ) {
442 fw[0] = bszW;
443}
444static __inline__
445Int get_bszW_lo ( WordF* fw )
446{
447 return fw[0];
448}
449
450
451/* Set and get the next and previous link fields of a block. */
452static __inline__
453void set_prev_p ( WordF* fw, Word* prev_p ) {
454 fw[1] = (Word)prev_p;
455}
456static __inline__
jsewardb1a26ae2004-03-14 03:06:37 +0000457void set_next_p ( WordF* fw, Word* next_p ) {
458 WordL* lw = first_to_last(fw);
459 lw[-1] = (Word)next_p;
sewardjde4a1d02002-03-22 01:27:54 +0000460}
461static __inline__
462Word* get_prev_p ( WordF* fw ) {
463 return (Word*)(fw[1]);
464}
465static __inline__
466Word* get_next_p ( WordF* fw ) {
jsewardb1a26ae2004-03-14 03:06:37 +0000467 WordL* lw = first_to_last(fw);
468 return (Word*)(lw[-1]);
sewardjde4a1d02002-03-22 01:27:54 +0000469}
470
471
472/* Set and get the upper size field of a block. */
473static __inline__
474void set_bszW_hi ( WordF* fw, Int bszW ) {
475 WordL* lw = first_to_last(fw);
476 vg_assert(lw == fw + mk_plain_bszW(bszW) - 1);
477 lw[0] = bszW;
478}
479static __inline__
480Int get_bszW_hi ( WordF* fw ) {
481 WordL* lw = first_to_last(fw);
482 return lw[0];
483}
484
485/* Get the upper size field of a block, given a pointer to the last
486 word of it. */
487static __inline__
488Int get_bszW_hi_from_last_word ( WordL* lw ) {
489 WordF* fw = last_to_first(lw);
490 return get_bszW_lo(fw);
491}
492
493
494/* Read and write the lower and upper red-zone words of a block. */
495static __inline__
496void set_rz_lo_word ( Arena* a, WordF* fw, Int rz_wordno, Word w )
497{
jsewardb1a26ae2004-03-14 03:06:37 +0000498 fw[2 + rz_wordno] = w;
sewardjde4a1d02002-03-22 01:27:54 +0000499}
500static __inline__
501void set_rz_hi_word ( Arena* a, WordF* fw, Int rz_wordno, Word w )
502{
503 WordL* lw = first_to_last(fw);
jsewardb1a26ae2004-03-14 03:06:37 +0000504 lw[-2-rz_wordno] = w;
sewardjde4a1d02002-03-22 01:27:54 +0000505}
506static __inline__
507Word get_rz_lo_word ( Arena* a, WordF* fw, Int rz_wordno )
508{
jsewardb1a26ae2004-03-14 03:06:37 +0000509 return fw[2 + rz_wordno];
sewardjde4a1d02002-03-22 01:27:54 +0000510}
511static __inline__
512Word get_rz_hi_word ( Arena* a, WordF* fw, Int rz_wordno )
513{
514 WordL* lw = first_to_last(fw);
jsewardb1a26ae2004-03-14 03:06:37 +0000515 return lw[-2-rz_wordno];
sewardjde4a1d02002-03-22 01:27:54 +0000516}
517
518
519/* Return the lower, upper and total overhead in words for a block.
520 These are determined purely by which arena the block lives in. */
521static __inline__
522Int overhead_szW_lo ( Arena* a )
523{
jsewardb1a26ae2004-03-14 03:06:37 +0000524 return 2 + a->rz_szW;
sewardjde4a1d02002-03-22 01:27:54 +0000525}
526static __inline__
527Int overhead_szW_hi ( Arena* a )
528{
jsewardb1a26ae2004-03-14 03:06:37 +0000529 return 2 + a->rz_szW;
sewardjde4a1d02002-03-22 01:27:54 +0000530}
531static __inline__
532Int overhead_szW ( Arena* a )
533{
534 return overhead_szW_lo(a) + overhead_szW_hi(a);
535}
536
537
njn8a6b6c02003-04-22 22:45:55 +0000538/* Convert payload size in words to block size in words, and back. */
sewardjde4a1d02002-03-22 01:27:54 +0000539static __inline__
540Int pszW_to_bszW ( Arena* a, Int pszW )
541{
542 vg_assert(pszW >= 0);
543 return pszW + overhead_szW(a);
544}
545static __inline__
546Int bszW_to_pszW ( Arena* a, Int bszW )
547{
548 Int pszW = bszW - overhead_szW(a);
549 vg_assert(pszW >= 0);
550 return pszW;
551}
552
njn8a6b6c02003-04-22 22:45:55 +0000553Int VG_(arena_payload_szB) ( ArenaId aid, void* ptr )
554{
555 Arena* a = arenaId_to_ArenaP(aid);
556 Word* fw = payload_to_first(a, (WordF*)ptr);
557 Int pszW = bszW_to_pszW(a, get_bszW_lo(fw));
558 return VKI_BYTES_PER_WORD * pszW;
559}
560
561
sewardjde4a1d02002-03-22 01:27:54 +0000562/*------------------------------------------------------------*/
563/*--- Functions for working with freelists. ---*/
564/*------------------------------------------------------------*/
565
566/* Determination of which freelist a block lives on is based on the
567 payload size, not block size, in words. */
568
569/* Convert a payload size in words to a freelist number. */
570
571static
572Int pszW_to_listNo ( Int pszW )
573{
574 vg_assert(pszW >= 0);
575 if (pszW <= 3) return 0;
576 if (pszW <= 4) return 1;
577 if (pszW <= 5) return 2;
578 if (pszW <= 6) return 3;
579 if (pszW <= 7) return 4;
580 if (pszW <= 8) return 5;
581 if (pszW <= 9) return 6;
582 if (pszW <= 10) return 7;
583 if (pszW <= 11) return 8;
584 if (pszW <= 12) return 9;
585 if (pszW <= 16) return 10;
586 if (pszW <= 32) return 11;
587 if (pszW <= 64) return 12;
588 if (pszW <= 128) return 13;
589 if (pszW <= 256) return 14;
590 return 15;
591}
592
593
594/* What are the minimum and maximum payload sizes for a given list? */
595
596static
597Int listNo_to_pszW_min ( Int listNo )
598{
599 Int pszW = 0;
600 vg_assert(listNo >= 0 && listNo <= VG_N_MALLOC_LISTS);
601 while (pszW_to_listNo(pszW) < listNo) pszW++;
602 return pszW;
603}
604
605static
606Int listNo_to_pszW_max ( Int listNo )
607{
608 vg_assert(listNo >= 0 && listNo <= VG_N_MALLOC_LISTS);
609 if (listNo == VG_N_MALLOC_LISTS-1) {
610 return 999999999;
611 } else {
612 return listNo_to_pszW_min(listNo+1) - 1;
613 }
614}
615
616
617/* A nasty hack to try and reduce fragmentation. Try and replace
618 a->freelist[lno] with another block on the same list but with a
619 lower address, with the idea of attempting to recycle the same
620 blocks rather than cruise through the address space. */
621
622static
623void swizzle ( Arena* a, Int lno )
624{
625 UInt* p_best;
626 UInt* pp;
627 UInt* pn;
628 Int i;
629
630 p_best = a->freelist[lno];
631 if (p_best == NULL) return;
632
633 pn = pp = p_best;
634 for (i = 0; i < 20; i++) {
635 pn = get_next_p(pn);
636 pp = get_prev_p(pp);
637 if (pn < p_best) p_best = pn;
638 if (pp < p_best) p_best = pp;
639 }
640 if (p_best < a->freelist[lno]) {
641# ifdef DEBUG_MALLOC
642 VG_(printf)("retreat by %d\n",
643 ((Char*)(a->freelist[lno])) - ((Char*)p_best));
644# endif
645 a->freelist[lno] = p_best;
646 }
647}
648
649
650/*------------------------------------------------------------*/
651/*--- Creating and deleting blocks. ---*/
652/*------------------------------------------------------------*/
653
654/* Mark the words at b .. b+bszW-1 as not in use, and add them to the
655 relevant free list. */
656
657static
658void mkFreeBlock ( Arena* a, Word* b, Int bszW, Int b_lno )
659{
660 Int pszW = bszW_to_pszW(a, bszW);
661 vg_assert(pszW >= 0);
662 vg_assert(b_lno == pszW_to_listNo(pszW));
663 /* Set the size fields and indicate not-in-use. */
664 set_bszW_lo(b, mk_free_bszW(bszW));
665 set_bszW_hi(b, mk_free_bszW(bszW));
666
667 /* Add to the relevant list. */
668 if (a->freelist[b_lno] == NULL) {
669 set_prev_p(b, b);
670 set_next_p(b, b);
671 a->freelist[b_lno] = b;
672 } else {
673 Word* b_prev = get_prev_p(a->freelist[b_lno]);
674 Word* b_next = a->freelist[b_lno];
675 set_next_p(b_prev, b);
676 set_prev_p(b_next, b);
677 set_next_p(b, b_next);
678 set_prev_p(b, b_prev);
679 }
680# ifdef DEBUG_MALLOC
681 (void)blockSane(a,b);
682# endif
683}
684
685
686/* Mark the words at b .. b+bszW-1 as in use, and set up the block
687 appropriately. */
688static
689void mkInuseBlock ( Arena* a, UInt* b, UInt bszW )
690{
691 Int i;
692 set_bszW_lo(b, mk_inuse_bszW(bszW));
693 set_bszW_hi(b, mk_inuse_bszW(bszW));
694 set_prev_p(b, NULL);
695 set_next_p(b, NULL);
696 if (a->rz_check) {
697 for (i = 0; i < a->rz_szW; i++) {
698 set_rz_lo_word(a, b, i, (UInt)b ^ VG_REDZONE_LO_MASK);
699 set_rz_hi_word(a, b, i, (UInt)b ^ VG_REDZONE_HI_MASK);
700 }
701 }
702# ifdef DEBUG_MALLOC
703 (void)blockSane(a,b);
704# endif
705}
706
707
708/* Remove a block from a given list. Does no sanity checking. */
709static
710void unlinkBlock ( Arena* a, UInt* b, Int listno )
711{
712 vg_assert(listno >= 0 && listno < VG_N_MALLOC_LISTS);
713 if (get_prev_p(b) == b) {
714 /* Only one element in the list; treat it specially. */
715 vg_assert(get_next_p(b) == b);
716 a->freelist[listno] = NULL;
717 } else {
718 UInt* b_prev = get_prev_p(b);
719 UInt* b_next = get_next_p(b);
720 a->freelist[listno] = b_prev;
721 set_next_p(b_prev, b_next);
722 set_prev_p(b_next, b_prev);
723 swizzle ( a, listno );
724 }
725 set_prev_p(b, NULL);
726 set_next_p(b, NULL);
727}
728
729
730/* Split an existing free block into two pieces, and put the fragment
731 (the second one along in memory) onto the relevant free list.
732 req_bszW is the required size of the block which isn't the
733 fragment. */
734static
735void splitChunk ( Arena* a, UInt* b, Int b_listno, UInt req_bszW )
736{
sewardj05bcdcb2003-05-18 10:05:38 +0000737 UInt b_bszW;
738 Int frag_bszW;
739 b_bszW = (UInt)mk_plain_bszW(get_bszW_lo(b));
sewardjde4a1d02002-03-22 01:27:54 +0000740 vg_assert(req_bszW < b_bszW);
741 frag_bszW = b_bszW - req_bszW;
742 vg_assert(frag_bszW >= overhead_szW(a));
743 /*
744 printf( "split %d into %d and %d\n",
745 b_bszW,req_bszW,frag_bszW );
746 */
747 vg_assert(bszW_to_pszW(a, frag_bszW) > 0);
748 unlinkBlock(a, b, b_listno);
749 mkInuseBlock(a, b, req_bszW);
750 mkFreeBlock(a, &b[req_bszW], frag_bszW,
751 pszW_to_listNo(bszW_to_pszW(a, frag_bszW)));
752}
753
754
755/*------------------------------------------------------------*/
756/*--- Sanity-check/debugging machinery. ---*/
757/*------------------------------------------------------------*/
758
759/* Do some crude sanity checks on a chunk. */
760static
761Bool blockSane ( Arena* a, Word* b )
762{
763# define BLEAT(str) VG_(printf)("blockSane: fail -- %s\n",str)
764 Int i;
765 if (get_bszW_lo(b) != get_bszW_hi(b))
766 {BLEAT("sizes");return False;}
767 if (a->rz_check && is_inuse_bszW(get_bszW_lo(b))) {
768 for (i = 0; i < a->rz_szW; i++) {
769 if (get_rz_lo_word(a, b, i) != ((Word)b ^ VG_REDZONE_LO_MASK))
770 {BLEAT("redzone-lo");return False;}
771 if (get_rz_hi_word(a, b, i) != ((Word)b ^ VG_REDZONE_HI_MASK))
772 {BLEAT("redzone-hi");return False;}
773 }
774 }
775 return True;
776# undef BLEAT
777}
778
779
780/* Print superblocks (only for debugging). */
781static
782void ppSuperblocks ( Arena* a )
783{
784 Int i, ch_bszW, blockno;
785 UInt* ch;
786 Superblock* sb = a->sblocks;
787 blockno = 1;
788
789 while (sb) {
790 VG_(printf)( "\n" );
791 VG_(printf)( "superblock %d at %p, sb->n_pl_ws = %d, next = %p\n",
792 blockno++, sb, sb->n_payload_words, sb->next );
793 i = 0;
794 while (True) {
795 if (i >= sb->n_payload_words) break;
796 ch = &sb->payload_words[i];
797 ch_bszW = get_bszW_lo(ch);
798 VG_(printf)( " block at %d, bszW %d: ", i, mk_plain_bszW(ch_bszW) );
799 VG_(printf)( "%s, ", is_inuse_bszW(ch_bszW) ? "inuse" : "free" );
800 VG_(printf)( "%s\n", blockSane(a,ch) ? "ok" : "BAD" );
801 i += mk_plain_bszW(ch_bszW);
802 }
803 if (i > sb->n_payload_words)
804 VG_(printf)( " last block overshoots end of SB\n");
805 sb = sb->next;
806 }
807 VG_(printf)( "end of superblocks\n\n" );
808}
809
810
811/* Sanity check both the superblocks and the chains. */
njn25e49d8e72002-09-23 09:36:25 +0000812static void mallocSanityCheckArena ( ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000813{
814 Int i, superblockctr, b_bszW, b_pszW, blockctr_sb, blockctr_li;
815 Int blockctr_sb_free, listno, list_min_pszW, list_max_pszW;
816 Superblock* sb;
817 Bool thisFree, lastWasFree;
818 Word* b;
819 Word* b_prev;
820 UInt arena_bytes_on_loan;
821 Arena* a;
822
njne427a662002-10-02 11:08:25 +0000823# define BOMB VG_(core_panic)("mallocSanityCheckArena")
sewardjde4a1d02002-03-22 01:27:54 +0000824
825 a = arenaId_to_ArenaP(aid);
826
827 /* First, traverse all the superblocks, inspecting the chunks in
828 each. */
829 superblockctr = blockctr_sb = blockctr_sb_free = 0;
830 arena_bytes_on_loan = 0;
831 sb = a->sblocks;
832 while (sb) {
833 lastWasFree = False;
834 superblockctr++;
835 i = 0;
836 while (True) {
837 if (i >= sb->n_payload_words) break;
838 blockctr_sb++;
839 b = &sb->payload_words[i];
840 b_bszW = get_bszW_lo(b);
841 if (!blockSane(a, b)) {
njn25e49d8e72002-09-23 09:36:25 +0000842 VG_(printf)("mallocSanityCheckArena: sb %p, block %d (bszW %d): "
843 " BAD\n",
sewardjde4a1d02002-03-22 01:27:54 +0000844 sb, i, b_bszW );
845 BOMB;
846 }
847 thisFree = !is_inuse_bszW(b_bszW);
848 if (thisFree && lastWasFree) {
njn25e49d8e72002-09-23 09:36:25 +0000849 VG_(printf)("mallocSanityCheckArena: sb %p, block %d (bszW %d): "
850 "UNMERGED FREES\n",
sewardjde4a1d02002-03-22 01:27:54 +0000851 sb, i, b_bszW );
852 BOMB;
853 }
854 lastWasFree = thisFree;
855 if (thisFree) blockctr_sb_free++;
856 if (!thisFree)
857 arena_bytes_on_loan += sizeof(Word) * bszW_to_pszW(a, b_bszW);
858 i += mk_plain_bszW(b_bszW);
859 }
860 if (i > sb->n_payload_words) {
njn25e49d8e72002-09-23 09:36:25 +0000861 VG_(printf)( "mallocSanityCheckArena: sb %p: last block "
sewardjde4a1d02002-03-22 01:27:54 +0000862 "overshoots end\n", sb);
863 BOMB;
864 }
865 sb = sb->next;
866 }
867
868 if (arena_bytes_on_loan != a->bytes_on_loan) {
869 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +0000870 "mallocSanityCheckArena: a->bytes_on_loan %d, "
sewardjde4a1d02002-03-22 01:27:54 +0000871 "arena_bytes_on_loan %d: "
872 "MISMATCH\n", a->bytes_on_loan, arena_bytes_on_loan);
873 ppSuperblocks(a);
874 BOMB;
875 }
876
877 /* Second, traverse each list, checking that the back pointers make
878 sense, counting blocks encountered, and checking that each block
879 is an appropriate size for this list. */
880 blockctr_li = 0;
881 for (listno = 0; listno < VG_N_MALLOC_LISTS; listno++) {
882 list_min_pszW = listNo_to_pszW_min(listno);
883 list_max_pszW = listNo_to_pszW_max(listno);
884 b = a->freelist[listno];
885 if (b == NULL) continue;
886 while (True) {
887 b_prev = b;
888 b = get_next_p(b);
889 if (get_prev_p(b) != b_prev) {
njn25e49d8e72002-09-23 09:36:25 +0000890 VG_(printf)( "mallocSanityCheckArena: list %d at %p: "
sewardjde4a1d02002-03-22 01:27:54 +0000891 "BAD LINKAGE\n",
892 listno, b );
893 BOMB;
894 }
895 b_pszW = bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(b)));
896 if (b_pszW < list_min_pszW || b_pszW > list_max_pszW) {
897 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +0000898 "mallocSanityCheckArena: list %d at %p: "
sewardjde4a1d02002-03-22 01:27:54 +0000899 "WRONG CHAIN SIZE %d (%d, %d)\n",
900 listno, b, b_pszW, list_min_pszW, list_max_pszW );
901 BOMB;
902 }
903 blockctr_li++;
904 if (b == a->freelist[listno]) break;
905 }
906 }
907
908 if (blockctr_sb_free != blockctr_li) {
909 VG_(printf)(
njn25e49d8e72002-09-23 09:36:25 +0000910 "mallocSanityCheckArena: BLOCK COUNT MISMATCH "
sewardjde4a1d02002-03-22 01:27:54 +0000911 "(via sbs %d, via lists %d)\n",
912 blockctr_sb_free, blockctr_li );
913 ppSuperblocks(a);
914 BOMB;
915 }
916
917 VG_(message)(Vg_DebugMsg,
njn3e884182003-04-15 13:03:23 +0000918 "mSC [%8s]: %2d sbs, %5d tot bs, %4d/%-4d free bs, "
sewardjde4a1d02002-03-22 01:27:54 +0000919 "%2d lists, %7d mmap, %7d loan",
920 a->name,
921 superblockctr,
922 blockctr_sb, blockctr_sb_free, blockctr_li,
923 VG_N_MALLOC_LISTS,
924 a->bytes_mmaped, a->bytes_on_loan);
925# undef BOMB
926}
927
928
929void VG_(mallocSanityCheckAll) ( void )
930{
931 Int i;
932 for (i = 0; i < VG_N_ARENAS; i++)
njn25e49d8e72002-09-23 09:36:25 +0000933 mallocSanityCheckArena ( i );
sewardjde4a1d02002-03-22 01:27:54 +0000934}
935
936
937/* Really, this isn't the right place for this. Nevertheless: find
938 out if an arena is empty -- currently has no bytes on loan. This
939 is useful for checking for memory leaks (of valgrind, not the
940 client.)
941*/
942Bool VG_(is_empty_arena) ( ArenaId aid )
943{
944 Arena* a;
945 Superblock* sb;
946 WordF* b;
947 Int b_bszW;
njn25e49d8e72002-09-23 09:36:25 +0000948
sewardjde4a1d02002-03-22 01:27:54 +0000949 ensure_mm_init();
950 a = arenaId_to_ArenaP(aid);
951 for (sb = a->sblocks; sb != NULL; sb = sb->next) {
952 /* If the superblock is empty, it should contain a single free
953 block, of the right size. */
954 b = &(sb->payload_words[0]);
955 b_bszW = get_bszW_lo(b);
956 if (is_inuse_bszW(b_bszW)) return False;
957 if (mk_plain_bszW(b_bszW) != sb->n_payload_words) return False;
958 /* So this block is not in use and is of the right size. Keep
959 going. */
960 }
961 return True;
962}
963
964
jsewardb1a26ae2004-03-14 03:06:37 +0000965/* Turn a request size in bytes into a payload request size in
966 words. This means 8-aligning the request size.
967*/
968static __inline__
969Int req_pszB_to_req_pszW ( Int req_pszB )
970{
971 return ((req_pszB + 7) / 8) /* # of 64-bit units */
972 * 2; /* # of 32-bit units */
973}
974
975
sewardjde4a1d02002-03-22 01:27:54 +0000976/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000977/*--- Core-visible functions. ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000978/*------------------------------------------------------------*/
979
njn25e49d8e72002-09-23 09:36:25 +0000980void* VG_(arena_malloc) ( ArenaId aid, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +0000981{
982 Int req_pszW, req_bszW, frag_bszW, b_bszW, lno;
983 Superblock* new_sb;
984 Word* b;
985 Arena* a;
jsewardb1a26ae2004-03-14 03:06:37 +0000986 void* v;
sewardjde4a1d02002-03-22 01:27:54 +0000987
988 VGP_PUSHCC(VgpMalloc);
989
990 ensure_mm_init();
991 a = arenaId_to_ArenaP(aid);
992
993 vg_assert(req_pszB >= 0);
994 vg_assert(req_pszB < 0x7FFFFFF0);
995
jsewardb1a26ae2004-03-14 03:06:37 +0000996 req_pszW = req_pszB_to_req_pszW(req_pszB);
sewardjde4a1d02002-03-22 01:27:54 +0000997
998 /* Keep gcc -O happy: */
999 b = NULL;
1000
1001 /* Start searching at this list. */
1002 lno = pszW_to_listNo(req_pszW);
1003
1004 /* This loop finds a list which has a block big enough, or sets
1005 req_listno to N_LISTS if no such block exists. */
1006 while (True) {
1007 if (lno == VG_N_MALLOC_LISTS) break;
1008 /* If this list is empty, try the next one. */
1009 if (a->freelist[lno] == NULL) {
1010 lno++;
1011 continue;
1012 }
1013 /* Scan a->list[lno] to find a big-enough chunk. */
1014 b = a->freelist[lno];
1015 b_bszW = mk_plain_bszW(get_bszW_lo(b));
1016 while (True) {
1017 if (bszW_to_pszW(a, b_bszW) >= req_pszW) break;
1018 b = get_next_p(b);
1019 b_bszW = mk_plain_bszW(get_bszW_lo(b));
1020 if (b == a->freelist[lno]) break;
1021 }
1022 if (bszW_to_pszW(a, b_bszW) >= req_pszW) break;
1023 /* No luck? Try a larger list. */
1024 lno++;
1025 }
1026
1027 /* Either lno < VG_N_MALLOC_LISTS and b points to the selected
1028 block, or lno == VG_N_MALLOC_LISTS, and we have to allocate a
1029 new superblock. */
1030
1031 if (lno == VG_N_MALLOC_LISTS) {
1032 req_bszW = pszW_to_bszW(a, req_pszW);
1033 new_sb = newSuperblock(a, req_bszW);
1034 vg_assert(new_sb != NULL);
1035 new_sb->next = a->sblocks;
1036 a->sblocks = new_sb;
1037 b = &(new_sb->payload_words[0]);
1038 lno = pszW_to_listNo(bszW_to_pszW(a, new_sb->n_payload_words));
1039 mkFreeBlock ( a, b, new_sb->n_payload_words, lno);
1040 }
1041
1042 /* Ok, we can allocate from b, which lives in list req_listno. */
1043 vg_assert(b != NULL);
1044 vg_assert(lno >= 0 && lno < VG_N_MALLOC_LISTS);
1045 vg_assert(a->freelist[lno] != NULL);
1046 b_bszW = mk_plain_bszW(get_bszW_lo(b));
1047 req_bszW = pszW_to_bszW(a, req_pszW);
1048 /* req_bszW is the size of the block we are after. b_bszW is the
1049 size of what we've actually got. */
1050 vg_assert(b_bszW >= req_bszW);
1051
1052 /* Could we split this block and still get a useful fragment?
1053 Where "useful" means that the payload size of the frag is at
1054 least one word. */
1055 frag_bszW = b_bszW - req_bszW;
1056 if (frag_bszW > overhead_szW(a)) {
1057 splitChunk(a, b, lno, req_bszW);
1058 } else {
1059 /* No, mark as in use and use as-is. */
1060 unlinkBlock(a, b, lno);
1061 /*
1062 set_bszW_lo(b, mk_inuse_bszW(b_bszW));
1063 set_bszW_hi(b, mk_inuse_bszW(b_bszW));
1064 */
1065 mkInuseBlock(a, b, b_bszW);
1066 }
1067 vg_assert(req_bszW <= mk_plain_bszW(get_bszW_lo(b)));
1068
1069 a->bytes_on_loan
1070 += sizeof(Word)
1071 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(b)));
1072 if (a->bytes_on_loan > a->bytes_on_loan_max)
1073 a->bytes_on_loan_max = a->bytes_on_loan;
1074
1075# ifdef DEBUG_MALLOC
njn25e49d8e72002-09-23 09:36:25 +00001076 mallocSanityCheckArena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001077# endif
1078
njn25e49d8e72002-09-23 09:36:25 +00001079 VGP_POPCC(VgpMalloc);
jsewardb1a26ae2004-03-14 03:06:37 +00001080 v = first_to_payload(a, b);
1081 vg_assert( (((UInt)v) & 7) == 0 );
1082 return v;
sewardjde4a1d02002-03-22 01:27:54 +00001083}
1084
1085
njn25e49d8e72002-09-23 09:36:25 +00001086void VG_(arena_free) ( ArenaId aid, void* ptr )
sewardjde4a1d02002-03-22 01:27:54 +00001087{
1088 Superblock* sb;
1089 UInt* sb_payl_firstw;
1090 UInt* sb_payl_lastw;
1091 UInt* other;
1092 UInt* ch;
1093 Int ch_bszW, ch_pszW, other_bszW, ch_listno;
1094 Arena* a;
1095
1096 VGP_PUSHCC(VgpMalloc);
1097
1098 ensure_mm_init();
1099 a = arenaId_to_ArenaP(aid);
1100
njn25e49d8e72002-09-23 09:36:25 +00001101 if (ptr == NULL) {
1102 VGP_POPCC(VgpMalloc);
1103 return;
1104 }
1105
sewardjde4a1d02002-03-22 01:27:54 +00001106 ch = payload_to_first(a, ptr);
1107
1108# ifdef DEBUG_MALLOC
1109 vg_assert(blockSane(a,ch));
1110# endif
1111
1112 a->bytes_on_loan
1113 -= sizeof(Word)
1114 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(ch)));
1115
1116 sb = findSb( a, ch );
1117 sb_payl_firstw = &(sb->payload_words[0]);
1118 sb_payl_lastw = &(sb->payload_words[sb->n_payload_words-1]);
1119
1120 /* Put this chunk back on a list somewhere. */
1121 ch_bszW = get_bszW_lo(ch);
1122 ch_pszW = bszW_to_pszW(a, ch_bszW);
1123 ch_listno = pszW_to_listNo(ch_pszW);
1124 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1125
1126 /* See if this block can be merged with the following one. */
1127 other = ch + ch_bszW;
1128 /* overhead_szW(a) is the smallest possible bszW for this arena.
1129 So the nearest possible end to the block beginning at other is
1130 other+overhead_szW(a)-1. Hence the test below. */
1131 if (other+overhead_szW(a)-1 <= sb_payl_lastw) {
1132 other_bszW = get_bszW_lo(other);
1133 if (!is_inuse_bszW(other_bszW)) {
1134 /* VG_(printf)( "merge-successor\n"); */
1135 other_bszW = mk_plain_bszW(other_bszW);
1136# ifdef DEBUG_MALLOC
1137 vg_assert(blockSane(a, other));
1138# endif
1139 unlinkBlock( a, ch, ch_listno );
1140 unlinkBlock( a, other, pszW_to_listNo(bszW_to_pszW(a,other_bszW)) );
1141 ch_bszW += other_bszW;
1142 ch_listno = pszW_to_listNo(bszW_to_pszW(a, ch_bszW));
1143 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1144 }
1145 }
1146
1147 /* See if this block can be merged with its predecessor. */
1148 if (ch-overhead_szW(a) >= sb_payl_firstw) {
1149 other_bszW = get_bszW_hi_from_last_word( ch-1 );
1150 if (!is_inuse_bszW(other_bszW)) {
1151 /* VG_(printf)( "merge-predecessor\n"); */
1152 other = last_to_first( ch-1 );
1153 other_bszW = mk_plain_bszW(other_bszW);
1154 unlinkBlock( a, ch, ch_listno );
1155 unlinkBlock( a, other, pszW_to_listNo(bszW_to_pszW(a, other_bszW)) );
1156 ch = other;
1157 ch_bszW += other_bszW;
1158 ch_listno = pszW_to_listNo(bszW_to_pszW(a, ch_bszW));
1159 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1160 }
1161 }
1162
1163# ifdef DEBUG_MALLOC
njn25e49d8e72002-09-23 09:36:25 +00001164 mallocSanityCheckArena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001165# endif
1166
njn25e49d8e72002-09-23 09:36:25 +00001167 VGP_POPCC(VgpMalloc);
sewardjde4a1d02002-03-22 01:27:54 +00001168}
1169
1170
1171/*
1172 The idea for malloc_aligned() is to allocate a big block, base, and
1173 then split it into two parts: frag, which is returned to the the
1174 free pool, and align, which is the bit we're really after. Here's
1175 a picture. L and H denote the block lower and upper overheads, in
1176 words. The details are gruesome. Note it is slightly complicated
1177 because the initial request to generate base may return a bigger
1178 block than we asked for, so it is important to distinguish the base
1179 request size and the base actual size.
1180
1181 frag_b align_b
1182 | |
1183 | frag_p | align_p
1184 | | | |
1185 v v v v
1186
1187 +---+ +---+---+ +---+
1188 | L |----------------| H | L |---------------| H |
1189 +---+ +---+---+ +---+
1190
1191 ^ ^ ^
1192 | | :
1193 | base_p this addr must be aligned
1194 |
1195 base_b
1196
1197 . . . . . . .
1198 <------ frag_bszW -------> . . .
1199 . <------------- base_pszW_act -----------> .
1200 . . . . . . .
1201
1202*/
njn25e49d8e72002-09-23 09:36:25 +00001203void* VG_(arena_malloc_aligned) ( ArenaId aid, Int req_alignB, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +00001204{
1205 Int req_alignW, req_pszW, base_pszW_req, base_pszW_act, frag_bszW;
1206 Word *base_b, *base_p, *align_p;
1207 UInt saved_bytes_on_loan;
1208 Arena* a;
jsewardb1a26ae2004-03-14 03:06:37 +00001209 void* v;
sewardjde4a1d02002-03-22 01:27:54 +00001210
njn25e49d8e72002-09-23 09:36:25 +00001211 VGP_PUSHCC(VgpMalloc);
1212
sewardjde4a1d02002-03-22 01:27:54 +00001213 ensure_mm_init();
1214 a = arenaId_to_ArenaP(aid);
1215
1216 vg_assert(req_pszB >= 0);
1217 vg_assert(req_pszB < 0x7FFFFFF0);
1218
1219 /* Check that the requested alignment seems reasonable; that is, is
sewardjb5045ef2002-06-04 16:48:29 +00001220 a power of 2. */
sewardjde4a1d02002-03-22 01:27:54 +00001221 switch (req_alignB) {
sewardjc76be292002-04-24 20:32:50 +00001222 case 4:
sewardjde4a1d02002-03-22 01:27:54 +00001223 case 8: case 16: case 32: case 64: case 128: case 256:
1224 case 512: case 1024: case 2048: case 4096: case 8192:
1225 case 16384: case 32768: case 65536: case 131072:
sewardjb5045ef2002-06-04 16:48:29 +00001226 case 262144:
sewardjde4a1d02002-03-22 01:27:54 +00001227 case 1048576:
1228 /* can't be bothered to calculate larger ones */
1229 break;
1230 default:
1231 VG_(printf)("vg_malloc_aligned(%p, %d, %d)\nbad alignment request",
njn25e49d8e72002-09-23 09:36:25 +00001232 a, req_alignB, req_pszB );
njne427a662002-10-02 11:08:25 +00001233 VG_(core_panic)("vg_malloc_aligned");
sewardjde4a1d02002-03-22 01:27:54 +00001234 /*NOTREACHED*/
1235 }
1236
1237 /* Required alignment, in words. Since it's constrained to be a
1238 power of 2 >= word size, no need to align the alignment. Still,
1239 we check. */
jsewardb1a26ae2004-03-14 03:06:37 +00001240 if (req_alignB == 4) req_alignB = 8;
sewardjde4a1d02002-03-22 01:27:54 +00001241 req_alignW = req_alignB / VKI_BYTES_PER_WORD;
1242 vg_assert(req_alignB == req_alignW * VKI_BYTES_PER_WORD);
1243
1244 /* Required payload size for the aligned chunk. */
jsewardb1a26ae2004-03-14 03:06:37 +00001245 req_pszW = req_pszB_to_req_pszW(req_pszB);
sewardjde4a1d02002-03-22 01:27:54 +00001246
1247 /* Payload size to request for the big block that we will split
1248 up. */
1249 base_pszW_req = req_pszW + overhead_szW(a) + req_alignW;
1250
1251 /* Payload ptr for the block we are going to split. Note this
1252 changes a->bytes_on_loan; we save and restore it ourselves. */
1253 saved_bytes_on_loan = a->bytes_on_loan;
njn25e49d8e72002-09-23 09:36:25 +00001254 base_p = VG_(arena_malloc) ( aid, base_pszW_req * VKI_BYTES_PER_WORD );
sewardjde4a1d02002-03-22 01:27:54 +00001255 a->bytes_on_loan = saved_bytes_on_loan;
1256
1257 /* Block ptr for the block we are going to split. */
1258 base_b = payload_to_first ( a, base_p );
1259
1260 /* Pointer to the payload of the aligned block we are going to
1261 return. This has to be suitably aligned. */
1262 align_p = align_upwards ( base_b + 2 * overhead_szW_lo(a)
1263 + overhead_szW_hi(a),
1264 req_alignB );
1265
1266 /* The block size of the fragment we will create. This must be big
1267 enough to actually create a fragment. */
1268 frag_bszW = align_p - overhead_szW_lo(a) - base_b;
1269 vg_assert(frag_bszW >= overhead_szW(a));
1270
1271 /* The actual payload size of the block we are going to split. */
1272 base_pszW_act = bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(base_b)));
1273
1274 /* Create the fragment block, and put it back on the relevant free
1275 list. */
1276 mkFreeBlock ( a, base_b, frag_bszW,
1277 pszW_to_listNo(bszW_to_pszW(a, frag_bszW)) );
1278
1279 /* Create the aligned block. */
1280 mkInuseBlock ( a,
1281 align_p - overhead_szW_lo(a),
1282 base_p + base_pszW_act
1283 + overhead_szW_hi(a)
1284 - (align_p - overhead_szW_lo(a)) );
1285
1286 /* Final sanity checks. */
1287 vg_assert(( (UInt)align_p % req_alignB) == 0);
1288
1289 vg_assert(is_inuse_bszW(get_bszW_lo(payload_to_first(a, align_p))));
1290
1291 vg_assert(req_pszW
1292 <=
1293 bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(
1294 payload_to_first(a, align_p))))
1295 );
1296
1297 a->bytes_on_loan
1298 += sizeof(Word)
1299 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(
1300 payload_to_first(a, align_p))));
1301 if (a->bytes_on_loan > a->bytes_on_loan_max)
1302 a->bytes_on_loan_max = a->bytes_on_loan;
1303
1304# ifdef DEBUG_MALLOC
njn25e49d8e72002-09-23 09:36:25 +00001305 mallocSanityCheckArena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001306# endif
1307
njn25e49d8e72002-09-23 09:36:25 +00001308 VGP_POPCC(VgpMalloc);
1309
jsewardb1a26ae2004-03-14 03:06:37 +00001310 v = (void*)align_p;
1311 vg_assert( (((UInt)v) % req_alignB) == 0 );
1312 return v;
sewardjde4a1d02002-03-22 01:27:54 +00001313}
1314
1315
1316/*------------------------------------------------------------*/
1317/*--- Services layered on top of malloc/free. ---*/
1318/*------------------------------------------------------------*/
1319
njn3e884182003-04-15 13:03:23 +00001320void* VG_(arena_calloc) ( ArenaId aid, Int alignB, Int nmemb, Int nbytes )
sewardjde4a1d02002-03-22 01:27:54 +00001321{
1322 Int i, size;
1323 UChar* p;
njn25e49d8e72002-09-23 09:36:25 +00001324
1325 VGP_PUSHCC(VgpMalloc);
1326
sewardjde4a1d02002-03-22 01:27:54 +00001327 size = nmemb * nbytes;
sewardjd0b9ac32002-05-01 00:10:28 +00001328 vg_assert(size >= 0);
njn3e884182003-04-15 13:03:23 +00001329
jsewardb1a26ae2004-03-14 03:06:37 +00001330 if (alignB == 8)
njn3e884182003-04-15 13:03:23 +00001331 p = VG_(arena_malloc) ( aid, size );
1332 else
1333 p = VG_(arena_malloc_aligned) ( aid, alignB, size );
1334
sewardjde4a1d02002-03-22 01:27:54 +00001335 for (i = 0; i < size; i++) p[i] = 0;
njn25e49d8e72002-09-23 09:36:25 +00001336
1337 VGP_POPCC(VgpMalloc);
1338
sewardjde4a1d02002-03-22 01:27:54 +00001339 return p;
1340}
1341
1342
njn25e49d8e72002-09-23 09:36:25 +00001343void* VG_(arena_realloc) ( ArenaId aid, void* ptr,
jsewardb1a26ae2004-03-14 03:06:37 +00001344 Int req_alignB, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +00001345{
1346 Arena* a;
1347 Int old_bszW, old_pszW, old_pszB, i;
1348 UChar *p_old, *p_new;
1349 UInt* ch;
1350
njn25e49d8e72002-09-23 09:36:25 +00001351 VGP_PUSHCC(VgpMalloc);
1352
sewardjde4a1d02002-03-22 01:27:54 +00001353 ensure_mm_init();
1354 a = arenaId_to_ArenaP(aid);
1355
1356 vg_assert(req_pszB >= 0);
1357 vg_assert(req_pszB < 0x7FFFFFF0);
1358
1359 ch = payload_to_first(a, ptr);
1360 vg_assert(blockSane(a, ch));
1361
1362 old_bszW = get_bszW_lo(ch);
1363 vg_assert(is_inuse_bszW(old_bszW));
1364 old_bszW = mk_plain_bszW(old_bszW);
1365 old_pszW = bszW_to_pszW(a, old_bszW);
1366 old_pszB = old_pszW * VKI_BYTES_PER_WORD;
1367
njn25e49d8e72002-09-23 09:36:25 +00001368 if (req_pszB <= old_pszB) {
1369 VGP_POPCC(VgpMalloc);
1370 return ptr;
1371 }
sewardjde4a1d02002-03-22 01:27:54 +00001372
jsewardb1a26ae2004-03-14 03:06:37 +00001373 if (req_alignB == 8)
njn25e49d8e72002-09-23 09:36:25 +00001374 p_new = VG_(arena_malloc) ( aid, req_pszB );
1375 else
1376 p_new = VG_(arena_malloc_aligned) ( aid, req_alignB, req_pszB );
1377
sewardjde4a1d02002-03-22 01:27:54 +00001378 p_old = (UChar*)ptr;
1379 for (i = 0; i < old_pszB; i++)
1380 p_new[i] = p_old[i];
1381
njn25e49d8e72002-09-23 09:36:25 +00001382 VG_(arena_free)(aid, p_old);
1383
1384 VGP_POPCC(VgpMalloc);
sewardjde4a1d02002-03-22 01:27:54 +00001385 return p_new;
1386}
1387
1388
1389/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001390/*--- Skin-visible functions. ---*/
1391/*------------------------------------------------------------*/
1392
nethercote7cc9c232004-01-21 15:08:04 +00001393/* All just wrappers to avoid exposing arenas to tools */
njn25e49d8e72002-09-23 09:36:25 +00001394
1395void* VG_(malloc) ( Int nbytes )
1396{
nethercote60f5b822004-01-26 17:24:42 +00001397 return VG_(arena_malloc) ( VG_AR_TOOL, nbytes );
njn25e49d8e72002-09-23 09:36:25 +00001398}
1399
1400void VG_(free) ( void* ptr )
1401{
nethercote60f5b822004-01-26 17:24:42 +00001402 VG_(arena_free) ( VG_AR_TOOL, ptr );
njn25e49d8e72002-09-23 09:36:25 +00001403}
1404
1405void* VG_(calloc) ( Int nmemb, Int nbytes )
1406{
jsewardb1a26ae2004-03-14 03:06:37 +00001407 return VG_(arena_calloc) ( VG_AR_TOOL, /*alignment*/8, nmemb, nbytes );
njn25e49d8e72002-09-23 09:36:25 +00001408}
1409
1410void* VG_(realloc) ( void* ptr, Int size )
1411{
jsewardb1a26ae2004-03-14 03:06:37 +00001412 return VG_(arena_realloc) ( VG_AR_TOOL, ptr, /*alignment*/8, size );
njn25e49d8e72002-09-23 09:36:25 +00001413}
1414
1415void* VG_(malloc_aligned) ( Int req_alignB, Int req_pszB )
1416{
nethercote60f5b822004-01-26 17:24:42 +00001417 return VG_(arena_malloc_aligned) ( VG_AR_TOOL, req_alignB, req_pszB );
njn25e49d8e72002-09-23 09:36:25 +00001418}
1419
1420
njn3e884182003-04-15 13:03:23 +00001421void* VG_(cli_malloc) ( UInt align, Int nbytes )
1422{
jsewardb1a26ae2004-03-14 03:06:37 +00001423 vg_assert(align >= 8);
1424 if (8 == align)
njn3e884182003-04-15 13:03:23 +00001425 return VG_(arena_malloc) ( VG_AR_CLIENT, nbytes );
1426 else
sewardjf1accbc2003-07-12 01:26:52 +00001427 return VG_(arena_malloc_aligned) ( VG_AR_CLIENT, align, nbytes );
njn3e884182003-04-15 13:03:23 +00001428}
1429
1430void VG_(cli_free) ( void* p )
1431{
1432 VG_(arena_free) ( VG_AR_CLIENT, p );
1433}
1434
1435
1436Bool VG_(addr_is_in_block)( Addr a, Addr start, UInt size )
1437{
1438 return (start - VG_(vg_malloc_redzone_szB) <= a
1439 && a < start + size + VG_(vg_malloc_redzone_szB));
1440}
1441
1442
njn25e49d8e72002-09-23 09:36:25 +00001443/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00001444/*--- The original test driver machinery. ---*/
1445/*------------------------------------------------------------*/
1446
1447#if 0
1448
1449#if 1
1450#define N_TEST_TRANSACTIONS 100000000
1451#define N_TEST_ARR 200000
1452#define M_TEST_MALLOC 1000
1453#else
1454#define N_TEST_TRANSACTIONS 500000
1455#define N_TEST_ARR 30000
1456#define M_TEST_MALLOC 500
1457#endif
1458
1459
1460void* test_arr[N_TEST_ARR];
1461
1462int main ( int argc, char** argv )
1463{
1464 Int i, j, k, nbytes, qq;
1465 unsigned char* chp;
njn25e49d8e72002-09-23 09:36:25 +00001466 Arena* a = &arena[VG_AR_CORE];
sewardjde4a1d02002-03-22 01:27:54 +00001467 srandom(1);
1468 for (i = 0; i < N_TEST_ARR; i++)
1469 test_arr[i] = NULL;
1470
1471 for (i = 0; i < N_TEST_TRANSACTIONS; i++) {
1472 if (i % 50000 == 0) mallocSanityCheck(a);
1473 j = random() % N_TEST_ARR;
1474 if (test_arr[j]) {
1475 vg_free(a, test_arr[j]);
1476 test_arr[j] = NULL;
1477 } else {
1478 nbytes = 1 + random() % M_TEST_MALLOC;
1479 qq = random()%64;
1480 if (qq == 32)
1481 nbytes *= 17;
1482 else if (qq == 33)
1483 nbytes = 0;
1484 test_arr[j]
1485 = (i % 17) == 0
1486 ? vg_memalign(a, nbytes, 1<< (3+(random()%10)))
1487 : vg_malloc( a, nbytes );
1488 chp = test_arr[j];
1489 for (k = 0; k < nbytes; k++)
1490 chp[k] = (unsigned char)(k + 99);
1491 }
1492 }
1493
1494
1495 for (i = 0; i < N_TEST_ARR; i++) {
1496 if (test_arr[i]) {
1497 vg_free(a, test_arr[i]);
1498 test_arr[i] = NULL;
1499 }
1500 }
1501 mallocSanityCheck(a);
1502
1503 fprintf(stderr, "ALL DONE\n");
1504
1505 show_arena_stats(a);
1506 fprintf(stderr, "%d max useful, %d bytes mmap'd (%4.1f%%), %d useful\n",
1507 a->bytes_on_loan_max,
1508 a->bytes_mmaped,
1509 100.0 * (double)a->bytes_on_loan_max / (double)a->bytes_mmaped,
1510 a->bytes_on_loan );
1511
1512 return 0;
1513}
1514#endif /* 0 */
1515
1516
1517/*--------------------------------------------------------------------*/
1518/*--- end vg_malloc2.c ---*/
1519/*--------------------------------------------------------------------*/