blob: 34dd228e5b230762ded27ea0ea1406052757259b [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
nethercotef28481f2004-07-10 13:56:19 +000069 else VG_BOOL_CLO("--sloppy-malloc", VG_(clo_sloppy_malloc))
70 else VG_BOOL_CLO("--trace-malloc", VG_(clo_trace_malloc))
fitzhardinge98abfc72003-12-16 02:05:15 +000071 else
72 return False;
73
74 return True;
75}
76
77void VG_(replacement_malloc_print_usage)(void)
78{
79 VG_(printf)(
80" --sloppy-malloc=no|yes round malloc sizes to next word? [no]\n"
mueller273d1d72004-03-13 02:49:49 +000081" --alignment=<number> set minimum alignment of allocations [8]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +000082 );
83}
84
85void VG_(replacement_malloc_print_debug_usage)(void)
86{
87 VG_(printf)(
88" --trace-malloc=no|yes show client malloc details? [no]\n"
89 );
90}
91
sewardjde4a1d02002-03-22 01:27:54 +000092
93/*------------------------------------------------------------*/
94/*--- Structs n stuff ---*/
95/*------------------------------------------------------------*/
96
97#define VG_REDZONE_LO_MASK 0x31415927
98#define VG_REDZONE_HI_MASK 0x14141356
99
100#define VG_N_MALLOC_LISTS 16 /* do not change this */
101
102
103typedef UInt Word;
104typedef Word WordF;
105typedef Word WordL;
106
107
108/* A superblock. */
109typedef
110 struct _Superblock {
111 struct _Superblock* next;
112 /* number of payload words in this superblock. */
113 Int n_payload_words;
114 Word payload_words[0];
115 }
116 Superblock;
117
118
119/* An arena. */
120typedef
121 struct {
122 Char* name;
fitzhardinge98abfc72003-12-16 02:05:15 +0000123 Bool clientmem; /* allocates in the client address space */
124 Int rz_szW; /* Red zone size in words */
125 Bool rz_check; /* Check red-zone on free? */
126 Int min_sblockW; /* Minimum superblock size */
sewardjde4a1d02002-03-22 01:27:54 +0000127 WordF* freelist[VG_N_MALLOC_LISTS];
128 Superblock* sblocks;
129 /* Stats only. */
130 UInt bytes_on_loan;
131 UInt bytes_mmaped;
132 UInt bytes_on_loan_max;
133 }
134 Arena;
135
136
137/* Block layout:
138
139 this block total sizeW (1 word)
140 freelist previous ptr (1 word)
sewardjde4a1d02002-03-22 01:27:54 +0000141 red zone words (depends on .rz_szW field of Arena)
142 (payload words)
143 red zone words (depends on .rz_szW field of Arena)
jsewardb1a26ae2004-03-14 03:06:37 +0000144 freelist next ptr (1 word)
145 this block total sizeW (1 word)
sewardjde4a1d02002-03-22 01:27:54 +0000146
147 Total size in words (bszW) and payload size in words (pszW)
148 are related by
149 bszW == pszW + 4 + 2 * a->rz_szW
150
151 Furthermore, both size fields in the block are negative if it is
152 not in use, and positive if it is in use. A block size of zero
153 is not possible, because a block always has at least four words
154 of overhead.
jsewardb1a26ae2004-03-14 03:06:37 +0000155
156 8-byte payload alignment is ensured by requiring the number
157 of words in the red zones and the number of payload words
158 to both be even (% 2 == 0).
sewardjde4a1d02002-03-22 01:27:54 +0000159*/
160typedef
161 struct {
162 Int bszW_lo;
163 Word* prev;
164 Word* next;
165 Word redzone[0];
166 }
167 BlockHeader;
168
169
170/*------------------------------------------------------------*/
171/*--- Forwardses ... and misc ... ---*/
172/*------------------------------------------------------------*/
173
174static Bool blockSane ( Arena* a, Word* b );
175
176/* Align ptr p upwards to an align-sized boundary. */
177static
178void* align_upwards ( void* p, Int align )
179{
180 Addr a = (Addr)p;
181 if ((a % align) == 0) return (void*)a;
182 return (void*)(a - (a % align) + align);
183}
184
185
186/*------------------------------------------------------------*/
187/*--- Arena management stuff ---*/
188/*------------------------------------------------------------*/
189
nethercotec314eba2004-07-15 12:59:41 +0000190#define CORE_ARENA_MIN_SZW 262144
191
sewardjde4a1d02002-03-22 01:27:54 +0000192/* The arena structures themselves. */
193static Arena vg_arena[VG_N_ARENAS];
194
195/* Functions external to this module identify arenas using ArenaIds,
196 not Arena*s. This fn converts the former to the latter. */
197static Arena* arenaId_to_ArenaP ( ArenaId arena )
198{
199 vg_assert(arena >= 0 && arena < VG_N_ARENAS);
200 return & vg_arena[arena];
201}
202
203
204/* Initialise an arena. */
205static
206void arena_init ( Arena* a, Char* name,
fitzhardinge98abfc72003-12-16 02:05:15 +0000207 Int rz_szW, Bool rz_check, Int min_sblockW, Bool client )
sewardjde4a1d02002-03-22 01:27:54 +0000208{
209 Int i;
jsewardb1a26ae2004-03-14 03:06:37 +0000210 vg_assert(rz_szW >= 0);
211 vg_assert(rz_szW % 2 == 0);
sewardjde4a1d02002-03-22 01:27:54 +0000212 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. */
nethercote885dd912004-08-03 23:14:00 +0000227void VG_(print_all_arena_stats) ( void )
sewardjde4a1d02002-03-22 01:27:54 +0000228{
229 Int i;
230 for (i = 0; i < VG_N_ARENAS; i++) {
231 VG_(message)(Vg_DebugMsg,
nethercote885dd912004-08-03 23:14:00 +0000232 "AR %8s: %8d mmap'd, %8d/%8d max/curr",
sewardjde4a1d02002-03-22 01:27:54 +0000233 vg_arena[i].name,
sewardjde4a1d02002-03-22 01:27:54 +0000234 vg_arena[i].bytes_mmaped,
nethercote885dd912004-08-03 23:14:00 +0000235 vg_arena[i].bytes_on_loan_max,
sewardjde4a1d02002-03-22 01:27:54 +0000236 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{
nethercotec314eba2004-07-15 12:59:41 +0000251 static Int client_rz_szW;
sewardjde4a1d02002-03-22 01:27:54 +0000252 static Bool init_done = False;
jsewardb1a26ae2004-03-14 03:06:37 +0000253
nethercotec314eba2004-07-15 12:59:41 +0000254 if (init_done) {
255 // Make sure the client arena's redzone size never changes. Could
256 // happen if VG_(arena_malloc) was called too early, ie. before the
257 // tool was loaded.
258 vg_assert(client_rz_szW == VG_(vg_malloc_redzone_szB)/4);
259 return;
260 }
sewardjde4a1d02002-03-22 01:27:54 +0000261
nethercotee1efb922004-07-10 16:01:52 +0000262 /* Use checked red zones (of various sizes) for our internal stuff,
sewardjde4a1d02002-03-22 01:27:54 +0000263 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
nethercotec314eba2004-07-15 12:59:41 +0000269 arena_init ( &vg_arena[VG_AR_CORE], "core", 2, True, CORE_ARENA_MIN_SZW, 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;
jsewardb1a26ae2004-03-14 03:06:37 +0000281
njn3e884182003-04-15 13:03:23 +0000282 arena_init ( &vg_arena[VG_AR_CLIENT], "client",
jsewardb1a26ae2004-03-14 03:06:37 +0000283 client_rz_szW, False, 262144, True );
sewardjde4a1d02002-03-22 01:27:54 +0000284
njn3e884182003-04-15 13:03:23 +0000285 arena_init ( &vg_arena[VG_AR_DEMANGLE], "demangle", 4 /*paranoid*/,
fitzhardinge98abfc72003-12-16 02:05:15 +0000286 True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000287
jsewardb1a26ae2004-03-14 03:06:37 +0000288 arena_init ( &vg_arena[VG_AR_EXECTXT], "exectxt", 2, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000289
jsewardb1a26ae2004-03-14 03:06:37 +0000290 arena_init ( &vg_arena[VG_AR_ERRORS], "errors", 2, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000291
fitzhardinge98abfc72003-12-16 02:05:15 +0000292 arena_init ( &vg_arena[VG_AR_TRANSIENT], "transien", 2, True, 16384, False );
sewardjde4a1d02002-03-22 01:27:54 +0000293
294 init_done = True;
295# ifdef DEBUG_MALLOC
nethercote885dd912004-08-03 23:14:00 +0000296 VG_(sanity_check_malloc_all)();
sewardjde4a1d02002-03-22 01:27:54 +0000297# endif
298}
299
300
301/*------------------------------------------------------------*/
sewardjecf8e102003-07-12 12:11:39 +0000302/*--- Superblock management stuff ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000303/*------------------------------------------------------------*/
304
nethercotec314eba2004-07-15 12:59:41 +0000305// If not enough memory available, either aborts (for non-client memory)
306// or returns 0 (for client memory).
sewardjde4a1d02002-03-22 01:27:54 +0000307static
308Superblock* newSuperblock ( Arena* a, Int cszW )
309{
nethercotec314eba2004-07-15 12:59:41 +0000310 static Bool called_before = False;
311 static Word bootstrap_superblock[CORE_ARENA_MIN_SZW];
312 Int cszB;
sewardjde4a1d02002-03-22 01:27:54 +0000313 Superblock* sb;
nethercotec314eba2004-07-15 12:59:41 +0000314
sewardjde4a1d02002-03-22 01:27:54 +0000315 cszW += 2; /* Take into account sb->next and sb->n_words fields */
316 if (cszW < a->min_sblockW) cszW = a->min_sblockW;
317 while ((cszW % VKI_WORDS_PER_PAGE) > 0) cszW++;
fitzhardinge98abfc72003-12-16 02:05:15 +0000318
nethercotec314eba2004-07-15 12:59:41 +0000319 cszB = cszW * sizeof(Word);
320
321 if (!called_before) {
322 // First time we're called -- use the special static bootstrap
323 // superblock (see comment at top of main() for details).
324 called_before = True;
325 vg_assert(a == &vg_arena[VG_AR_CORE]);
326 vg_assert(CORE_ARENA_MIN_SZW*sizeof(Word) >= cszB);
327 sb = (Superblock*)bootstrap_superblock;
328
329 } else if (a->clientmem) {
nethercote57e36b32004-07-10 14:56:28 +0000330 // client allocation -- return 0 to client if it fails
jsewardb1a26ae2004-03-14 03:06:37 +0000331 sb = (Superblock *)
nethercotec314eba2004-07-15 12:59:41 +0000332 VG_(client_alloc)(0, cszB,
nethercote57e36b32004-07-10 14:56:28 +0000333 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC, 0);
334 if (NULL == sb) {
335 return 0;
336 }
337 } else {
338 // non-client allocation -- abort if it fails
nethercotec314eba2004-07-15 12:59:41 +0000339 sb = VG_(get_memory_from_mmap) ( cszB, "newSuperblock" );
nethercote57e36b32004-07-10 14:56:28 +0000340 }
sewardjde4a1d02002-03-22 01:27:54 +0000341 sb->n_payload_words = cszW - 2;
nethercotec314eba2004-07-15 12:59:41 +0000342 a->bytes_mmaped += cszB;
sewardjde4a1d02002-03-22 01:27:54 +0000343 if (0)
344 VG_(message)(Vg_DebugMsg, "newSuperblock, %d payload words",
345 sb->n_payload_words);
346 return sb;
347}
348
349
350/* Find the superblock containing the given chunk. */
351static
352Superblock* findSb ( Arena* a, UInt* ch )
353{
354 Superblock* sb;
355 for (sb = a->sblocks; sb; sb = sb->next)
356 if (&sb->payload_words[0] <= ch
357 && ch < &sb->payload_words[sb->n_payload_words])
358 return sb;
359 VG_(printf)("findSb: can't find pointer %p in arena `%s'\n",
360 ch, a->name );
njne427a662002-10-02 11:08:25 +0000361 VG_(core_panic)("findSb: vg_free() in wrong arena?");
sewardjde4a1d02002-03-22 01:27:54 +0000362 return NULL; /*NOTREACHED*/
363}
364
365
366/*------------------------------------------------------------*/
367/*--- Low-level functions for working with blocks. ---*/
368/*------------------------------------------------------------*/
369
370/* Add the not-in-use attribute to a bszW. */
371static __inline__
372Int mk_free_bszW ( Int bszW )
373{
374 vg_assert(bszW != 0);
375 return (bszW < 0) ? bszW : -bszW;
376}
377
378/* Add the in-use attribute to a bszW. */
379static __inline__
380Int mk_inuse_bszW ( Int bszW )
381{
382 vg_assert(bszW != 0);
383 return (bszW < 0) ? -bszW : bszW;
384}
385
386/* Remove the in-use/not-in-use attribute from a bszW, leaving just
387 the size. */
388static __inline__
389Int mk_plain_bszW ( Int bszW )
390{
391 vg_assert(bszW != 0);
392 return (bszW < 0) ? -bszW : bszW;
393}
394
395/* Does this bszW have the in-use attribute ? */
396static __inline__
397Bool is_inuse_bszW ( Int bszW )
398{
399 vg_assert(bszW != 0);
400 return (bszW < 0) ? False : True;
401}
402
403
404/* Given the addr of the first word of a block, return the addr of the
405 last word. */
406static __inline__
407WordL* first_to_last ( WordF* fw )
408{
409 return fw + mk_plain_bszW(fw[0]) - 1;
410}
411
412/* Given the addr of the last word of a block, return the addr of the
413 first word. */
414static __inline__
415WordF* last_to_first ( WordL* lw )
416{
417 return lw - mk_plain_bszW(lw[0]) + 1;
418}
419
420
421/* Given the addr of the first word of a block, return the addr of the
422 first word of its payload. */
423static __inline__
424Word* first_to_payload ( Arena* a, WordF* fw )
425{
jsewardb1a26ae2004-03-14 03:06:37 +0000426 return & fw[2 + a->rz_szW];
sewardjde4a1d02002-03-22 01:27:54 +0000427}
428
njn8a6b6c02003-04-22 22:45:55 +0000429/* Given the addr of the first word of the payload of a block,
sewardjde4a1d02002-03-22 01:27:54 +0000430 return the addr of the first word of the block. */
431static __inline__
432Word* payload_to_first ( Arena* a, WordF* payload )
433{
jsewardb1a26ae2004-03-14 03:06:37 +0000434 return & payload[- (2 + a->rz_szW)];
sewardjde4a1d02002-03-22 01:27:54 +0000435}
436
437/* Set and get the lower size field of a block. */
438static __inline__
439void set_bszW_lo ( WordF* fw, Int bszW ) {
440 fw[0] = bszW;
441}
442static __inline__
443Int get_bszW_lo ( WordF* fw )
444{
445 return fw[0];
446}
447
448
449/* Set and get the next and previous link fields of a block. */
450static __inline__
451void set_prev_p ( WordF* fw, Word* prev_p ) {
452 fw[1] = (Word)prev_p;
453}
454static __inline__
jsewardb1a26ae2004-03-14 03:06:37 +0000455void set_next_p ( WordF* fw, Word* next_p ) {
456 WordL* lw = first_to_last(fw);
457 lw[-1] = (Word)next_p;
sewardjde4a1d02002-03-22 01:27:54 +0000458}
459static __inline__
460Word* get_prev_p ( WordF* fw ) {
461 return (Word*)(fw[1]);
462}
463static __inline__
464Word* get_next_p ( WordF* fw ) {
jsewardb1a26ae2004-03-14 03:06:37 +0000465 WordL* lw = first_to_last(fw);
466 return (Word*)(lw[-1]);
sewardjde4a1d02002-03-22 01:27:54 +0000467}
468
469
470/* Set and get the upper size field of a block. */
471static __inline__
472void set_bszW_hi ( WordF* fw, Int bszW ) {
473 WordL* lw = first_to_last(fw);
474 vg_assert(lw == fw + mk_plain_bszW(bszW) - 1);
475 lw[0] = bszW;
476}
477static __inline__
478Int get_bszW_hi ( WordF* fw ) {
479 WordL* lw = first_to_last(fw);
480 return lw[0];
481}
482
483/* Get the upper size field of a block, given a pointer to the last
484 word of it. */
485static __inline__
486Int get_bszW_hi_from_last_word ( WordL* lw ) {
487 WordF* fw = last_to_first(lw);
488 return get_bszW_lo(fw);
489}
490
491
492/* Read and write the lower and upper red-zone words of a block. */
493static __inline__
494void set_rz_lo_word ( Arena* a, WordF* fw, Int rz_wordno, Word w )
495{
jsewardb1a26ae2004-03-14 03:06:37 +0000496 fw[2 + rz_wordno] = w;
sewardjde4a1d02002-03-22 01:27:54 +0000497}
498static __inline__
499void set_rz_hi_word ( Arena* a, WordF* fw, Int rz_wordno, Word w )
500{
501 WordL* lw = first_to_last(fw);
jsewardb1a26ae2004-03-14 03:06:37 +0000502 lw[-2-rz_wordno] = w;
sewardjde4a1d02002-03-22 01:27:54 +0000503}
504static __inline__
505Word get_rz_lo_word ( Arena* a, WordF* fw, Int rz_wordno )
506{
jsewardb1a26ae2004-03-14 03:06:37 +0000507 return fw[2 + rz_wordno];
sewardjde4a1d02002-03-22 01:27:54 +0000508}
509static __inline__
510Word get_rz_hi_word ( Arena* a, WordF* fw, Int rz_wordno )
511{
512 WordL* lw = first_to_last(fw);
jsewardb1a26ae2004-03-14 03:06:37 +0000513 return lw[-2-rz_wordno];
sewardjde4a1d02002-03-22 01:27:54 +0000514}
515
516
517/* Return the lower, upper and total overhead in words for a block.
518 These are determined purely by which arena the block lives in. */
519static __inline__
520Int overhead_szW_lo ( Arena* a )
521{
jsewardb1a26ae2004-03-14 03:06:37 +0000522 return 2 + a->rz_szW;
sewardjde4a1d02002-03-22 01:27:54 +0000523}
524static __inline__
525Int overhead_szW_hi ( Arena* a )
526{
jsewardb1a26ae2004-03-14 03:06:37 +0000527 return 2 + a->rz_szW;
sewardjde4a1d02002-03-22 01:27:54 +0000528}
529static __inline__
530Int overhead_szW ( Arena* a )
531{
532 return overhead_szW_lo(a) + overhead_szW_hi(a);
533}
534
535
njn8a6b6c02003-04-22 22:45:55 +0000536/* Convert payload size in words to block size in words, and back. */
sewardjde4a1d02002-03-22 01:27:54 +0000537static __inline__
538Int pszW_to_bszW ( Arena* a, Int pszW )
539{
540 vg_assert(pszW >= 0);
541 return pszW + overhead_szW(a);
542}
543static __inline__
544Int bszW_to_pszW ( Arena* a, Int bszW )
545{
546 Int pszW = bszW - overhead_szW(a);
547 vg_assert(pszW >= 0);
548 return pszW;
549}
550
njn8a6b6c02003-04-22 22:45:55 +0000551Int VG_(arena_payload_szB) ( ArenaId aid, void* ptr )
552{
553 Arena* a = arenaId_to_ArenaP(aid);
554 Word* fw = payload_to_first(a, (WordF*)ptr);
555 Int pszW = bszW_to_pszW(a, get_bszW_lo(fw));
556 return VKI_BYTES_PER_WORD * pszW;
557}
558
559
sewardjde4a1d02002-03-22 01:27:54 +0000560/*------------------------------------------------------------*/
561/*--- Functions for working with freelists. ---*/
562/*------------------------------------------------------------*/
563
564/* Determination of which freelist a block lives on is based on the
565 payload size, not block size, in words. */
566
567/* Convert a payload size in words to a freelist number. */
568
569static
570Int pszW_to_listNo ( Int pszW )
571{
572 vg_assert(pszW >= 0);
573 if (pszW <= 3) return 0;
574 if (pszW <= 4) return 1;
575 if (pszW <= 5) return 2;
576 if (pszW <= 6) return 3;
577 if (pszW <= 7) return 4;
578 if (pszW <= 8) return 5;
579 if (pszW <= 9) return 6;
580 if (pszW <= 10) return 7;
581 if (pszW <= 11) return 8;
582 if (pszW <= 12) return 9;
583 if (pszW <= 16) return 10;
584 if (pszW <= 32) return 11;
585 if (pszW <= 64) return 12;
586 if (pszW <= 128) return 13;
587 if (pszW <= 256) return 14;
588 return 15;
589}
590
591
592/* What are the minimum and maximum payload sizes for a given list? */
593
594static
595Int listNo_to_pszW_min ( Int listNo )
596{
597 Int pszW = 0;
598 vg_assert(listNo >= 0 && listNo <= VG_N_MALLOC_LISTS);
599 while (pszW_to_listNo(pszW) < listNo) pszW++;
600 return pszW;
601}
602
603static
604Int listNo_to_pszW_max ( Int listNo )
605{
606 vg_assert(listNo >= 0 && listNo <= VG_N_MALLOC_LISTS);
607 if (listNo == VG_N_MALLOC_LISTS-1) {
608 return 999999999;
609 } else {
610 return listNo_to_pszW_min(listNo+1) - 1;
611 }
612}
613
614
615/* A nasty hack to try and reduce fragmentation. Try and replace
616 a->freelist[lno] with another block on the same list but with a
617 lower address, with the idea of attempting to recycle the same
618 blocks rather than cruise through the address space. */
619
620static
621void swizzle ( Arena* a, Int lno )
622{
623 UInt* p_best;
624 UInt* pp;
625 UInt* pn;
626 Int i;
627
628 p_best = a->freelist[lno];
629 if (p_best == NULL) return;
630
631 pn = pp = p_best;
632 for (i = 0; i < 20; i++) {
633 pn = get_next_p(pn);
634 pp = get_prev_p(pp);
635 if (pn < p_best) p_best = pn;
636 if (pp < p_best) p_best = pp;
637 }
638 if (p_best < a->freelist[lno]) {
639# ifdef DEBUG_MALLOC
640 VG_(printf)("retreat by %d\n",
641 ((Char*)(a->freelist[lno])) - ((Char*)p_best));
642# endif
643 a->freelist[lno] = p_best;
644 }
645}
646
647
648/*------------------------------------------------------------*/
649/*--- Creating and deleting blocks. ---*/
650/*------------------------------------------------------------*/
651
652/* Mark the words at b .. b+bszW-1 as not in use, and add them to the
653 relevant free list. */
654
655static
656void mkFreeBlock ( Arena* a, Word* b, Int bszW, Int b_lno )
657{
658 Int pszW = bszW_to_pszW(a, bszW);
659 vg_assert(pszW >= 0);
660 vg_assert(b_lno == pszW_to_listNo(pszW));
661 /* Set the size fields and indicate not-in-use. */
662 set_bszW_lo(b, mk_free_bszW(bszW));
663 set_bszW_hi(b, mk_free_bszW(bszW));
664
665 /* Add to the relevant list. */
666 if (a->freelist[b_lno] == NULL) {
667 set_prev_p(b, b);
668 set_next_p(b, b);
669 a->freelist[b_lno] = b;
670 } else {
671 Word* b_prev = get_prev_p(a->freelist[b_lno]);
672 Word* b_next = a->freelist[b_lno];
673 set_next_p(b_prev, b);
674 set_prev_p(b_next, b);
675 set_next_p(b, b_next);
676 set_prev_p(b, b_prev);
677 }
678# ifdef DEBUG_MALLOC
679 (void)blockSane(a,b);
680# endif
681}
682
683
684/* Mark the words at b .. b+bszW-1 as in use, and set up the block
685 appropriately. */
686static
687void mkInuseBlock ( Arena* a, UInt* b, UInt bszW )
688{
689 Int i;
690 set_bszW_lo(b, mk_inuse_bszW(bszW));
691 set_bszW_hi(b, mk_inuse_bszW(bszW));
692 set_prev_p(b, NULL);
693 set_next_p(b, NULL);
694 if (a->rz_check) {
695 for (i = 0; i < a->rz_szW; i++) {
696 set_rz_lo_word(a, b, i, (UInt)b ^ VG_REDZONE_LO_MASK);
697 set_rz_hi_word(a, b, i, (UInt)b ^ VG_REDZONE_HI_MASK);
698 }
699 }
700# ifdef DEBUG_MALLOC
701 (void)blockSane(a,b);
702# endif
703}
704
705
706/* Remove a block from a given list. Does no sanity checking. */
707static
708void unlinkBlock ( Arena* a, UInt* b, Int listno )
709{
710 vg_assert(listno >= 0 && listno < VG_N_MALLOC_LISTS);
711 if (get_prev_p(b) == b) {
712 /* Only one element in the list; treat it specially. */
713 vg_assert(get_next_p(b) == b);
714 a->freelist[listno] = NULL;
715 } else {
716 UInt* b_prev = get_prev_p(b);
717 UInt* b_next = get_next_p(b);
718 a->freelist[listno] = b_prev;
719 set_next_p(b_prev, b_next);
720 set_prev_p(b_next, b_prev);
721 swizzle ( a, listno );
722 }
723 set_prev_p(b, NULL);
724 set_next_p(b, NULL);
725}
726
727
728/* Split an existing free block into two pieces, and put the fragment
729 (the second one along in memory) onto the relevant free list.
730 req_bszW is the required size of the block which isn't the
731 fragment. */
732static
733void splitChunk ( Arena* a, UInt* b, Int b_listno, UInt req_bszW )
734{
sewardj05bcdcb2003-05-18 10:05:38 +0000735 UInt b_bszW;
736 Int frag_bszW;
737 b_bszW = (UInt)mk_plain_bszW(get_bszW_lo(b));
sewardjde4a1d02002-03-22 01:27:54 +0000738 vg_assert(req_bszW < b_bszW);
739 frag_bszW = b_bszW - req_bszW;
740 vg_assert(frag_bszW >= overhead_szW(a));
741 /*
742 printf( "split %d into %d and %d\n",
743 b_bszW,req_bszW,frag_bszW );
744 */
745 vg_assert(bszW_to_pszW(a, frag_bszW) > 0);
746 unlinkBlock(a, b, b_listno);
747 mkInuseBlock(a, b, req_bszW);
748 mkFreeBlock(a, &b[req_bszW], frag_bszW,
749 pszW_to_listNo(bszW_to_pszW(a, frag_bszW)));
750}
751
752
753/*------------------------------------------------------------*/
754/*--- Sanity-check/debugging machinery. ---*/
755/*------------------------------------------------------------*/
756
757/* Do some crude sanity checks on a chunk. */
758static
759Bool blockSane ( Arena* a, Word* b )
760{
761# define BLEAT(str) VG_(printf)("blockSane: fail -- %s\n",str)
762 Int i;
763 if (get_bszW_lo(b) != get_bszW_hi(b))
764 {BLEAT("sizes");return False;}
765 if (a->rz_check && is_inuse_bszW(get_bszW_lo(b))) {
766 for (i = 0; i < a->rz_szW; i++) {
767 if (get_rz_lo_word(a, b, i) != ((Word)b ^ VG_REDZONE_LO_MASK))
768 {BLEAT("redzone-lo");return False;}
769 if (get_rz_hi_word(a, b, i) != ((Word)b ^ VG_REDZONE_HI_MASK))
770 {BLEAT("redzone-hi");return False;}
771 }
772 }
773 return True;
774# undef BLEAT
775}
776
777
778/* Print superblocks (only for debugging). */
779static
780void ppSuperblocks ( Arena* a )
781{
782 Int i, ch_bszW, blockno;
783 UInt* ch;
784 Superblock* sb = a->sblocks;
785 blockno = 1;
786
787 while (sb) {
788 VG_(printf)( "\n" );
789 VG_(printf)( "superblock %d at %p, sb->n_pl_ws = %d, next = %p\n",
790 blockno++, sb, sb->n_payload_words, sb->next );
791 i = 0;
792 while (True) {
793 if (i >= sb->n_payload_words) break;
794 ch = &sb->payload_words[i];
795 ch_bszW = get_bszW_lo(ch);
796 VG_(printf)( " block at %d, bszW %d: ", i, mk_plain_bszW(ch_bszW) );
797 VG_(printf)( "%s, ", is_inuse_bszW(ch_bszW) ? "inuse" : "free" );
798 VG_(printf)( "%s\n", blockSane(a,ch) ? "ok" : "BAD" );
799 i += mk_plain_bszW(ch_bszW);
800 }
801 if (i > sb->n_payload_words)
802 VG_(printf)( " last block overshoots end of SB\n");
803 sb = sb->next;
804 }
805 VG_(printf)( "end of superblocks\n\n" );
806}
807
808
809/* Sanity check both the superblocks and the chains. */
nethercote885dd912004-08-03 23:14:00 +0000810static void sanity_check_malloc_arena ( ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000811{
812 Int i, superblockctr, b_bszW, b_pszW, blockctr_sb, blockctr_li;
813 Int blockctr_sb_free, listno, list_min_pszW, list_max_pszW;
814 Superblock* sb;
815 Bool thisFree, lastWasFree;
816 Word* b;
817 Word* b_prev;
818 UInt arena_bytes_on_loan;
819 Arena* a;
820
nethercote885dd912004-08-03 23:14:00 +0000821# define BOMB VG_(core_panic)("sanity_check_malloc_arena")
sewardjde4a1d02002-03-22 01:27:54 +0000822
823 a = arenaId_to_ArenaP(aid);
824
nethercote885dd912004-08-03 23:14:00 +0000825 /* First, traverse all the superblocks, inspecting the chunks in each. */
sewardjde4a1d02002-03-22 01:27:54 +0000826 superblockctr = blockctr_sb = blockctr_sb_free = 0;
827 arena_bytes_on_loan = 0;
828 sb = a->sblocks;
829 while (sb) {
830 lastWasFree = False;
831 superblockctr++;
832 i = 0;
833 while (True) {
834 if (i >= sb->n_payload_words) break;
835 blockctr_sb++;
836 b = &sb->payload_words[i];
837 b_bszW = get_bszW_lo(b);
838 if (!blockSane(a, b)) {
nethercote885dd912004-08-03 23:14:00 +0000839 VG_(printf)("sanity_check_malloc_arena: sb %p, block %d (bszW %d): "
njn25e49d8e72002-09-23 09:36:25 +0000840 " BAD\n",
sewardjde4a1d02002-03-22 01:27:54 +0000841 sb, i, b_bszW );
842 BOMB;
843 }
844 thisFree = !is_inuse_bszW(b_bszW);
845 if (thisFree && lastWasFree) {
nethercote885dd912004-08-03 23:14:00 +0000846 VG_(printf)("sanity_check_malloc_arena: sb %p, block %d (bszW %d): "
njn25e49d8e72002-09-23 09:36:25 +0000847 "UNMERGED FREES\n",
sewardjde4a1d02002-03-22 01:27:54 +0000848 sb, i, b_bszW );
849 BOMB;
850 }
851 lastWasFree = thisFree;
852 if (thisFree) blockctr_sb_free++;
853 if (!thisFree)
854 arena_bytes_on_loan += sizeof(Word) * bszW_to_pszW(a, b_bszW);
855 i += mk_plain_bszW(b_bszW);
856 }
857 if (i > sb->n_payload_words) {
nethercote885dd912004-08-03 23:14:00 +0000858 VG_(printf)( "sanity_check_malloc_arena: sb %p: last block "
sewardjde4a1d02002-03-22 01:27:54 +0000859 "overshoots end\n", sb);
860 BOMB;
861 }
862 sb = sb->next;
863 }
864
865 if (arena_bytes_on_loan != a->bytes_on_loan) {
866 VG_(printf)(
nethercote885dd912004-08-03 23:14:00 +0000867 "sanity_check_malloc_arena: a->bytes_on_loan %d, "
sewardjde4a1d02002-03-22 01:27:54 +0000868 "arena_bytes_on_loan %d: "
869 "MISMATCH\n", a->bytes_on_loan, arena_bytes_on_loan);
870 ppSuperblocks(a);
871 BOMB;
872 }
873
874 /* Second, traverse each list, checking that the back pointers make
875 sense, counting blocks encountered, and checking that each block
876 is an appropriate size for this list. */
877 blockctr_li = 0;
878 for (listno = 0; listno < VG_N_MALLOC_LISTS; listno++) {
879 list_min_pszW = listNo_to_pszW_min(listno);
880 list_max_pszW = listNo_to_pszW_max(listno);
881 b = a->freelist[listno];
882 if (b == NULL) continue;
883 while (True) {
884 b_prev = b;
885 b = get_next_p(b);
886 if (get_prev_p(b) != b_prev) {
nethercote885dd912004-08-03 23:14:00 +0000887 VG_(printf)( "sanity_check_malloc_arena: list %d at %p: "
sewardjde4a1d02002-03-22 01:27:54 +0000888 "BAD LINKAGE\n",
889 listno, b );
890 BOMB;
891 }
892 b_pszW = bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(b)));
893 if (b_pszW < list_min_pszW || b_pszW > list_max_pszW) {
894 VG_(printf)(
nethercote885dd912004-08-03 23:14:00 +0000895 "sanity_check_malloc_arena: list %d at %p: "
sewardjde4a1d02002-03-22 01:27:54 +0000896 "WRONG CHAIN SIZE %d (%d, %d)\n",
897 listno, b, b_pszW, list_min_pszW, list_max_pszW );
898 BOMB;
899 }
900 blockctr_li++;
901 if (b == a->freelist[listno]) break;
902 }
903 }
904
905 if (blockctr_sb_free != blockctr_li) {
906 VG_(printf)(
nethercote885dd912004-08-03 23:14:00 +0000907 "sanity_check_malloc_arena: BLOCK COUNT MISMATCH "
sewardjde4a1d02002-03-22 01:27:54 +0000908 "(via sbs %d, via lists %d)\n",
909 blockctr_sb_free, blockctr_li );
910 ppSuperblocks(a);
911 BOMB;
912 }
913
nethercote885dd912004-08-03 23:14:00 +0000914 if (VG_(clo_verbosity) > 2)
915 VG_(message)(Vg_DebugMsg,
916 "AR %8s: %2d sbs, %5d bs, %2d/%-2d free bs, "
917 "%7d mmap, %7d loan",
918 a->name,
919 superblockctr,
920 blockctr_sb, blockctr_sb_free, blockctr_li,
921 a->bytes_mmaped, a->bytes_on_loan);
sewardjde4a1d02002-03-22 01:27:54 +0000922# undef BOMB
923}
924
925
nethercote885dd912004-08-03 23:14:00 +0000926void VG_(sanity_check_malloc_all) ( void )
sewardjde4a1d02002-03-22 01:27:54 +0000927{
928 Int i;
929 for (i = 0; i < VG_N_ARENAS; i++)
nethercote885dd912004-08-03 23:14:00 +0000930 sanity_check_malloc_arena ( i );
sewardjde4a1d02002-03-22 01:27:54 +0000931}
932
933
934/* Really, this isn't the right place for this. Nevertheless: find
935 out if an arena is empty -- currently has no bytes on loan. This
936 is useful for checking for memory leaks (of valgrind, not the
937 client.)
938*/
939Bool VG_(is_empty_arena) ( ArenaId aid )
940{
941 Arena* a;
942 Superblock* sb;
943 WordF* b;
944 Int b_bszW;
njn25e49d8e72002-09-23 09:36:25 +0000945
sewardjde4a1d02002-03-22 01:27:54 +0000946 ensure_mm_init();
947 a = arenaId_to_ArenaP(aid);
948 for (sb = a->sblocks; sb != NULL; sb = sb->next) {
949 /* If the superblock is empty, it should contain a single free
950 block, of the right size. */
951 b = &(sb->payload_words[0]);
952 b_bszW = get_bszW_lo(b);
953 if (is_inuse_bszW(b_bszW)) return False;
954 if (mk_plain_bszW(b_bszW) != sb->n_payload_words) return False;
955 /* So this block is not in use and is of the right size. Keep
956 going. */
957 }
958 return True;
959}
960
961
jsewardb1a26ae2004-03-14 03:06:37 +0000962/* Turn a request size in bytes into a payload request size in
963 words. This means 8-aligning the request size.
964*/
965static __inline__
966Int req_pszB_to_req_pszW ( Int req_pszB )
967{
968 return ((req_pszB + 7) / 8) /* # of 64-bit units */
969 * 2; /* # of 32-bit units */
970}
971
972
sewardjde4a1d02002-03-22 01:27:54 +0000973/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000974/*--- Core-visible functions. ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000975/*------------------------------------------------------------*/
976
njn25e49d8e72002-09-23 09:36:25 +0000977void* VG_(arena_malloc) ( ArenaId aid, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +0000978{
979 Int req_pszW, req_bszW, frag_bszW, b_bszW, lno;
980 Superblock* new_sb;
981 Word* b;
982 Arena* a;
jsewardb1a26ae2004-03-14 03:06:37 +0000983 void* v;
sewardjde4a1d02002-03-22 01:27:54 +0000984
985 VGP_PUSHCC(VgpMalloc);
986
987 ensure_mm_init();
988 a = arenaId_to_ArenaP(aid);
989
990 vg_assert(req_pszB >= 0);
991 vg_assert(req_pszB < 0x7FFFFFF0);
992
jsewardb1a26ae2004-03-14 03:06:37 +0000993 req_pszW = req_pszB_to_req_pszW(req_pszB);
sewardjde4a1d02002-03-22 01:27:54 +0000994
995 /* Keep gcc -O happy: */
996 b = NULL;
997
998 /* Start searching at this list. */
999 lno = pszW_to_listNo(req_pszW);
1000
1001 /* This loop finds a list which has a block big enough, or sets
1002 req_listno to N_LISTS if no such block exists. */
1003 while (True) {
1004 if (lno == VG_N_MALLOC_LISTS) break;
1005 /* If this list is empty, try the next one. */
1006 if (a->freelist[lno] == NULL) {
1007 lno++;
1008 continue;
1009 }
1010 /* Scan a->list[lno] to find a big-enough chunk. */
1011 b = a->freelist[lno];
1012 b_bszW = mk_plain_bszW(get_bszW_lo(b));
1013 while (True) {
1014 if (bszW_to_pszW(a, b_bszW) >= req_pszW) break;
1015 b = get_next_p(b);
1016 b_bszW = mk_plain_bszW(get_bszW_lo(b));
1017 if (b == a->freelist[lno]) break;
1018 }
1019 if (bszW_to_pszW(a, b_bszW) >= req_pszW) break;
1020 /* No luck? Try a larger list. */
1021 lno++;
1022 }
1023
1024 /* Either lno < VG_N_MALLOC_LISTS and b points to the selected
1025 block, or lno == VG_N_MALLOC_LISTS, and we have to allocate a
1026 new superblock. */
1027
1028 if (lno == VG_N_MALLOC_LISTS) {
1029 req_bszW = pszW_to_bszW(a, req_pszW);
1030 new_sb = newSuperblock(a, req_bszW);
nethercote57e36b32004-07-10 14:56:28 +00001031 if (NULL == new_sb) {
1032 // Should only fail if for client, otherwise, should have aborted
1033 // already.
1034 vg_assert(VG_AR_CLIENT == aid);
1035 return NULL;
1036 }
sewardjde4a1d02002-03-22 01:27:54 +00001037 new_sb->next = a->sblocks;
1038 a->sblocks = new_sb;
1039 b = &(new_sb->payload_words[0]);
1040 lno = pszW_to_listNo(bszW_to_pszW(a, new_sb->n_payload_words));
1041 mkFreeBlock ( a, b, new_sb->n_payload_words, lno);
1042 }
1043
1044 /* Ok, we can allocate from b, which lives in list req_listno. */
1045 vg_assert(b != NULL);
1046 vg_assert(lno >= 0 && lno < VG_N_MALLOC_LISTS);
1047 vg_assert(a->freelist[lno] != NULL);
1048 b_bszW = mk_plain_bszW(get_bszW_lo(b));
1049 req_bszW = pszW_to_bszW(a, req_pszW);
1050 /* req_bszW is the size of the block we are after. b_bszW is the
1051 size of what we've actually got. */
1052 vg_assert(b_bszW >= req_bszW);
1053
1054 /* Could we split this block and still get a useful fragment?
1055 Where "useful" means that the payload size of the frag is at
1056 least one word. */
1057 frag_bszW = b_bszW - req_bszW;
1058 if (frag_bszW > overhead_szW(a)) {
1059 splitChunk(a, b, lno, req_bszW);
1060 } else {
1061 /* No, mark as in use and use as-is. */
1062 unlinkBlock(a, b, lno);
1063 /*
1064 set_bszW_lo(b, mk_inuse_bszW(b_bszW));
1065 set_bszW_hi(b, mk_inuse_bszW(b_bszW));
1066 */
1067 mkInuseBlock(a, b, b_bszW);
1068 }
1069 vg_assert(req_bszW <= mk_plain_bszW(get_bszW_lo(b)));
1070
1071 a->bytes_on_loan
1072 += sizeof(Word)
1073 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(b)));
1074 if (a->bytes_on_loan > a->bytes_on_loan_max)
1075 a->bytes_on_loan_max = a->bytes_on_loan;
1076
1077# ifdef DEBUG_MALLOC
nethercote885dd912004-08-03 23:14:00 +00001078 sanity_check_malloc_arena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001079# endif
1080
njn25e49d8e72002-09-23 09:36:25 +00001081 VGP_POPCC(VgpMalloc);
jsewardb1a26ae2004-03-14 03:06:37 +00001082 v = first_to_payload(a, b);
1083 vg_assert( (((UInt)v) & 7) == 0 );
1084 return v;
sewardjde4a1d02002-03-22 01:27:54 +00001085}
1086
1087
njn25e49d8e72002-09-23 09:36:25 +00001088void VG_(arena_free) ( ArenaId aid, void* ptr )
sewardjde4a1d02002-03-22 01:27:54 +00001089{
1090 Superblock* sb;
1091 UInt* sb_payl_firstw;
1092 UInt* sb_payl_lastw;
1093 UInt* other;
1094 UInt* ch;
1095 Int ch_bszW, ch_pszW, other_bszW, ch_listno;
1096 Arena* a;
1097
1098 VGP_PUSHCC(VgpMalloc);
1099
1100 ensure_mm_init();
1101 a = arenaId_to_ArenaP(aid);
1102
njn25e49d8e72002-09-23 09:36:25 +00001103 if (ptr == NULL) {
1104 VGP_POPCC(VgpMalloc);
1105 return;
1106 }
1107
sewardjde4a1d02002-03-22 01:27:54 +00001108 ch = payload_to_first(a, ptr);
1109
1110# ifdef DEBUG_MALLOC
1111 vg_assert(blockSane(a,ch));
1112# endif
1113
1114 a->bytes_on_loan
1115 -= sizeof(Word)
1116 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(ch)));
1117
1118 sb = findSb( a, ch );
1119 sb_payl_firstw = &(sb->payload_words[0]);
1120 sb_payl_lastw = &(sb->payload_words[sb->n_payload_words-1]);
1121
1122 /* Put this chunk back on a list somewhere. */
1123 ch_bszW = get_bszW_lo(ch);
1124 ch_pszW = bszW_to_pszW(a, ch_bszW);
1125 ch_listno = pszW_to_listNo(ch_pszW);
1126 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1127
1128 /* See if this block can be merged with the following one. */
1129 other = ch + ch_bszW;
1130 /* overhead_szW(a) is the smallest possible bszW for this arena.
1131 So the nearest possible end to the block beginning at other is
1132 other+overhead_szW(a)-1. Hence the test below. */
1133 if (other+overhead_szW(a)-1 <= sb_payl_lastw) {
1134 other_bszW = get_bszW_lo(other);
1135 if (!is_inuse_bszW(other_bszW)) {
1136 /* VG_(printf)( "merge-successor\n"); */
1137 other_bszW = mk_plain_bszW(other_bszW);
1138# ifdef DEBUG_MALLOC
1139 vg_assert(blockSane(a, other));
1140# endif
1141 unlinkBlock( a, ch, ch_listno );
1142 unlinkBlock( a, other, pszW_to_listNo(bszW_to_pszW(a,other_bszW)) );
1143 ch_bszW += other_bszW;
1144 ch_listno = pszW_to_listNo(bszW_to_pszW(a, ch_bszW));
1145 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1146 }
1147 }
1148
1149 /* See if this block can be merged with its predecessor. */
1150 if (ch-overhead_szW(a) >= sb_payl_firstw) {
1151 other_bszW = get_bszW_hi_from_last_word( ch-1 );
1152 if (!is_inuse_bszW(other_bszW)) {
1153 /* VG_(printf)( "merge-predecessor\n"); */
1154 other = last_to_first( ch-1 );
1155 other_bszW = mk_plain_bszW(other_bszW);
1156 unlinkBlock( a, ch, ch_listno );
1157 unlinkBlock( a, other, pszW_to_listNo(bszW_to_pszW(a, other_bszW)) );
1158 ch = other;
1159 ch_bszW += other_bszW;
1160 ch_listno = pszW_to_listNo(bszW_to_pszW(a, ch_bszW));
1161 mkFreeBlock( a, ch, ch_bszW, ch_listno );
1162 }
1163 }
1164
1165# ifdef DEBUG_MALLOC
nethercote885dd912004-08-03 23:14:00 +00001166 sanity_check_malloc_arena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001167# endif
1168
njn25e49d8e72002-09-23 09:36:25 +00001169 VGP_POPCC(VgpMalloc);
sewardjde4a1d02002-03-22 01:27:54 +00001170}
1171
1172
1173/*
1174 The idea for malloc_aligned() is to allocate a big block, base, and
1175 then split it into two parts: frag, which is returned to the the
1176 free pool, and align, which is the bit we're really after. Here's
1177 a picture. L and H denote the block lower and upper overheads, in
1178 words. The details are gruesome. Note it is slightly complicated
1179 because the initial request to generate base may return a bigger
1180 block than we asked for, so it is important to distinguish the base
1181 request size and the base actual size.
1182
1183 frag_b align_b
1184 | |
1185 | frag_p | align_p
1186 | | | |
1187 v v v v
1188
1189 +---+ +---+---+ +---+
1190 | L |----------------| H | L |---------------| H |
1191 +---+ +---+---+ +---+
1192
1193 ^ ^ ^
1194 | | :
1195 | base_p this addr must be aligned
1196 |
1197 base_b
1198
1199 . . . . . . .
1200 <------ frag_bszW -------> . . .
1201 . <------------- base_pszW_act -----------> .
1202 . . . . . . .
1203
1204*/
njn25e49d8e72002-09-23 09:36:25 +00001205void* VG_(arena_malloc_aligned) ( ArenaId aid, Int req_alignB, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +00001206{
1207 Int req_alignW, req_pszW, base_pszW_req, base_pszW_act, frag_bszW;
1208 Word *base_b, *base_p, *align_p;
1209 UInt saved_bytes_on_loan;
1210 Arena* a;
jsewardb1a26ae2004-03-14 03:06:37 +00001211 void* v;
sewardjde4a1d02002-03-22 01:27:54 +00001212
njn25e49d8e72002-09-23 09:36:25 +00001213 VGP_PUSHCC(VgpMalloc);
1214
sewardjde4a1d02002-03-22 01:27:54 +00001215 ensure_mm_init();
1216 a = arenaId_to_ArenaP(aid);
1217
1218 vg_assert(req_pszB >= 0);
1219 vg_assert(req_pszB < 0x7FFFFFF0);
1220
1221 /* Check that the requested alignment seems reasonable; that is, is
sewardjb5045ef2002-06-04 16:48:29 +00001222 a power of 2. */
sewardjde4a1d02002-03-22 01:27:54 +00001223 switch (req_alignB) {
sewardjc76be292002-04-24 20:32:50 +00001224 case 4:
sewardjde4a1d02002-03-22 01:27:54 +00001225 case 8: case 16: case 32: case 64: case 128: case 256:
1226 case 512: case 1024: case 2048: case 4096: case 8192:
1227 case 16384: case 32768: case 65536: case 131072:
sewardjb5045ef2002-06-04 16:48:29 +00001228 case 262144:
sewardjde4a1d02002-03-22 01:27:54 +00001229 case 1048576:
1230 /* can't be bothered to calculate larger ones */
1231 break;
1232 default:
1233 VG_(printf)("vg_malloc_aligned(%p, %d, %d)\nbad alignment request",
njn25e49d8e72002-09-23 09:36:25 +00001234 a, req_alignB, req_pszB );
njne427a662002-10-02 11:08:25 +00001235 VG_(core_panic)("vg_malloc_aligned");
sewardjde4a1d02002-03-22 01:27:54 +00001236 /*NOTREACHED*/
1237 }
1238
1239 /* Required alignment, in words. Since it's constrained to be a
1240 power of 2 >= word size, no need to align the alignment. Still,
1241 we check. */
jsewardb1a26ae2004-03-14 03:06:37 +00001242 if (req_alignB == 4) req_alignB = 8;
sewardjde4a1d02002-03-22 01:27:54 +00001243 req_alignW = req_alignB / VKI_BYTES_PER_WORD;
1244 vg_assert(req_alignB == req_alignW * VKI_BYTES_PER_WORD);
1245
1246 /* Required payload size for the aligned chunk. */
jsewardb1a26ae2004-03-14 03:06:37 +00001247 req_pszW = req_pszB_to_req_pszW(req_pszB);
sewardjde4a1d02002-03-22 01:27:54 +00001248
1249 /* Payload size to request for the big block that we will split
1250 up. */
1251 base_pszW_req = req_pszW + overhead_szW(a) + req_alignW;
1252
1253 /* Payload ptr for the block we are going to split. Note this
1254 changes a->bytes_on_loan; we save and restore it ourselves. */
1255 saved_bytes_on_loan = a->bytes_on_loan;
njn25e49d8e72002-09-23 09:36:25 +00001256 base_p = VG_(arena_malloc) ( aid, base_pszW_req * VKI_BYTES_PER_WORD );
sewardjde4a1d02002-03-22 01:27:54 +00001257 a->bytes_on_loan = saved_bytes_on_loan;
1258
1259 /* Block ptr for the block we are going to split. */
1260 base_b = payload_to_first ( a, base_p );
1261
1262 /* Pointer to the payload of the aligned block we are going to
1263 return. This has to be suitably aligned. */
1264 align_p = align_upwards ( base_b + 2 * overhead_szW_lo(a)
1265 + overhead_szW_hi(a),
1266 req_alignB );
1267
1268 /* The block size of the fragment we will create. This must be big
1269 enough to actually create a fragment. */
1270 frag_bszW = align_p - overhead_szW_lo(a) - base_b;
1271 vg_assert(frag_bszW >= overhead_szW(a));
1272
1273 /* The actual payload size of the block we are going to split. */
1274 base_pszW_act = bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(base_b)));
1275
1276 /* Create the fragment block, and put it back on the relevant free
1277 list. */
1278 mkFreeBlock ( a, base_b, frag_bszW,
1279 pszW_to_listNo(bszW_to_pszW(a, frag_bszW)) );
1280
1281 /* Create the aligned block. */
1282 mkInuseBlock ( a,
1283 align_p - overhead_szW_lo(a),
1284 base_p + base_pszW_act
1285 + overhead_szW_hi(a)
1286 - (align_p - overhead_szW_lo(a)) );
1287
1288 /* Final sanity checks. */
1289 vg_assert(( (UInt)align_p % req_alignB) == 0);
1290
1291 vg_assert(is_inuse_bszW(get_bszW_lo(payload_to_first(a, align_p))));
1292
1293 vg_assert(req_pszW
1294 <=
1295 bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(
1296 payload_to_first(a, align_p))))
1297 );
1298
1299 a->bytes_on_loan
1300 += sizeof(Word)
1301 * bszW_to_pszW(a, mk_plain_bszW(get_bszW_lo(
1302 payload_to_first(a, align_p))));
1303 if (a->bytes_on_loan > a->bytes_on_loan_max)
1304 a->bytes_on_loan_max = a->bytes_on_loan;
1305
1306# ifdef DEBUG_MALLOC
nethercote885dd912004-08-03 23:14:00 +00001307 sanity_check_malloc_arena(aid);
sewardjde4a1d02002-03-22 01:27:54 +00001308# endif
1309
njn25e49d8e72002-09-23 09:36:25 +00001310 VGP_POPCC(VgpMalloc);
1311
jsewardb1a26ae2004-03-14 03:06:37 +00001312 v = (void*)align_p;
1313 vg_assert( (((UInt)v) % req_alignB) == 0 );
1314 return v;
sewardjde4a1d02002-03-22 01:27:54 +00001315}
1316
1317
1318/*------------------------------------------------------------*/
1319/*--- Services layered on top of malloc/free. ---*/
1320/*------------------------------------------------------------*/
1321
njn3e884182003-04-15 13:03:23 +00001322void* VG_(arena_calloc) ( ArenaId aid, Int alignB, Int nmemb, Int nbytes )
sewardjde4a1d02002-03-22 01:27:54 +00001323{
1324 Int i, size;
1325 UChar* p;
njn25e49d8e72002-09-23 09:36:25 +00001326
1327 VGP_PUSHCC(VgpMalloc);
1328
sewardjde4a1d02002-03-22 01:27:54 +00001329 size = nmemb * nbytes;
sewardjd0b9ac32002-05-01 00:10:28 +00001330 vg_assert(size >= 0);
njn3e884182003-04-15 13:03:23 +00001331
jsewardb1a26ae2004-03-14 03:06:37 +00001332 if (alignB == 8)
njn3e884182003-04-15 13:03:23 +00001333 p = VG_(arena_malloc) ( aid, size );
1334 else
1335 p = VG_(arena_malloc_aligned) ( aid, alignB, size );
1336
sewardjde4a1d02002-03-22 01:27:54 +00001337 for (i = 0; i < size; i++) p[i] = 0;
njn25e49d8e72002-09-23 09:36:25 +00001338
1339 VGP_POPCC(VgpMalloc);
1340
sewardjde4a1d02002-03-22 01:27:54 +00001341 return p;
1342}
1343
1344
njn25e49d8e72002-09-23 09:36:25 +00001345void* VG_(arena_realloc) ( ArenaId aid, void* ptr,
jsewardb1a26ae2004-03-14 03:06:37 +00001346 Int req_alignB, Int req_pszB )
sewardjde4a1d02002-03-22 01:27:54 +00001347{
1348 Arena* a;
1349 Int old_bszW, old_pszW, old_pszB, i;
1350 UChar *p_old, *p_new;
1351 UInt* ch;
1352
njn25e49d8e72002-09-23 09:36:25 +00001353 VGP_PUSHCC(VgpMalloc);
1354
sewardjde4a1d02002-03-22 01:27:54 +00001355 ensure_mm_init();
1356 a = arenaId_to_ArenaP(aid);
1357
1358 vg_assert(req_pszB >= 0);
1359 vg_assert(req_pszB < 0x7FFFFFF0);
1360
1361 ch = payload_to_first(a, ptr);
1362 vg_assert(blockSane(a, ch));
1363
1364 old_bszW = get_bszW_lo(ch);
1365 vg_assert(is_inuse_bszW(old_bszW));
1366 old_bszW = mk_plain_bszW(old_bszW);
1367 old_pszW = bszW_to_pszW(a, old_bszW);
1368 old_pszB = old_pszW * VKI_BYTES_PER_WORD;
1369
njn25e49d8e72002-09-23 09:36:25 +00001370 if (req_pszB <= old_pszB) {
1371 VGP_POPCC(VgpMalloc);
1372 return ptr;
1373 }
sewardjde4a1d02002-03-22 01:27:54 +00001374
jsewardb1a26ae2004-03-14 03:06:37 +00001375 if (req_alignB == 8)
njn25e49d8e72002-09-23 09:36:25 +00001376 p_new = VG_(arena_malloc) ( aid, req_pszB );
1377 else
1378 p_new = VG_(arena_malloc_aligned) ( aid, req_alignB, req_pszB );
1379
sewardjde4a1d02002-03-22 01:27:54 +00001380 p_old = (UChar*)ptr;
1381 for (i = 0; i < old_pszB; i++)
1382 p_new[i] = p_old[i];
1383
njn25e49d8e72002-09-23 09:36:25 +00001384 VG_(arena_free)(aid, p_old);
1385
1386 VGP_POPCC(VgpMalloc);
sewardjde4a1d02002-03-22 01:27:54 +00001387 return p_new;
1388}
1389
1390
1391/*------------------------------------------------------------*/
nethercote996901a2004-08-03 13:29:09 +00001392/*--- Tool-visible functions. ---*/
njn25e49d8e72002-09-23 09:36:25 +00001393/*------------------------------------------------------------*/
1394
nethercote7cc9c232004-01-21 15:08:04 +00001395/* All just wrappers to avoid exposing arenas to tools */
njn25e49d8e72002-09-23 09:36:25 +00001396
1397void* VG_(malloc) ( Int nbytes )
1398{
nethercote60f5b822004-01-26 17:24:42 +00001399 return VG_(arena_malloc) ( VG_AR_TOOL, nbytes );
njn25e49d8e72002-09-23 09:36:25 +00001400}
1401
1402void VG_(free) ( void* ptr )
1403{
nethercote60f5b822004-01-26 17:24:42 +00001404 VG_(arena_free) ( VG_AR_TOOL, ptr );
njn25e49d8e72002-09-23 09:36:25 +00001405}
1406
1407void* VG_(calloc) ( Int nmemb, Int nbytes )
1408{
jsewardb1a26ae2004-03-14 03:06:37 +00001409 return VG_(arena_calloc) ( VG_AR_TOOL, /*alignment*/8, nmemb, nbytes );
njn25e49d8e72002-09-23 09:36:25 +00001410}
1411
1412void* VG_(realloc) ( void* ptr, Int size )
1413{
jsewardb1a26ae2004-03-14 03:06:37 +00001414 return VG_(arena_realloc) ( VG_AR_TOOL, ptr, /*alignment*/8, size );
njn25e49d8e72002-09-23 09:36:25 +00001415}
1416
1417void* VG_(malloc_aligned) ( Int req_alignB, Int req_pszB )
1418{
nethercote60f5b822004-01-26 17:24:42 +00001419 return VG_(arena_malloc_aligned) ( VG_AR_TOOL, req_alignB, req_pszB );
njn25e49d8e72002-09-23 09:36:25 +00001420}
1421
1422
njn3e884182003-04-15 13:03:23 +00001423void* VG_(cli_malloc) ( UInt align, Int nbytes )
1424{
jsewardb1a26ae2004-03-14 03:06:37 +00001425 vg_assert(align >= 8);
1426 if (8 == align)
njn3e884182003-04-15 13:03:23 +00001427 return VG_(arena_malloc) ( VG_AR_CLIENT, nbytes );
1428 else
sewardjf1accbc2003-07-12 01:26:52 +00001429 return VG_(arena_malloc_aligned) ( VG_AR_CLIENT, align, nbytes );
njn3e884182003-04-15 13:03:23 +00001430}
1431
1432void VG_(cli_free) ( void* p )
1433{
1434 VG_(arena_free) ( VG_AR_CLIENT, p );
1435}
1436
1437
1438Bool VG_(addr_is_in_block)( Addr a, Addr start, UInt size )
1439{
1440 return (start - VG_(vg_malloc_redzone_szB) <= a
1441 && a < start + size + VG_(vg_malloc_redzone_szB));
1442}
1443
1444
njn25e49d8e72002-09-23 09:36:25 +00001445/*------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00001446/*--- The original test driver machinery. ---*/
1447/*------------------------------------------------------------*/
1448
1449#if 0
1450
1451#if 1
1452#define N_TEST_TRANSACTIONS 100000000
1453#define N_TEST_ARR 200000
1454#define M_TEST_MALLOC 1000
1455#else
1456#define N_TEST_TRANSACTIONS 500000
1457#define N_TEST_ARR 30000
1458#define M_TEST_MALLOC 500
1459#endif
1460
1461
1462void* test_arr[N_TEST_ARR];
1463
1464int main ( int argc, char** argv )
1465{
1466 Int i, j, k, nbytes, qq;
1467 unsigned char* chp;
njn25e49d8e72002-09-23 09:36:25 +00001468 Arena* a = &arena[VG_AR_CORE];
sewardjde4a1d02002-03-22 01:27:54 +00001469 srandom(1);
1470 for (i = 0; i < N_TEST_ARR; i++)
1471 test_arr[i] = NULL;
1472
1473 for (i = 0; i < N_TEST_TRANSACTIONS; i++) {
1474 if (i % 50000 == 0) mallocSanityCheck(a);
1475 j = random() % N_TEST_ARR;
1476 if (test_arr[j]) {
1477 vg_free(a, test_arr[j]);
1478 test_arr[j] = NULL;
1479 } else {
1480 nbytes = 1 + random() % M_TEST_MALLOC;
1481 qq = random()%64;
1482 if (qq == 32)
1483 nbytes *= 17;
1484 else if (qq == 33)
1485 nbytes = 0;
1486 test_arr[j]
1487 = (i % 17) == 0
1488 ? vg_memalign(a, nbytes, 1<< (3+(random()%10)))
1489 : vg_malloc( a, nbytes );
1490 chp = test_arr[j];
1491 for (k = 0; k < nbytes; k++)
1492 chp[k] = (unsigned char)(k + 99);
1493 }
1494 }
1495
1496
1497 for (i = 0; i < N_TEST_ARR; i++) {
1498 if (test_arr[i]) {
1499 vg_free(a, test_arr[i]);
1500 test_arr[i] = NULL;
1501 }
1502 }
1503 mallocSanityCheck(a);
1504
1505 fprintf(stderr, "ALL DONE\n");
1506
1507 show_arena_stats(a);
1508 fprintf(stderr, "%d max useful, %d bytes mmap'd (%4.1f%%), %d useful\n",
1509 a->bytes_on_loan_max,
1510 a->bytes_mmaped,
1511 100.0 * (double)a->bytes_on_loan_max / (double)a->bytes_mmaped,
1512 a->bytes_on_loan );
1513
1514 return 0;
1515}
1516#endif /* 0 */
1517
1518
1519/*--------------------------------------------------------------------*/
1520/*--- end vg_malloc2.c ---*/
1521/*--------------------------------------------------------------------*/