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