1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- An implementation of malloc/free which doesn't use sbrk. ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- m_mallocfree.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2000-2012 Julian Seward 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" // For VG_INVALID_THREADID 43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_transtab.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_tool_inner.h" 47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#if defined(ENABLE_INNER_CLIENT_REQUEST) 48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "memcheck/memcheck.h" 49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// #define DEBUG_MALLOC // turn on heavyweight debugging machinery 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// #define VERBOSE_MALLOC // make verbose, esp. in debugging machinery 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Number and total size of blocks in free queue. Used by mallinfo(). */ 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLong VG_(free_queue_volume) = 0; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLong VG_(free_queue_length) = 0; 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cc_analyse_alloc_arena ( ArenaId aid ); /* fwds */ 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Main types ---*/ 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_MALLOC_LISTS 112 // do not change this 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The amount you can ask for is limited only by sizeof(SizeT)... 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAX_PSZB (~((SizeT)0x0)) 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Each arena has a sorted array of superblocks, which expands 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// dynamically. This is its initial size. 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SBLOCKS_SIZE_INITIAL 50 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef UChar UByte; 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Layout of an in-use block: 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost center (OPTIONAL) (VG_MIN_MALLOC_SZB bytes, only when h-p enabled) 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this block total szB (sizeof(SizeT) bytes) 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown red zone bytes (depends on Arena.rz_szB, but >= sizeof(void*)) 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (payload bytes) 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown red zone bytes (depends on Arena.rz_szB, but >= sizeof(void*)) 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this block total szB (sizeof(SizeT) bytes) 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Layout of a block on the free list: 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cost center (OPTIONAL) (VG_MIN_MALLOC_SZB bytes, only when h-p enabled) 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this block total szB (sizeof(SizeT) bytes) 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown freelist previous ptr (sizeof(void*) bytes) 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown excess red zone bytes (if Arena.rz_szB > sizeof(void*)) 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (payload bytes) 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown excess red zone bytes (if Arena.rz_szB > sizeof(void*)) 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown freelist next ptr (sizeof(void*) bytes) 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this block total szB (sizeof(SizeT) bytes) 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Total size in bytes (bszB) and payload size in bytes (pszB) 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are related by: 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bszB == pszB + 2*sizeof(SizeT) + 2*a->rz_szB 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when heap profiling is not enabled, and 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bszB == pszB + 2*sizeof(SizeT) + 2*a->rz_szB + VG_MIN_MALLOC_SZB 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when it is enabled. It follows that the minimum overhead per heap 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block for arenas used by the core is: 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32-bit platforms: 2*4 + 2*4 == 16 bytes 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64-bit platforms: 2*8 + 2*8 == 32 bytes 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when heap profiling is not enabled, and 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32-bit platforms: 2*4 + 2*4 + 8 == 24 bytes 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64-bit platforms: 2*8 + 2*8 + 16 == 48 bytes 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when it is enabled. In all cases, extra overhead may be incurred 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when rounding the payload size up to VG_MIN_MALLOC_SZB. 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Furthermore, both size fields in the block have their least-significant 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bit set if the block is not in use, and unset if it is in use. 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (The bottom 3 or so bits are always free for this because of alignment.) 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A block size of zero is not possible, because a block always has at 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown least two SizeTs and two pointers of overhead. 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Nb: All Block payloads must be VG_MIN_MALLOC_SZB-aligned. This is 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown achieved by ensuring that Superblocks are VG_MIN_MALLOC_SZB-aligned 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (see newSuperblock() for how), and that the lengths of the following 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown things are a multiple of VG_MIN_MALLOC_SZB: 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Superblock admin section lengths (due to elastic padding) 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Block admin section (low and high) lengths (due to elastic redzones) 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Block payload lengths (due to req_pszB rounding up) 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The heap-profile cost-center field is 8 bytes even on 32 bit 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platforms. This is so as to keep the payload field 8-aligned. On 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a 64-bit platform, this cc-field contains a pointer to a const 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar*, which is the cost center name. On 32-bit platforms, the 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pointer lives in the lower-addressed half of the field, regardless 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the endianness of the host. 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // No fields are actually used in this struct, because a Block has 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // many variable sized fields and so can't be accessed 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // meaningfully with normal fields. So we use access functions all 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // the time. This struct gives us a type to use, though. Also, we 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // make sizeof(Block) 1 byte so that we can do arithmetic with the 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Block* type in increments of 1! 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte dummy; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block; 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A superblock. 'padding' is never used, it just ensures that if the 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// entire Superblock is aligned to VG_MIN_MALLOC_SZB, then payload_bytes[] 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// will be too. It can add small amounts of padding unnecessarily -- eg. 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 8-bytes on 32-bit machines with an 8-byte VG_MIN_MALLOC_SZB -- because 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// it's too hard to make a constant expression that works perfectly in all 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// cases. 157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// 'unsplittable' is set to NULL if superblock can be splitted, otherwise 158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// it is set to the address of the superblock. An unsplittable superblock 159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// will contain only one allocated block. An unsplittable superblock will 160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// be unmapped when its (only) allocated block is freed. 161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// The free space at the end of an unsplittable superblock is not used to 162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// make a free block. Note that this means that an unsplittable superblock can 163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// have up to slightly less than 1 page of unused bytes at the end of the 164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// superblock. 165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// 'unsplittable' is used to avoid quadratic memory usage for linear 166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// reallocation of big structures 167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// (see http://bugs.kde.org/show_bug.cgi?id=250101). 168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// ??? unsplittable replaces 'void *padding2'. Choosed this 169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// ??? to avoid changing the alignment logic. Maybe something cleaner 170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// ??? can be done. 171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// A splittable block can be reclaimed when all its blocks are freed : 172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// the reclaim of such a block is deferred till either another superblock 173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// of the same arena can be reclaimed or till a new superblock is needed 174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// in any arena. 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// payload_bytes[] is made a single big Block when the Superblock is 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// created, and then can be split and the splittings remerged, but Blocks 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// always cover its entire length -- there's never any unused bytes at the 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// end, for example. 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct _Superblock { 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT n_payload_bytes; 182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov struct _Superblock* unsplittable; 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte padding[ VG_MIN_MALLOC_SZB - 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ((sizeof(struct _Superblock*) + sizeof(SizeT)) % 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_MIN_MALLOC_SZB) ]; 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte payload_bytes[0]; 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// An arena. 'freelist' is a circular, doubly-linked list. 'rz_szB' is 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// elastic, in that it can be bigger than asked-for to ensure alignment. 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* name; 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool clientmem; // Allocates in the client address space? 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT rz_szB; // Red zone size in bytes 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT min_sblock_szB; // Minimum superblock size in bytes 198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT min_unsplittable_sblock_szB; 199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Minimum unsplittable superblock size in bytes. To be marked as 200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // unsplittable, a superblock must have a 201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // size >= min_unsplittable_sblock_szB and cannot be splitted. 202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // So, to avoid big overhead, superblocks used to provide aligned 203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // blocks on big alignments are splittable. 204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Unsplittable superblocks will be reclaimed when their (only) 205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // allocated block is freed. 206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Smaller size superblocks are splittable and can be reclaimed when all 207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // their blocks are freed. 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* freelist[N_MALLOC_LISTS]; 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // A dynamically expanding, ordered array of (pointers to) 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // superblocks in the arena. If this array is expanded, which 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // is rare, the previous space it occupies is simply abandoned. 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // To avoid having to get yet another block from m_aspacemgr for 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // the first incarnation of this array, the first allocation of 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // it is within this struct. If it has to be expanded then the 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // new space is acquired from m_aspacemgr as you would expect. 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock** sblocks; 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT sblocks_size; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT sblocks_used; 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock* sblocks_initial[SBLOCKS_SIZE_INITIAL]; 220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Superblock* deferred_reclaimed_sb; 221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Stats only. 223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ULong stats__nreclaim_unsplit; 224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ULong stats__nreclaim_split; 225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* total # of reclaim executed for unsplittable/splittable superblocks */ 226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT stats__bytes_on_loan; 227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT stats__bytes_mmaped; 228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT stats__bytes_on_loan_max; 229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ULong stats__tot_blocks; /* total # blocks alloc'd */ 230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ULong stats__tot_bytes; /* total # bytes alloc'd */ 231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ULong stats__nsearches; /* total # freelist checks */ 232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // If profiling, when should the next profile happen at 233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // (in terms of stats__bytes_on_loan_max) ? 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT next_profile_at; 235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT stats__bytes_mmaped_max; 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena; 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Low-level functions for working with Blocks. ---*/ 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SIZE_T_0x1 ((SizeT)0x1) 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char* probably_your_fault = 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "This is probably caused by your program erroneously writing past the\n" 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "end of a heap block and corrupting heap metadata. If you fix any\n" 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "invalid writes reported by Memcheck, this assertion failure will\n" 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "probably go away. Please try that before reporting this as a bug.\n"; 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Mark a bszB as in-use, and not in-use, and remove the in-use attribute. 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT mk_inuse_bszB ( SizeT bszB ) 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(bszB != 0, probably_your_fault); 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return bszB & (~SIZE_T_0x1); 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT mk_free_bszB ( SizeT bszB ) 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(bszB != 0, probably_your_fault); 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return bszB | SIZE_T_0x1; 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT mk_plain_bszB ( SizeT bszB ) 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(bszB != 0, probably_your_fault); 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return bszB & (~SIZE_T_0x1); 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Forward definition. 273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic 274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid ensure_mm_init ( ArenaId aid ); 275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// return either 0 or sizeof(ULong) depending on whether or not 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// heap profiling is engaged 278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define hp_overhead_szB() set_at_init_hp_overhead_szB 279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic SizeT set_at_init_hp_overhead_szB = -1000000; 280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// startup value chosen to very likely cause a problem if used before 281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// a proper value is given by ensure_mm_init. 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Get a block's size as stored, ie with the in-use/free attribute. 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT get_bszB_as_is ( Block* b ) 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT bszB_lo = *(SizeT*)&b2[0 + hp_overhead_szB()]; 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT bszB_hi = *(SizeT*)&b2[mk_plain_bszB(bszB_lo) - sizeof(SizeT)]; 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(bszB_lo == bszB_hi, 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Heap block lo/hi size mismatch: lo = %llu, hi = %llu.\n%s", 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)bszB_lo, (ULong)bszB_hi, probably_your_fault); 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return bszB_lo; 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Get a block's plain size, ie. remove the in-use/free attribute. 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT get_bszB ( Block* b ) 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mk_plain_bszB(get_bszB_as_is(b)); 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Set the size fields of a block. bszB may have the in-use/free attribute. 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_bszB ( Block* b, SizeT bszB ) 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *(SizeT*)&b2[0 + hp_overhead_szB()] = bszB; 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *(SizeT*)&b2[mk_plain_bszB(bszB) - sizeof(SizeT)] = bszB; 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Does this block have the in-use attribute? 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool is_inuse_block ( Block* b ) 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT bszB = get_bszB_as_is(b); 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(bszB != 0, probably_your_fault); 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (0 != (bszB & SIZE_T_0x1)) ? False : True; 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Return the lower, upper and total overhead in bytes for a block. 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// These are determined purely by which arena the block lives in. 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT overhead_szB_lo ( Arena* a ) 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return hp_overhead_szB() + sizeof(SizeT) + a->rz_szB; 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT overhead_szB_hi ( Arena* a ) 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return a->rz_szB + sizeof(SizeT); 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT overhead_szB ( Arena* a ) 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return overhead_szB_lo(a) + overhead_szB_hi(a); 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Return the minimum bszB for a block in this arena. Can have zero-length 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// payloads, so it's the size of the admin bytes. 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT min_useful_bszB ( Arena* a ) 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return overhead_szB(a); 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Convert payload size <--> block size (both in bytes). 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT pszB_to_bszB ( Arena* a, SizeT pszB ) 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pszB + overhead_szB(a); 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT bszB_to_pszB ( Arena* a, SizeT bszB ) 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(bszB >= overhead_szB(a), probably_your_fault); 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return bszB - overhead_szB(a); 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Get a block's payload size. 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT get_pszB ( Arena* a, Block* b ) 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return bszB_to_pszB(a, get_bszB(b)); 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Given the addr of a block, return the addr of its payload, and vice versa. 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUByte* get_block_payload ( Arena* a, Block* b ) 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return & b2[ overhead_szB_lo(a) ]; 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Given the addr of a block's payload, return the addr of the block itself. 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBlock* get_payload_block ( Arena* a, UByte* payload ) 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (Block*)&payload[ -overhead_szB_lo(a) ]; 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Set and get the next and previous link fields of a block. 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_prev_b ( Block* b, Block* prev_p ) 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *(Block**)&b2[hp_overhead_szB() + sizeof(SizeT)] = prev_p; 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_next_b ( Block* b, Block* next_p ) 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *(Block**)&b2[get_bszB(b) - sizeof(SizeT) - sizeof(void*)] = next_p; 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBlock* get_prev_b ( Block* b ) 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return *(Block**)&b2[hp_overhead_szB() + sizeof(SizeT)]; 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBlock* get_next_b ( Block* b ) 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return *(Block**)&b2[get_bszB(b) - sizeof(SizeT) - sizeof(void*)]; 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Set and get the cost-center field of a block. 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_cc ( Block* b, HChar* cc ) 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(clo_profile_heap) ); 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *(HChar**)&b2[0] = cc; 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* get_cc ( Block* b ) 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(clo_profile_heap) ); 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return *(HChar**)&b2[0]; 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Get the block immediately preceding this one in the Superblock. 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBlock* get_predecessor_block ( Block* b ) 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT bszB = mk_plain_bszB( (*(SizeT*)&b2[-sizeof(SizeT)]) ); 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (Block*)&b2[-bszB]; 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//--------------------------------------------------------------------------- 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Read and write the lower and upper red-zone bytes of a block. 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_rz_lo_byte ( Block* b, UInt rz_byteno, UByte v ) 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b2[hp_overhead_szB() + sizeof(SizeT) + rz_byteno] = v; 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_rz_hi_byte ( Block* b, UInt rz_byteno, UByte v ) 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b2[get_bszB(b) - sizeof(SizeT) - rz_byteno - 1] = v; 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUByte get_rz_lo_byte ( Block* b, UInt rz_byteno ) 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return b2[hp_overhead_szB() + sizeof(SizeT) + rz_byteno]; 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUByte get_rz_hi_byte ( Block* b, UInt rz_byteno ) 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* b2 = (UByte*)b; 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return b2[get_bszB(b) - sizeof(SizeT) - rz_byteno - 1]; 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Arena management ---*/ 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CORE_ARENA_MIN_SZB 1048576 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The arena structures themselves. 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Arena vg_arena[VG_N_ARENAS]; 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Functions external to this module identify arenas using ArenaIds, 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// not Arena*s. This fn converts the former to the latter. 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Arena* arenaId_to_ArenaP ( ArenaId arena ) 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(arena >= 0 && arena < VG_N_ARENAS); 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return & vg_arena[arena]; 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 498663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengSizeT VG_(malloc_effective_client_redzone_size)(void) 499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_(needs).malloc_replacement); 501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ensure_mm_init (VG_AR_CLIENT); 502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* ensure_mm_init will call arena_init if not yet done. 503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng This then ensures that the arena redzone size is properly 504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng initialised. */ 505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return arenaId_to_ArenaP(VG_AR_CLIENT)->rz_szB; 506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Initialise an arena. rz_szB is the (default) minimum redzone size; 509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// It might be overriden by VG_(clo_redzone_size) or VG_(clo_core_redzone_size). 510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// it might be made bigger to ensure that VG_MIN_MALLOC_SZB is observed. 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid arena_init ( ArenaId aid, Char* name, SizeT rz_szB, 513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT min_sblock_szB, SizeT min_unsplittable_sblock_szB ) 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT i; 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a = arenaId_to_ArenaP(aid); 517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Ensure default redzones are a reasonable size. 519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(rz_szB <= MAX_REDZONE_SZB); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Override the default redzone size if a clo value was given. 522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Note that the clo value can be significantly bigger than MAX_REDZONE_SZB 523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng to allow the user to chase horrible bugs using up to 1 page 524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng of protection. */ 525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_AR_CLIENT == aid) { 526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(clo_redzone_size) != -1) 527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng rz_szB = VG_(clo_redzone_size); 528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(clo_core_redzone_size) != rz_szB) 530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng rz_szB = VG_(clo_core_redzone_size); 531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Redzones must always be at least the size of a pointer, for holding the 534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // prev/next pointer (see the layout details at the top of this file). 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (rz_szB < sizeof(void*)) rz_szB = sizeof(void*); 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The size of the low and high admin sections in a block must be a 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // multiple of VG_MIN_MALLOC_SZB. So we round up the asked-for 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // redzone size if necessary to achieve this. 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->rz_szB = rz_szB; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (0 != overhead_szB_lo(a) % VG_MIN_MALLOC_SZB) a->rz_szB++; 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(overhead_szB_lo(a) - hp_overhead_szB() == overhead_szB_hi(a)); 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Here we have established the effective redzone size. 545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert((min_sblock_szB % VKI_PAGE_SIZE) == 0); 548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng a->name = name; 549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng a->clientmem = ( VG_AR_CLIENT == aid ? True : False ); 550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->min_sblock_szB = min_sblock_szB; 552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->min_unsplittable_sblock_szB = min_unsplittable_sblock_szB; 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < N_MALLOC_LISTS; i++) a->freelist[i] = NULL; 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->sblocks = & a->sblocks_initial[0]; 556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->sblocks_size = SBLOCKS_SIZE_INITIAL; 557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->sblocks_used = 0; 558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__nreclaim_unsplit = 0; 559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__nreclaim_split = 0; 560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan = 0; 561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_mmaped = 0; 562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan_max = 0; 563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_mmaped_max = 0; 564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__tot_blocks = 0; 565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__tot_bytes = 0; 566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__nsearches = 0; 567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->next_profile_at = 25 * 1000 * 1000; 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sizeof(a->sblocks_initial) 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == SBLOCKS_SIZE_INITIAL * sizeof(Superblock*)); 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Print vital stats for an arena. */ 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(print_all_arena_stats) ( void ) 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_N_ARENAS; i++) { 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a = arenaId_to_ArenaP(i); 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "%8s: %8ld/%8ld max/curr mmap'd, " 580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "%llu/%llu unsplit/split sb unmmap'd, " 581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "%8ld/%8ld max/curr, " 582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "%10llu/%10llu totalloc-blocks/bytes," 583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng " %10llu searches %lu rzB\n", 584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->name, 585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_mmaped_max, a->stats__bytes_mmaped, 586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__nreclaim_unsplit, a->stats__nreclaim_split, 587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan_max, 588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan, 589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__tot_blocks, a->stats__tot_bytes, 590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng a->stats__nsearches, 591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng a->rz_szB 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(print_arena_cc_analysis) ( void ) 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(clo_profile_heap) ); 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_N_ARENAS; i++) { 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_analyse_alloc_arena(i); 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This library is self-initialising, as it makes this more self-contained, 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown less coupled with the outside world. Hence VG_(arena_malloc)() and 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free)() below always call ensure_mm_init() to ensure things are 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown correctly initialised. 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We initialise the client arena separately (and later) because the core 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown must do non-client allocation before the tool has a chance to set the 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client arena's redzone size. 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool client_inited = False; 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool nonclient_inited = False; 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ensure_mm_init ( ArenaId aid ) 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static SizeT client_rz_szB = 8; // default: be paranoid 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We use checked red zones (of various sizes) for our internal stuff, 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and an unchecked zone of arbitrary size for the client. Of 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown course the client's red zone can be checked by the tool, eg. 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by using addressibility maps, but not by the mechanism implemented 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown here, which merely checks at the time of freeing that the red 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zone bytes are unchanged. 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Nb: redzone sizes are *minimums*; they could be made bigger to ensure 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alignment. Eg. with 8 byte alignment, on 32-bit machines 4 stays as 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4, but 16 becomes 20; but on 64-bit machines 4 becomes 8, and 16 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stays as 16 --- the extra 4 bytes in both are accounted for by the 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown larger prev/next ptr. 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_AR_CLIENT == aid) { 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ar_client_sbszB; 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (client_inited) { 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // This assertion ensures that a tool cannot try to change the client 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // redzone size with VG_(needs_malloc_replacement)() after this module 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // has done its first allocation from the client arena. 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(needs).malloc_replacement) 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(client_rz_szB == VG_(tdict).tool_client_redzone_szB); 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Check and set the client arena redzone size 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(needs).malloc_replacement) { 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client_rz_szB = VG_(tdict).tool_client_redzone_szB; 650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (client_rz_szB > MAX_REDZONE_SZB) { 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "\nTool error:\n" 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " specified redzone size is too big (%llu)\n", 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (ULong)client_rz_szB); 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Initialise the client arena. On all platforms, 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // increasing the superblock size reduces the number of superblocks 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // in the client arena, which makes findSb cheaper. 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ar_client_sbszB = 4194304; 661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // superblocks with a size > ar_client_sbszB will be unsplittable 662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // (unless used for providing memalign-ed blocks). 663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov arena_init ( VG_AR_CLIENT, "client", client_rz_szB, 664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ar_client_sbszB, ar_client_sbszB+1); 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client_inited = True; 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nonclient_inited) { 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov set_at_init_hp_overhead_szB = 672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(clo_profile_heap) ? VG_MIN_MALLOC_SZB : 0; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Initialise the non-client arenas 674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Similarly to client arena, big allocations will be unsplittable. 675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arena_init ( VG_AR_CORE, "core", CORE_REDZONE_DEFAULT_SZB, 676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1048576, 1048576+1 ); 677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arena_init ( VG_AR_TOOL, "tool", CORE_REDZONE_DEFAULT_SZB, 678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4194304, 4194304+1 ); 679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arena_init ( VG_AR_DINFO, "dinfo", CORE_REDZONE_DEFAULT_SZB, 680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1048576, 1048576+1 ); 681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arena_init ( VG_AR_DEMANGLE, "demangle", CORE_REDZONE_DEFAULT_SZB, 682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 65536, 65536+1 ); 683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arena_init ( VG_AR_EXECTXT, "exectxt", CORE_REDZONE_DEFAULT_SZB, 684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1048576, 1048576+1 ); 685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arena_init ( VG_AR_ERRORS, "errors", CORE_REDZONE_DEFAULT_SZB, 686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 65536, 65536+1 ); 687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arena_init ( VG_AR_TTAUX, "ttaux", CORE_REDZONE_DEFAULT_SZB, 688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 65536, 65536+1 ); 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nonclient_inited = True; 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef DEBUG_MALLOC 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("ZZZ1\n"); 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_malloc_all)(); 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("ZZZ2\n"); 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Superblock management ---*/ 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noreturn)) 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(out_of_memory_NORETURN) ( HChar* who, SizeT szB ) 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool alreadyCrashing = False; 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong tot_alloc = VG_(am_get_anonsize_total)(); 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* s1 = 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " Valgrind's memory management: out of memory:\n" 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " %s's request for %llu bytes failed.\n" 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " %llu bytes have already been allocated.\n" 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " Valgrind cannot continue. Sorry.\n\n" 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " There are several possible reasons for this.\n" 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " - You have some kind of memory limit in place. Look at the\n" 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " output of 'ulimit -a'. Is there a limit on the size of\n" 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " virtual memory or address space?\n" 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " - You have run out of swap space.\n" 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " - Valgrind has a bug. If you think this is the case or you are\n" 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " not sure, please let us know and we'll try to fix it.\n" 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " Please note that programs can take substantially more memory than\n" 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " normal when running under Valgrind tools, eg. up to twice or\n" 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " more, depending on the tool. On a 64-bit machine, Valgrind\n" 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " should be able to make use of up 32GB memory. On a 32-bit\n" 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " machine, Valgrind should be able to use all the memory available\n" 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " to a single process, up to 4GB if that's how you have your\n" 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " kernel configured. Most 32-bit Linux setups allow a maximum of\n" 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " 3GB per process.\n\n" 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " Whatever the reason, Valgrind cannot continue. Sorry.\n"; 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!alreadyCrashing) { 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown alreadyCrashing = True; 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, s1, who, (ULong)szB, tot_alloc); 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(0,"mallocfree", s1, who, (ULong)szB, tot_alloc); 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Align ptr p upwards to an align-sized boundary. 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* align_upwards ( void* p, SizeT align ) 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a = (Addr)p; 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((a % align) == 0) return (void*)a; 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (void*)(a - (a % align) + align); 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Forward definition. 753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic 754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid deferred_reclaimSuperblock ( Arena* a, Superblock* sb); 755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// If not enough memory available, either aborts (for non-client memory) 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// or returns 0 (for client memory). 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSuperblock* newSuperblock ( Arena* a, SizeT cszB ) 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock* sb; 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool unsplittable; 764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ArenaId aid; 765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // A new superblock is needed for arena a. We will execute the deferred 767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // reclaim in all arenas in order to minimise fragmentation and 768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // peak memory usage. 769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (aid = 0; aid < VG_N_ARENAS; aid++) { 770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Arena* arena = arenaId_to_ArenaP(aid); 771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (arena->deferred_reclaimed_sb != NULL) 772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deferred_reclaimSuperblock (arena, NULL); 773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Take into account admin bytes in the Superblock. 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cszB += sizeof(Superblock); 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cszB < a->min_sblock_szB) cszB = a->min_sblock_szB; 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cszB = VG_PGROUNDUP(cszB); 780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (cszB >= a->min_unsplittable_sblock_szB) 782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unsplittable = True; 783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unsplittable = False; 785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a->clientmem) { 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // client allocation -- return 0 to client if it fails 789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (unsplittable) 790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sres = VG_(am_mmap_anon_float_client) 791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ( cszB, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC ); 792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else 793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sres = VG_(am_sbrk_anon_float_client) 794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ( cszB, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC ); 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sb = (Superblock*)(AddrH)sr_Res(sres); 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Mark this segment as containing client heap. The leak 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // checker needs to be able to identify such segments so as not 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // to use them as sources of roots during leak checks. 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_set_segment_isCH_if_SkAnonC)( 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (NSegment*) VG_(am_find_nsegment)( (Addr)sb ) 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // non-client allocation -- abort if it fails 806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (unsplittable) 807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sres = VG_(am_mmap_anon_float_valgrind)( cszB ); 808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else 809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sres = VG_(am_sbrk_anon_float_valgrind)( cszB ); 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) { 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(out_of_memory_NORETURN)("newSuperblock", cszB); 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTREACHED */ 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sb = NULL; /* keep gcc happy */ 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sb = (Superblock*)(AddrH)sr_Res(sres); 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(NULL != sb); 819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_UNDEFINED(sb, cszB)); 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == (Addr)sb % VG_MIN_MALLOC_SZB); 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sb->n_payload_bytes = cszB - sizeof(Superblock); 822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sb->unsplittable = (unsplittable ? sb : NULL); 823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_mmaped += cszB; 824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (a->stats__bytes_mmaped > a->stats__bytes_mmaped_max) 825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_mmaped_max = a->stats__bytes_mmaped; 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "mallocfree", 827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "newSuperblock at %p (pszB %7ld) %s owner %s/%s\n", 828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sb, sb->n_payload_bytes, 829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (unsplittable ? "unsplittable" : ""), 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->clientmem ? "CLIENT" : "VALGRIND", a->name ); 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sb; 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Reclaims the given superblock: 835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// * removes sb from arena sblocks list. 836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// * munmap the superblock segment. 837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic 838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid reclaimSuperblock ( Arena* a, Superblock* sb) 839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SysRes sres; 841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT cszB; 842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UInt i, j; 843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(debugLog)(1, "mallocfree", 845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "reclaimSuperblock at %p (pszB %7ld) %s owner %s/%s\n", 846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sb, sb->n_payload_bytes, 847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (sb->unsplittable ? "unsplittable" : ""), 848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->clientmem ? "CLIENT" : "VALGRIND", a->name ); 849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Take into account admin bytes in the Superblock. 851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov cszB = sizeof(Superblock) + sb->n_payload_bytes; 852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // removes sb from superblock list. 854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; i < a->sblocks_used; i++) { 855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (a->sblocks[i] == sb) 856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(i >= 0 && i < a->sblocks_used); 859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (j = i; j < a->sblocks_used; j++) 860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->sblocks[j] = a->sblocks[j+1]; 861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->sblocks_used--; 862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->sblocks[a->sblocks_used] = NULL; 863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // paranoia: NULLify ptr to reclaimed sb or NULLify copy of ptr to last sb. 864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_mmaped -= cszB; 866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sb->unsplittable) 867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__nreclaim_unsplit++; 868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__nreclaim_split++; 870b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Now that the sb is removed from the list, mnumap its space. 872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (a->clientmem) { 873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // reclaimable client allocation 874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool need_discard = False; 875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sres = VG_(am_munmap_client)(&need_discard, (Addr) sb, cszB); 876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert2(! sr_isError(sres), "superblock client munmap failure\n"); 877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* We somewhat help the client by discarding the range. 878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Note however that if the client has JITted some code in 879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a small block that was freed, we do not provide this 880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 'discard support' */ 881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* JRS 2011-Sept-26: it would be nice to move the discard 882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov outwards somewhat (in terms of calls) so as to make it easier 883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to verify that there will be no nonterminating recursive set 884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov of calls a result of calling VG_(discard_translations). 885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Another day, perhaps. */ 886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (need_discard) 887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(discard_translations) ((Addr) sb, cszB, "reclaimSuperblock"); 888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // reclaimable non-client allocation 890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sres = VG_(am_munmap_valgrind)((Addr) sb, cszB); 891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert2(! sr_isError(sres), "superblock valgrind munmap failure\n"); 892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Find the superblock containing the given chunk. 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSuperblock* findSb ( Arena* a, Block* b ) 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT min = 0; 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT max = a->sblocks_used; 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (min <= max) { 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock * sb; 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT pos = min + (max - min)/2; 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(pos >= 0 && pos < a->sblocks_used); 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sb = a->sblocks[pos]; 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((Block*)&sb->payload_bytes[0] <= b 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && b < (Block*)&sb->payload_bytes[sb->n_payload_bytes]) 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sb; 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ((Block*)&sb->payload_bytes[0] <= b) { 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown min = pos + 1; 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown max = pos - 1; 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("findSb: can't find pointer %p in arena '%s'\n", 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b, a->name ); 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("findSb: VG_(arena_free)() in wrong arena?"); 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; /*NOTREACHED*/ 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Functions for working with freelists. ---*/ 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Nb: Determination of which freelist a block lives on is based on the 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// payload size, not block size. 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Convert a payload size in bytes to a freelist number. 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt pszB_to_listNo ( SizeT pszB ) 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT n = pszB / VG_MIN_MALLOC_SZB; 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0 == pszB % VG_MIN_MALLOC_SZB); 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The first 64 lists hold blocks of size VG_MIN_MALLOC_SZB * list_num. 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The final 48 hold bigger blocks. 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 64) return (UInt)n; 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Exponential slope up, factor 1.05 */ 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 67) return 64; 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 70) return 65; 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 74) return 66; 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 77) return 67; 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 81) return 68; 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 85) return 69; 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 90) return 70; 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 94) return 71; 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 99) return 72; 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 104) return 73; 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 109) return 74; 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 114) return 75; 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 120) return 76; 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 126) return 77; 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 133) return 78; 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 139) return 79; 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Exponential slope up, factor 1.10 */ 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 153) return 80; 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 169) return 81; 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 185) return 82; 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 204) return 83; 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 224) return 84; 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 247) return 85; 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 272) return 86; 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 299) return 87; 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 329) return 88; 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 362) return 89; 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 398) return 90; 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 438) return 91; 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 482) return 92; 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 530) return 93; 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 583) return 94; 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 641) return 95; 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Exponential slope up, factor 1.20 */ 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 770) return 96; 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 924) return 97; 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 1109) return 98; 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 1331) return 99; 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 1597) return 100; 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 1916) return 101; 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 2300) return 102; 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 2760) return 103; 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 3312) return 104; 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 3974) return 105; 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 4769) return 106; 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 5723) return 107; 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 6868) return 108; 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 8241) return 109; 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n < 9890) return 110; 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 111; 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// What is the minimum payload size for a given list? 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT listNo_to_pszB_min ( UInt listNo ) 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Repeatedly computing this function at every request is 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expensive. Hence at the first call just cache the result for 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown every possible argument. */ 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static SizeT cache[N_MALLOC_LISTS]; 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool cache_valid = False; 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!cache_valid) { 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < N_MALLOC_LISTS; i++) { 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT pszB = 0; 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (pszB_to_listNo(pszB) < i) 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pszB += VG_MIN_MALLOC_SZB; 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache[i] = pszB; 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cache_valid = True; 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Returned cached answer. */ 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(listNo <= N_MALLOC_LISTS); 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cache[listNo]; 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// What is the maximum payload size for a given list? 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT listNo_to_pszB_max ( UInt listNo ) 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(listNo <= N_MALLOC_LISTS); 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (listNo == N_MALLOC_LISTS-1) { 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return MAX_PSZB; 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return listNo_to_pszB_min(listNo+1) - 1; 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A nasty hack to try and reduce fragmentation. Try and replace 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->freelist[lno] with another block on the same list but with a 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lower address, with the idea of attempting to recycle the same 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blocks rather than cruise through the address space. */ 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid swizzle ( Arena* a, UInt lno ) 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* p_best; 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* pp; 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* pn; 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p_best = a->freelist[lno]; 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p_best == NULL) return; 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pn = pp = p_best; 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // This loop bound was 20 for a long time, but experiments showed that 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // reducing it to 10 gave the same result in all the tests, and 5 got the 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // same result in 85--100% of cases. And it's called often enough to be 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // noticeable in programs that allocated a lot. 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 5; i++) { 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pn = get_next_b(pn); 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pp = get_prev_b(pp); 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pn < p_best) p_best = pn; 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pp < p_best) p_best = pp; 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p_best < a->freelist[lno]) { 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef VERBOSE_MALLOC 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("retreat by %ld\n", (Word)(a->freelist[lno] - p_best)); 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->freelist[lno] = p_best; 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Sanity-check/debugging machinery. ---*/ 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REDZONE_LO_MASK 0x31 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REDZONE_HI_MASK 0x7c 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Do some crude sanity checks on a Block. 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool blockSane ( Arena* a, Block* b ) 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define BLEAT(str) VG_(printf)("blockSane: fail -- %s\n",str) 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The lo and hi size fields will be checked (indirectly) by the call 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // to get_rz_hi_byte(). 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!a->clientmem && is_inuse_block(b)) { 1085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // In the inner, for memcheck sake, temporarily mark redzone accessible. 1086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_DEFINED 1087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (b + hp_overhead_szB() + sizeof(SizeT), a->rz_szB)); 1088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_DEFINED 1089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (b + get_bszB(b) 1090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - sizeof(SizeT) - a->rz_szB, a->rz_szB)); 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < a->rz_szB; i++) { 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (get_rz_lo_byte(b, i) != 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UByte)(((Addr)b&0xff) ^ REDZONE_LO_MASK)) 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown {BLEAT("redzone-lo");return False;} 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (get_rz_hi_byte(b, i) != 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UByte)(((Addr)b&0xff) ^ REDZONE_HI_MASK)) 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown {BLEAT("redzone-hi");return False;} 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_NOACCESS 1100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (b + hp_overhead_szB() + sizeof(SizeT), a->rz_szB)); 1101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_NOACCESS 1102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (b + get_bszB(b) 1103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - sizeof(SizeT) - a->rz_szB, a->rz_szB)); 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef BLEAT 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Print superblocks (only for debugging). 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppSuperblocks ( Arena* a ) 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i, j, blockno = 1; 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT b_bszB; 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < a->sblocks_used; ++j) { 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock * sb = a->sblocks[j]; 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "\n" ); 1120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)( "superblock %d at %p %s, sb->n_pl_bs = %lu\n", 1121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov blockno++, sb, (sb->unsplittable ? "unsplittable" : ""), 1122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sb->n_payload_bytes); 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < sb->n_payload_bytes; i += b_bszB) { 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b = (Block*)&sb->payload_bytes[i]; 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_bszB = get_bszB(b); 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( " block at %d, bszB %lu: ", i, b_bszB ); 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "%s, ", is_inuse_block(b) ? "inuse" : "free"); 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "%s\n", blockSane(a, b) ? "ok" : "BAD" ); 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(i == sb->n_payload_bytes); // no overshoot at end of Sb 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "end of superblocks\n\n" ); 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Sanity check both the superblocks and the chains. 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sanity_check_malloc_arena ( ArenaId aid ) 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i, j, superblockctr, blockctr_sb, blockctr_li; 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt blockctr_sb_free, listno; 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT b_bszB, b_pszB, list_min_pszB, list_max_pszB; 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool thisFree, lastWasFree, sblockarrOK; 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b; 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b_prev; 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT arena_bytes_on_loan; 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a; 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define BOMB VG_(core_panic)("sanity_check_malloc_arena") 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a = arenaId_to_ArenaP(aid); 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Check the superblock array. 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sblockarrOK 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = a->sblocks != NULL 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a->sblocks_size >= SBLOCKS_SIZE_INITIAL 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && a->sblocks_used <= a->sblocks_size 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (a->sblocks_size == SBLOCKS_SIZE_INITIAL 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? (a->sblocks == &a->sblocks_initial[0]) 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : (a->sblocks != &a->sblocks_initial[0])); 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sblockarrOK) { 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sanity_check_malloc_arena: sblock array BAD\n"); 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BOMB; 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // First, traverse all the superblocks, inspecting the Blocks in each. 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown superblockctr = blockctr_sb = blockctr_sb_free = 0; 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arena_bytes_on_loan = 0; 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < a->sblocks_used; ++j) { 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock * sb = a->sblocks[j]; 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lastWasFree = False; 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown superblockctr++; 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < sb->n_payload_bytes; i += mk_plain_bszB(b_bszB)) { 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blockctr_sb++; 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = (Block*)&sb->payload_bytes[i]; 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_bszB = get_bszB_as_is(b); 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!blockSane(a, b)) { 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sanity_check_malloc_arena: sb %p, block %d " 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(bszB %lu): BAD\n", sb, i, b_bszB ); 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BOMB; 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thisFree = !is_inuse_block(b); 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (thisFree && lastWasFree) { 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sanity_check_malloc_arena: sb %p, block %d " 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(bszB %lu): UNMERGED FREES\n", sb, i, b_bszB ); 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BOMB; 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (thisFree) blockctr_sb_free++; 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!thisFree) 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arena_bytes_on_loan += bszB_to_pszB(a, b_bszB); 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lastWasFree = thisFree; 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i > sb->n_payload_bytes) { 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "sanity_check_malloc_arena: sb %p: last block " 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "overshoots end\n", sb); 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BOMB; 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (arena_bytes_on_loan != a->stats__bytes_on_loan) { 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef VERBOSE_MALLOC 1200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)( "sanity_check_malloc_arena: a->bytes_on_loan %lu, " 1201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "arena_bytes_on_loan %lu: " 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "MISMATCH\n", a->bytes_on_loan, arena_bytes_on_loan); 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppSuperblocks(a); 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BOMB; 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Second, traverse each list, checking that the back pointers make 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sense, counting blocks encountered, and checking that each block 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is an appropriate size for this list. */ 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blockctr_li = 0; 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (listno = 0; listno < N_MALLOC_LISTS; listno++) { 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown list_min_pszB = listNo_to_pszB_min(listno); 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown list_max_pszB = listNo_to_pszB_max(listno); 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = a->freelist[listno]; 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (b == NULL) continue; 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_prev = b; 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = get_next_b(b); 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (get_prev_b(b) != b_prev) { 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "sanity_check_malloc_arena: list %d at %p: " 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "BAD LINKAGE\n", 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown listno, b ); 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BOMB; 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_pszB = get_pszB(a, b); 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (b_pszB < list_min_pszB || b_pszB > list_max_pszB) { 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sanity_check_malloc_arena: list %d at %p: " 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "WRONG CHAIN SIZE %luB (%luB, %luB)\n", 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown listno, b, b_pszB, list_min_pszB, list_max_pszB ); 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BOMB; 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blockctr_li++; 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (b == a->freelist[listno]) break; 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (blockctr_sb_free != blockctr_li) { 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef VERBOSE_MALLOC 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "sanity_check_malloc_arena: BLOCK COUNT MISMATCH " 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(via sbs %d, via lists %d)\n", 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blockctr_sb_free, blockctr_li ); 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppSuperblocks(a); 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown BOMB; 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%8s: %2d sbs, %5d bs, %2d/%-2d free bs, " 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%7ld mmap, %7ld loan\n", 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->name, 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown superblockctr, 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blockctr_sb, blockctr_sb_free, blockctr_li, 1256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_mmaped, a->stats__bytes_on_loan); 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef BOMB 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_AN_CCS 1000 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct { ULong nBytes; ULong nBlocks; HChar* cc; } AnCC; 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AnCC anCCs[N_AN_CCS]; 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int cmp_AnCC_by_vol ( void* v1, void* v2 ) { 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AnCC* ancc1 = (AnCC*)v1; 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AnCC* ancc2 = (AnCC*)v2; 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ancc1->nBytes < ancc2->nBytes) return -1; 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ancc1->nBytes > ancc2->nBytes) return 1; 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cc_analyse_alloc_arena ( ArenaId aid ) 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word i, j, k; 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a; 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b; 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool thisFree, lastWasFree; 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT b_bszB; 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* cc; 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt n_ccs = 0; 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //return; 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a = arenaId_to_ArenaP(aid); 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a->name == NULL) { 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* arena is not in use, is not initialised and will fail the 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity check that follows. */ 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_check_malloc_arena(aid); 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "-------- Arena \"%s\": %lu/%lu max/curr mmap'd, " 1297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "%llu/%llu unsplit/split sb unmmap'd, " 1298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "%lu/%lu max/curr on_loan %lu rzB --------\n", 1299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->name, a->stats__bytes_mmaped_max, a->stats__bytes_mmaped, 1300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__nreclaim_unsplit, a->stats__nreclaim_split, 1301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng a->stats__bytes_on_loan_max, a->stats__bytes_on_loan, 1302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng a->rz_szB 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (j = 0; j < a->sblocks_used; ++j) { 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock * sb = a->sblocks[j]; 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lastWasFree = False; 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < sb->n_payload_bytes; i += mk_plain_bszB(b_bszB)) { 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = (Block*)&sb->payload_bytes[i]; 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_bszB = get_bszB_as_is(b); 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!blockSane(a, b)) { 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sanity_check_malloc_arena: sb %p, block %ld " 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(bszB %lu): BAD\n", sb, i, b_bszB ); 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thisFree = !is_inuse_block(b); 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (thisFree && lastWasFree) { 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("sanity_check_malloc_arena: sb %p, block %ld " 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(bszB %lu): UNMERGED FREES\n", sb, i, b_bszB ); 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lastWasFree = thisFree; 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (thisFree) continue; 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("block: inUse=%d pszB=%d cc=%s\n", 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)(!thisFree), 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)bszB_to_pszB(a, b_bszB), 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown get_cc(b)); 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = get_cc(b); 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(cc); 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (k = 0; k < n_ccs; k++) { 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(anCCs[k].cc); 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(strcmp)(cc, anCCs[k].cc)) 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(k >= 0 && k <= n_ccs); 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (k == n_ccs) { 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(n_ccs < N_AN_CCS-1); 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_ccs++; 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anCCs[k].nBytes = 0; 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anCCs[k].nBlocks = 0; 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anCCs[k].cc = cc; 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(k >= 0 && k < n_ccs && k < N_AN_CCS); 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anCCs[k].nBytes += (ULong)bszB_to_pszB(a, b_bszB); 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anCCs[k].nBlocks++; 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i > sb->n_payload_bytes) { 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "sanity_check_malloc_arena: sb %p: last block " 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "overshoots end\n", sb); 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(0); 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(ssort)( &anCCs[0], n_ccs, sizeof(anCCs[0]), cmp_AnCC_by_vol ); 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (k = 0; k < n_ccs; k++) { 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%'13llu in %'9llu: %s\n", 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown anCCs[k].nBytes, anCCs[k].nBlocks, anCCs[k].cc ); 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sanity_check_malloc_all) ( void ) 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < VG_N_ARENAS; i++) { 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i == VG_AR_CLIENT && !client_inited) 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_check_malloc_arena ( i ); 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Creating and deleting blocks. ---*/ 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Mark the bytes at b .. b+bszB-1 as not in use, and add them to the 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// relevant free list. 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid mkFreeBlock ( Arena* a, Block* b, SizeT bszB, UInt b_lno ) 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT pszB = bszB_to_pszB(a, bszB); 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(b_lno == pszB_to_listNo(pszB)); 1393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_UNDEFINED(b, bszB)); 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set the size fields and indicate not-in-use. 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_bszB(b, mk_free_bszB(bszB)); 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Add to the relevant list. 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a->freelist[b_lno] == NULL) { 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_prev_b(b, b); 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_next_b(b, b); 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->freelist[b_lno] = b; 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b_prev = get_prev_b(a->freelist[b_lno]); 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b_next = a->freelist[b_lno]; 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_next_b(b_prev, b); 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_prev_b(b_next, b); 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_next_b(b, b_next); 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_prev_b(b, b_prev); 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef DEBUG_MALLOC 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void)blockSane(a,b); 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Mark the bytes at b .. b+bszB-1 as in use, and set up the block 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// appropriately. 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid mkInuseBlock ( Arena* a, Block* b, SizeT bszB ) 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(bszB >= min_useful_bszB(a)); 1422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_UNDEFINED(b, bszB)); 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_bszB(b, mk_inuse_bszB(bszB)); 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_prev_b(b, NULL); // Take off freelist 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_next_b(b, NULL); // ditto 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!a->clientmem) { 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < a->rz_szB; i++) { 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_rz_lo_byte(b, i, (UByte)(((Addr)b&0xff) ^ REDZONE_LO_MASK)); 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_rz_hi_byte(b, i, (UByte)(((Addr)b&0xff) ^ REDZONE_HI_MASK)); 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef DEBUG_MALLOC 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void)blockSane(a,b); 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Remove a block from a given list. Does no sanity checking. 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid unlinkBlock ( Arena* a, Block* b, UInt listno ) 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(listno < N_MALLOC_LISTS); 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (get_prev_b(b) == b) { 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Only one element in the list; treat it specially. 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(get_next_b(b) == b); 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->freelist[listno] = NULL; 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b_prev = get_prev_b(b); 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b_next = get_next_b(b); 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->freelist[listno] = b_prev; 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_next_b(b_prev, b_next); 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_prev_b(b_next, b_prev); 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown swizzle ( a, listno ); 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_prev_b(b, NULL); 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_next_b(b, NULL); 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Core-visible functions. ---*/ 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Align the request size. 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT align_req_pszB ( SizeT req_pszB ) 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT n = VG_MIN_MALLOC_SZB-1; 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ((req_pszB + n) & (~n)); 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(arena_malloc) ( ArenaId aid, HChar* cc, SizeT req_pszB ) 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT req_bszB, frag_bszB, b_bszB; 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt lno, i; 1475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Superblock* new_sb = NULL; 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b = NULL; 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a; 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* v; 1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord stats__nsearches = 0; 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ensure_mm_init(aid); 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a = arenaId_to_ArenaP(aid); 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(req_pszB < MAX_PSZB); 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown req_pszB = align_req_pszB(req_pszB); 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown req_bszB = pszB_to_bszB(a, req_pszB); 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // You must provide a cost-center name against which to charge 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // this allocation; it isn't optional. 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(cc); 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Scan through all the big-enough freelists for a block. 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: this scanning might be expensive in some cases. Eg. if you 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // allocate lots of small objects without freeing them, but no 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // medium-sized objects, it will repeatedly scanning through the whole 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // list, and each time not find any free blocks until the last element. 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If this becomes a noticeable problem... the loop answers the question 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // "where is the first nonempty list above me?" And most of the time, 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // you ask the same question and get the same answer. So it would be 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // good to somehow cache the results of previous searches. 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // One possibility is an array (with N_MALLOC_LISTS elements) of 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // shortcuts. shortcut[i] would give the index number of the nearest 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // larger list above list i which is non-empty. Then this loop isn't 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // necessary. However, we'd have to modify some section [ .. i-1] of the 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // shortcut array every time a list [i] changes from empty to nonempty or 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // back. This would require care to avoid pathological worst-case 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // behaviour. 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (lno = pszB_to_listNo(req_pszB); lno < N_MALLOC_LISTS; lno++) { 1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord nsearches_this_level = 0; 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = a->freelist[lno]; 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (NULL == b) continue; // If this list is empty, try the next one. 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov stats__nsearches++; 1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov nsearches_this_level++; 1518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (UNLIKELY(nsearches_this_level >= 100) 1519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && lno < N_MALLOC_LISTS-1) { 1520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Avoid excessive scanning on this freelist, and instead 1521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov try the next one up. But first, move this freelist's 1522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov start pointer one element along, so as to ensure that 1523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov subsequent searches of this list don't endlessly 1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov revisit only these 100 elements, but in fact slowly 1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov progress through the entire list. */ 1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b = a->freelist[lno]; 1527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(b); // this list must be nonempty! 1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->freelist[lno] = get_next_b(b); // step one along 1529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 1530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_bszB = get_bszB(b); 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (b_bszB >= req_bszB) goto obtained_block; // success! 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = get_next_b(b); 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (b == a->freelist[lno]) break; // traversed entire freelist 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If we reach here, no suitable block found, allocate a new superblock 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(lno == N_MALLOC_LISTS); 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_sb = newSuperblock(a, req_bszB); 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (NULL == new_sb) { 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Should only fail if for client, otherwise, should have aborted 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // already. 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_AR_CLIENT == aid); 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a->sblocks_used <= a->sblocks_size); 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a->sblocks_used == a->sblocks_size) { 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock ** array; 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres = VG_(am_sbrk_anon_float_valgrind)(sizeof(Superblock *) * 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->sblocks_size * 2); 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) { 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(out_of_memory_NORETURN)("arena_init", sizeof(Superblock *) * 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->sblocks_size * 2); 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTREACHED */ 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown array = (Superblock**)(AddrH)sr_Res(sres); 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < a->sblocks_used; ++i) array[i] = a->sblocks[i]; 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->sblocks_size *= 2; 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->sblocks = array; 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1, "mallocfree", 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sblock array for arena `%s' resized to %ld\n", 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->name, a->sblocks_size); 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a->sblocks_used < a->sblocks_size); 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i = a->sblocks_used; 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (i > 0) { 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a->sblocks[i-1] > new_sb) { 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->sblocks[i] = a->sblocks[i-1]; 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown --i; 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->sblocks[i] = new_sb; 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->sblocks_used++; 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = (Block*)&new_sb->payload_bytes[0]; 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lno = pszB_to_listNo(bszB_to_pszB(a, new_sb->n_payload_bytes)); 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkFreeBlock ( a, b, new_sb->n_payload_bytes, lno); 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_profile_heap)) 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_cc(b, "admin.free-new-sb-1"); 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // fall through 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown obtained_block: 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Ok, we can allocate from b, which lives in list lno. 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(b != NULL); 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(lno < N_MALLOC_LISTS); 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a->freelist[lno] != NULL); 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_bszB = get_bszB(b); 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // req_bszB is the size of the block we are after. b_bszB is the 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // size of what we've actually got. */ 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(b_bszB >= req_bszB); 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Could we split this block and still get a useful fragment? 1600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // A block in an unsplittable superblock can never be splitted. 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frag_bszB = b_bszB - req_bszB; 1602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (frag_bszB >= min_useful_bszB(a) 1603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && (NULL == new_sb || ! new_sb->unsplittable)) { 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Yes, split block in two, put the fragment on the appropriate free 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // list, and update b_bszB accordingly. 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // printf( "split %dB into %dB and %dB\n", b_bszB, req_bszB, frag_bszB ); 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unlinkBlock(a, b, lno); 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkInuseBlock(a, b, req_bszB); 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_profile_heap)) 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_cc(b, cc); 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkFreeBlock(a, &b[req_bszB], frag_bszB, 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pszB_to_listNo(bszB_to_pszB(a, frag_bszB))); 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_profile_heap)) 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_cc(&b[req_bszB], "admin.fragmentation-1"); 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_bszB = get_bszB(b); 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // No, mark as in use and use as-is. 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unlinkBlock(a, b, lno); 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkInuseBlock(a, b, b_bszB); 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_profile_heap)) 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_cc(b, cc); 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Update stats 1625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT loaned = bszB_to_pszB(a, b_bszB); 1626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan += loaned; 1627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (a->stats__bytes_on_loan > a->stats__bytes_on_loan_max) { 1628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan_max = a->stats__bytes_on_loan; 1629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (a->stats__bytes_on_loan_max >= a->next_profile_at) { 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* next profile after 10% more growth */ 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a->next_profile_at 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (SizeT)( 1633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (((ULong)a->stats__bytes_on_loan_max) * 105ULL) / 100ULL ); 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_profile_heap)) 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc_analyse_alloc_arena(aid); 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__tot_blocks += (ULong)1; 1639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__tot_bytes += (ULong)loaned; 1640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__nsearches += (ULong)stats__nsearches; 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef DEBUG_MALLOC 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_check_malloc_arena(aid); 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown v = get_block_payload(a, b); 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( (((Addr)v) & (VG_MIN_MALLOC_SZB-1)) == 0 ); 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Which size should we pass to VALGRIND_MALLOCLIKE_BLOCK ? 1650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // We have 2 possible options: 1651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // 1. The final resulting usable size. 1652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // 2. The initial (non-aligned) req_pszB. 1653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Memcheck implements option 2 easily, as the initial requested size 1654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // is maintained in the mc_chunk data structure. 1655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // This is not as easy in the core, as there is no such structure. 1656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // (note: using the aligned req_pszB is not simpler than 2, as 1657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // requesting an aligned req_pszB might still be satisfied by returning 1658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // a (slightly) bigger block than requested if the remaining part of 1659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // of a free block is not big enough to make a free block by itself). 1660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Implement Sol 2 can be done the following way: 1661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // After having called VALGRIND_MALLOCLIKE_BLOCK, the non accessible 1662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // redzone just after the block can be used to determine the 1663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // initial requested size. 1664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Currently, not implemented => we use Option 1. 1665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST 1666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (VALGRIND_MALLOCLIKE_BLOCK(v, 1667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(arena_malloc_usable_size)(aid, v), 1668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng a->rz_szB, False)); 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For debugging/testing purposes, fill the newly allocated area 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with a definite value in an attempt to shake out any 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown uninitialised uses of the data (by V core / V tools, not by the 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown client). Testing on 25 Nov 07 with the values 0x00, 0xFF, 0x55, 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0xAA showed no differences in the regression tests on 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown amd64-linux. Note, is disabled by default. */ 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && aid != VG_AR_CLIENT) 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(v, 0xAA, (SizeT)req_pszB); 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return v; 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// If arena has already a deferred reclaimed superblock and 1683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// this superblock is still reclaimable, then this superblock is first 1684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// reclaimed. 1685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// sb becomes then the new arena deferred superblock. 1686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Passing NULL as sb allows to reclaim a deferred sb without setting a new 1687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// deferred reclaim. 1688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic 1689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid deferred_reclaimSuperblock ( Arena* a, Superblock* sb) 1690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 1691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sb == NULL) { 1693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!a->deferred_reclaimed_sb) 1694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // no deferred sb to reclaim now, nothing to do in the future => 1695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // return directly. 1696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; 1697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(debugLog)(1, "mallocfree", 1699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "deferred_reclaimSuperblock NULL " 1700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "(prev %p) owner %s/%s\n", 1701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->deferred_reclaimed_sb, 1702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->clientmem ? "CLIENT" : "VALGRIND", a->name ); 1703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else 1704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(debugLog)(1, "mallocfree", 1705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "deferred_reclaimSuperblock at %p (pszB %7ld) %s " 1706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "(prev %p) owner %s/%s\n", 1707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sb, sb->n_payload_bytes, 1708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (sb->unsplittable ? "unsplittable" : ""), 1709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->deferred_reclaimed_sb, 1710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->clientmem ? "CLIENT" : "VALGRIND", a->name ); 1711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (a->deferred_reclaimed_sb && a->deferred_reclaimed_sb != sb) { 1713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // If we are deferring another block that the current block deferred, 1714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // then if this block can stil be reclaimed, reclaim it now. 1715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Note that we might have a re-deferred reclaim of the same block 1716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // with a sequence: free (causing a deferred reclaim of sb) 1717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // alloc (using a piece of memory of the deferred sb) 1718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // free of the just alloc-ed block (causing a re-defer). 1719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UByte* def_sb_start; 1720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UByte* def_sb_end; 1721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Superblock* def_sb; 1722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Block* b; 1723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov def_sb = a->deferred_reclaimed_sb; 1725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov def_sb_start = &def_sb->payload_bytes[0]; 1726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov def_sb_end = &def_sb->payload_bytes[def_sb->n_payload_bytes - 1]; 1727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b = (Block *)def_sb_start; 1728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert (blockSane(a, b)); 1729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Check if the deferred_reclaimed_sb is still reclaimable. 1731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // If yes, we will execute the reclaim. 1732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!is_inuse_block(b)) { 1733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // b (at the beginning of def_sb) is not in use. 1734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UInt b_listno; 1735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT b_bszB, b_pszB; 1736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b_bszB = get_bszB(b); 1737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b_pszB = bszB_to_pszB(a, b_bszB); 1738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (b + b_bszB-1 == (Block*)def_sb_end) { 1739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // b (not in use) covers the full superblock. 1740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // => def_sb is still reclaimable 1741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // => execute now the reclaim of this def_sb. 1742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b_listno = pszB_to_listNo(b_pszB); 1743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unlinkBlock( a, b, b_listno ); 1744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov reclaimSuperblock (a, def_sb); 1745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->deferred_reclaimed_sb = NULL; 1746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // sb (possibly NULL) becomes the new deferred reclaimed superblock. 1751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->deferred_reclaimed_sb = sb; 1752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 1753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(arena_free) ( ArenaId aid, void* ptr ) 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Superblock* sb; 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* sb_start; 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte* sb_end; 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* other_b; 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b; 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT b_bszB, b_pszB, other_bszB; 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt b_listno; 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a; 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ensure_mm_init(aid); 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a = arenaId_to_ArenaP(aid); 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ptr == NULL) { 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = get_payload_block(a, ptr); 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this is one of V's areas, check carefully the block we're 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getting back. This picks up simple block-end overruns. */ 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (aid != VG_AR_CLIENT) 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(blockSane(a, b)); 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_bszB = get_bszB(b); 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b_pszB = bszB_to_pszB(a, b_bszB); 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sb = findSb( a, b ); 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sb_start = &sb->payload_bytes[0]; 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sb_end = &sb->payload_bytes[sb->n_payload_bytes - 1]; 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan -= b_pszB; 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If this is one of V's areas, fill it up with junk to enhance the 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chances of catching any later reads of it. Note, 0xDD is 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown carefully chosen junk :-), in that: (1) 0xDDDDDDDD is an invalid 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and non-word-aligned address on most systems, and (2) 0xDD is a 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value which is unlikely to be generated by the new compressed 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vbits representation for memcheck. */ 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (aid != VG_AR_CLIENT) 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(ptr, 0xDD, (SizeT)b_pszB); 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (! sb->unsplittable) { 1798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Put this chunk back on a list somewhere. 1799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b_listno = pszB_to_listNo(b_pszB); 1800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkFreeBlock( a, b, b_bszB, b_listno ); 1801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_profile_heap)) 1802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov set_cc(b, "admin.free-1"); 1803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // See if this block can be merged with its successor. 1805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // First test if we're far enough before the superblock's end to possibly 1806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // have a successor. 1807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov other_b = b + b_bszB; 1808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (other_b+min_useful_bszB(a)-1 <= (Block*)sb_end) { 1809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Ok, we have a successor, merge if it's not in use. 1810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov other_bszB = get_bszB(other_b); 1811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!is_inuse_block(other_b)) { 1812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // VG_(printf)( "merge-successor\n"); 1813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# ifdef DEBUG_MALLOC 1814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(blockSane(a, other_b)); 1815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 1816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unlinkBlock( a, b, b_listno ); 1817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unlinkBlock( a, other_b, 1818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pszB_to_listNo(bszB_to_pszB(a,other_bszB)) ); 1819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b_bszB += other_bszB; 1820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b_listno = pszB_to_listNo(bszB_to_pszB(a, b_bszB)); 1821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkFreeBlock( a, b, b_bszB, b_listno ); 1822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_profile_heap)) 1823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov set_cc(b, "admin.free-2"); 1824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 1826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Not enough space for successor: check that b is the last block 1827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // ie. there are no unused bytes at the end of the Superblock. 1828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(other_b-1 == (Block*)sb_end); 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 18308f943afc22a6a683b78271836c8ddc462b4824a9Evgeniy Stepanov 1831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Then see if this block can be merged with its predecessor. 1832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // First test if we're far enough after the superblock's start to possibly 1833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // have a predecessor. 1834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (b >= (Block*)sb_start + min_useful_bszB(a)) { 1835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Ok, we have a predecessor, merge if it's not in use. 1836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov other_b = get_predecessor_block( b ); 1837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov other_bszB = get_bszB(other_b); 1838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!is_inuse_block(other_b)) { 1839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // VG_(printf)( "merge-predecessor\n"); 1840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unlinkBlock( a, b, b_listno ); 1841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unlinkBlock( a, other_b, 1842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pszB_to_listNo(bszB_to_pszB(a, other_bszB)) ); 1843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b = other_b; 1844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b_bszB += other_bszB; 1845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov b_listno = pszB_to_listNo(bszB_to_pszB(a, b_bszB)); 1846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkFreeBlock( a, b, b_bszB, b_listno ); 1847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_profile_heap)) 1848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov set_cc(b, "admin.free-3"); 1849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 1851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Not enough space for predecessor: check that b is the first block, 1852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // ie. there are no unused bytes at the start of the Superblock. 1853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert((Block*)sb_start == b); 18548f943afc22a6a683b78271836c8ddc462b4824a9Evgeniy Stepanov } 1855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* If the block b just merged is the only block of the superblock sb, 1857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov then we defer reclaim sb. */ 1858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if ( ((Block*)sb_start == b) && (b + b_bszB-1 == (Block*)sb_end) ) { 1859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov deferred_reclaimSuperblock (a, sb); 1860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Inform that ptr has been released. We give redzone size 1863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // 0 instead of a->rz_szB as proper accessibility is done just after. 1864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_FREELIKE_BLOCK(ptr, 0)); 1865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // We need to (re-)establish the minimum accessibility needed 1867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // for free list management. E.g. if block ptr has been put in a free 1868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // list and a neighbour block is released afterwards, the 1869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // "lo" and "hi" portions of the block ptr will be accessed to 1870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // glue the 2 blocks together. 1871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // We could mark the whole block as not accessible, and each time 1872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // transiently mark accessible the needed lo/hi parts. Not done as this 1873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // is quite complex, for very little expected additional bug detection. 1874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // fully unaccessible. Note that the below marks the (possibly) merged 1875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // block, not the block corresponding to the ptr argument. 1876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // First mark the whole block unaccessible. 1878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_NOACCESS(b, b_bszB)); 1879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Then mark the relevant administrative headers as defined. 1880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // No need to mark the heap profile portion as defined, this is not 1881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // used for free blocks. 1882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_DEFINED(b + hp_overhead_szB(), 1883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sizeof(SizeT) + sizeof(void*))); 1884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_DEFINED(b + b_bszB 1885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - sizeof(SizeT) - sizeof(void*), 1886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng sizeof(SizeT) + sizeof(void*))); 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // b must be first block (i.e. no unused bytes at the beginning) 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert((Block*)sb_start == b); 1890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // b must be last block (i.e. no unused bytes at the end) 1892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov other_b = b + b_bszB; 1893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(other_b-1 == (Block*)sb_end); 1894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Inform that ptr has been released. Redzone size value 1896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // is not relevant (so we give 0 instead of a->rz_szB) 1897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // as it is expected that the aspacemgr munmap will be used by 1898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // outer to mark the whole superblock as unaccessible. 1899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_FREELIKE_BLOCK(ptr, 0)); 1900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Reclaim immediately the unsplittable superblock sb. 1902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov reclaimSuperblock (a, sb); 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef DEBUG_MALLOC 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_check_malloc_arena(aid); 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The idea for malloc_aligned() is to allocate a big block, base, and 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then split it into two parts: frag, which is returned to the the 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown free pool, and align, which is the bit we're really after. Here's 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a picture. L and H denote the block lower and upper overheads, in 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bytes. The details are gruesome. Note it is slightly complicated 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because the initial request to generate base may return a bigger 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block than we asked for, so it is important to distinguish the base 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown request size and the base actual size. 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frag_b align_b 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | | 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | frag_p | align_p 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | | | | 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown v v v v 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown +---+ +---+---+ +---+ 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | L |----------------| H | L |---------------| H | 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown +---+ +---+---+ +---+ 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ^ ^ ^ 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | | : 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | base_p this addr must be aligned 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown base_b 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown . . . . . . . 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown <------ frag_bszB -------> . . . 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown . <------------- base_pszB_act -----------> . 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown . . . . . . . 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(arena_memalign) ( ArenaId aid, HChar* cc, 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT req_alignB, SizeT req_pszB ) 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT base_pszB_req, base_pszB_act, frag_bszB; 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block *base_b, *align_b; 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UByte *base_p, *align_p; 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT saved_bytes_on_loan; 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a; 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ensure_mm_init(aid); 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a = arenaId_to_ArenaP(aid); 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(req_pszB < MAX_PSZB); 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // You must provide a cost-center name against which to charge 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // this allocation; it isn't optional. 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(cc); 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // Check that the requested alignment has a plausible size. 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Check that the requested alignment seems reasonable; that is, is 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // a power of 2. 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (req_alignB < VG_MIN_MALLOC_SZB 1966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || req_alignB > 16 * 1024 * 1024 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || VG_(log2)( req_alignB ) == -1 /* not a power of 2 */) { 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("VG_(arena_memalign)(%p, %lu, %lu)\n" 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "bad alignment value %lu\n" 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "(it is too small, too big, or not a power of two)", 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a, req_alignB, req_pszB, req_alignB ); 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("VG_(arena_memalign)"); 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Paranoid 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(req_alignB % VG_MIN_MALLOC_SZB == 0); 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Required payload size for the aligned chunk. */ 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown req_pszB = align_req_pszB(req_pszB); 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Payload size to request for the big block that we will split up. */ 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown base_pszB_req = req_pszB + min_useful_bszB(a) + req_alignB; 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Payload ptr for the block we are going to split. Note this 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown changes a->bytes_on_loan; we save and restore it ourselves. */ 1986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov saved_bytes_on_loan = a->stats__bytes_on_loan; 1987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { 1988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* As we will split the block given back by VG_(arena_malloc), 1989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov we have to (temporarily) disable unsplittable for this arena, 1990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov as unsplittable superblocks cannot be splitted. */ 1991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const SizeT save_min_unsplittable_sblock_szB 1992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov = a->min_unsplittable_sblock_szB; 1993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->min_unsplittable_sblock_szB = MAX_PSZB; 1994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov base_p = VG_(arena_malloc) ( aid, cc, base_pszB_req ); 1995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->min_unsplittable_sblock_szB = save_min_unsplittable_sblock_szB; 1996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan = saved_bytes_on_loan; 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Give up if we couldn't allocate enough space */ 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (base_p == 0) 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 2002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* base_p was marked as allocated by VALGRIND_MALLOCLIKE_BLOCK 2003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng inside VG_(arena_malloc). We need to indicate it is free, then 2004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng we need to mark it undefined to allow the below code to access is. */ 2005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_FREELIKE_BLOCK(base_p, a->rz_szB)); 2006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MAKE_MEM_UNDEFINED(base_p, base_pszB_req)); 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Block ptr for the block we are going to split. */ 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown base_b = get_payload_block ( a, base_p ); 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Pointer to the payload of the aligned block we are going to 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return. This has to be suitably aligned. */ 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown align_p = align_upwards ( base_b + 2 * overhead_szB_lo(a) 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + overhead_szB_hi(a), 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown req_alignB ); 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown align_b = get_payload_block(a, align_p); 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The block size of the fragment we will create. This must be big 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown enough to actually create a fragment. */ 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown frag_bszB = align_b - base_b; 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(frag_bszB >= min_useful_bszB(a)); 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The actual payload size of the block we are going to split. */ 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown base_pszB_act = get_pszB(a, base_b); 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create the fragment block, and put it back on the relevant free list. */ 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkFreeBlock ( a, base_b, frag_bszB, 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pszB_to_listNo(bszB_to_pszB(a, frag_bszB)) ); 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_profile_heap)) 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_cc(base_b, "admin.frag-memalign-1"); 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create the aligned block. */ 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkInuseBlock ( a, align_b, 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown base_p + base_pszB_act 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown + overhead_szB_hi(a) - (UByte*)align_b ); 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_profile_heap)) 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_cc(align_b, cc); 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Final sanity checks. */ 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( is_inuse_block(get_payload_block(a, align_p)) ); 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(req_pszB <= get_pszB(a, get_payload_block(a, align_p))); 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan += get_pszB(a, get_payload_block(a, align_p)); 2046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (a->stats__bytes_on_loan > a->stats__bytes_on_loan_max) { 2047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov a->stats__bytes_on_loan_max = a->stats__bytes_on_loan; 2048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* a->stats__tot_blocks, a->stats__tot_bytes, a->stats__nsearches 2050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov are updated by the call to VG_(arena_malloc) just a few lines 2051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov above. So we don't need to update them here. */ 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef DEBUG_MALLOC 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_check_malloc_arena(aid); 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( (((Addr)align_p) % req_alignB) == 0 ); 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng INNER_REQUEST(VALGRIND_MALLOCLIKE_BLOCK(align_p, 2060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng req_pszB, a->rz_szB, False)); 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return align_p; 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT VG_(arena_malloc_usable_size) ( ArenaId aid, void* ptr ) 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a = arenaId_to_ArenaP(aid); 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b = get_payload_block(a, ptr); 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return get_pszB(a, b); 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Implementation of mallinfo(). There is no recent standard that defines 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the behavior of mallinfo(). The meaning of the fields in struct mallinfo 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// is as follows: 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// struct mallinfo { 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int arena; /* total space in arena */ 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int ordblks; /* number of ordinary blocks */ 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int smblks; /* number of small blocks */ 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int hblks; /* number of holding blocks */ 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int hblkhd; /* space in holding block headers */ 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int usmblks; /* space in small blocks in use */ 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int fsmblks; /* space in free small blocks */ 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int uordblks; /* space in ordinary blocks in use */ 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int fordblks; /* space in free ordinary blocks */ 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int keepcost; /* space penalty if keep option */ 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// /* is used */ 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// }; 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The glibc documentation about mallinfo (which is somewhat outdated) can 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// be found here: 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// http://www.gnu.org/software/libtool/manual/libc/Statistics-of-Malloc.html 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// See also http://bugs.kde.org/show_bug.cgi?id=160956. 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Regarding the implementation of VG_(mallinfo)(): we cannot return the 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// whole struct as the library function does, because this is called by a 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// client request. So instead we use a pointer to do call by reference. 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(mallinfo) ( ThreadId tid, struct vg_mallinfo* mi ) 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord i, free_blocks, free_blocks_size; 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a = arenaId_to_ArenaP(VG_AR_CLIENT); 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Traverse free list and calculate free blocks statistics. 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // This may seem slow but glibc works the same way. 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown free_blocks_size = free_blocks = 0; 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < N_MALLOC_LISTS; i++) { 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b = a->freelist[i]; 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (b == NULL) continue; 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (;;) { 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown free_blocks++; 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown free_blocks_size += (UWord)get_pszB(a, b); 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = get_next_b(b); 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (b == a->freelist[i]) break; 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // We don't have fastbins so smblks & fsmblks are always 0. Also we don't 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // have a separate mmap allocator so set hblks & hblkhd to 0. 2122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mi->arena = a->stats__bytes_mmaped; 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mi->ordblks = free_blocks + VG_(free_queue_length); 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mi->smblks = 0; 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mi->hblks = 0; 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mi->hblkhd = 0; 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mi->usmblks = 0; 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mi->fsmblks = 0; 2129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mi->uordblks = a->stats__bytes_on_loan - VG_(free_queue_volume); 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mi->fordblks = free_blocks_size + VG_(free_queue_volume); 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mi->keepcost = 0; // may want some value in here 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Services layered on top of malloc/free. ---*/ 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(arena_calloc) ( ArenaId aid, HChar* cc, 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT nmemb, SizeT bytes_per_memb ) 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT size; 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* p; 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size = nmemb * bytes_per_memb; 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(size >= nmemb && size >= bytes_per_memb);// check against overflow 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = VG_(arena_malloc) ( aid, cc, size ); 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(p, 0, size); 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return p; 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(arena_realloc) ( ArenaId aid, HChar* cc, 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* ptr, SizeT req_pszB ) 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Arena* a; 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT old_pszB; 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar *p_new; 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Block* b; 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ensure_mm_init(aid); 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a = arenaId_to_ArenaP(aid); 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(req_pszB < MAX_PSZB); 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (NULL == ptr) { 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_malloc)(aid, cc, req_pszB); 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (req_pszB == 0) { 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free)(aid, ptr); 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown b = get_payload_block(a, ptr); 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(blockSane(a, b)); 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(is_inuse_block(b)); 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_pszB = get_pszB(a, b); 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (req_pszB <= old_pszB) { 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ptr; 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p_new = VG_(arena_malloc) ( aid, cc, req_pszB ); 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memcpy)(p_new, ptr, old_pszB); 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free)(aid, ptr); 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return p_new; 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Inline just for the wrapper VG_(strdup) below */ 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__inline__ Char* VG_(arena_strdup) ( ArenaId aid, HChar* cc, 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char* s ) 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len; 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* res; 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s == NULL) 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len = VG_(strlen)(s) + 1; 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(arena_malloc) (aid, cc, len); 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < len; i++) 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res[i] = s[i]; 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Tool-visible functions. ---*/ 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// All just wrappers to avoid exposing arenas to tools. 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(malloc) ( HChar* cc, SizeT nbytes ) 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_malloc) ( VG_AR_TOOL, cc, nbytes ); 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(free) ( void* ptr ) 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free) ( VG_AR_TOOL, ptr ); 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(calloc) ( HChar* cc, SizeT nmemb, SizeT bytes_per_memb ) 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_calloc) ( VG_AR_TOOL, cc, nmemb, bytes_per_memb ); 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* VG_(realloc) ( HChar* cc, void* ptr, SizeT size ) 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_realloc) ( VG_AR_TOOL, cc, ptr, size ); 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(strdup) ( HChar* cc, const Char* s ) 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_strdup) ( VG_AR_TOOL, cc, s ); 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Useful for querying user blocks. 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT VG_(malloc_usable_size) ( void* p ) 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(arena_malloc_usable_size)(VG_AR_CLIENT, p); 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2259