Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/awt/debug/debug_mem.c
38918 views
1
/*
2
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#if defined(DEBUG)
27
28
#include "debug_util.h"
29
30
/* Use THIS_FILE when it is available. */
31
#ifndef THIS_FILE
32
#define THIS_FILE __FILE__
33
#endif
34
35
#define DMEM_MIN(a,b) (a) < (b) ? (a) : (b)
36
#define DMEM_MAX(a,b) (a) > (b) ? (a) : (b)
37
38
typedef char byte_t;
39
40
static const byte_t ByteInited = '\xCD';
41
static const byte_t ByteFreed = '\xDD';
42
static const byte_t ByteGuard = '\xFD';
43
44
enum {
45
MAX_LINENUM = 50000, /* I certainly hope we don't have source files bigger than this */
46
MAX_CHECK_BYTES = 27, /* max bytes to check at start of block */
47
MAX_GUARD_BYTES = 8, /* size of guard areas on either side of a block */
48
MAX_DECIMAL_DIGITS = 15
49
};
50
51
/* Debug Info Header to precede allocated block */
52
typedef struct MemoryBlockHeader {
53
char filename[FILENAME_MAX+1]; /* filename where alloc occurred */
54
int linenumber; /* line where alloc occurred */
55
size_t size; /* size of the allocation */
56
int order; /* the order the block was allocated in */
57
struct MemoryListLink * listEnter; /* pointer to the free list node */
58
byte_t guard[MAX_GUARD_BYTES]; /* guard area for underrun check */
59
} MemoryBlockHeader;
60
61
/* Tail to follow allocated block */
62
typedef struct MemoryBlockTail {
63
byte_t guard[MAX_GUARD_BYTES]; /* guard area overrun check */
64
} MemoryBlockTail;
65
66
/* Linked list of allocated memory blocks */
67
typedef struct MemoryListLink {
68
struct MemoryListLink * next;
69
MemoryBlockHeader * header;
70
int freed;
71
} MemoryListLink;
72
73
/**************************************************
74
* Global Data structures
75
*/
76
static DMemState DMemGlobalState;
77
extern const DMemState * DMemStatePtr = &DMemGlobalState;
78
static MemoryListLink MemoryList = {NULL,NULL,FALSE};
79
static dmutex_t DMemMutex = NULL;
80
81
/**************************************************/
82
83
/*************************************************
84
* Client callback invocation functions
85
*/
86
static void * DMem_ClientAllocate(size_t size) {
87
if (DMemGlobalState.pfnAlloc != NULL) {
88
return (*DMemGlobalState.pfnAlloc)(size);
89
}
90
return malloc(size);
91
}
92
93
static void DMem_ClientFree(void * ptr) {
94
if (DMemGlobalState.pfnFree != NULL) {
95
(*DMemGlobalState.pfnFree)(ptr);
96
}
97
free(ptr);
98
}
99
100
static dbool_t DMem_ClientCheckPtr(void * ptr, size_t size) {
101
if (DMemGlobalState.pfnCheckPtr != NULL) {
102
return (*DMemGlobalState.pfnCheckPtr)(ptr, size);
103
}
104
return ptr != NULL;
105
}
106
107
/**************************************************/
108
109
/*************************************************
110
* Debug Memory Manager implementation
111
*/
112
113
static MemoryListLink * DMem_TrackBlock(MemoryBlockHeader * header) {
114
MemoryListLink * link;
115
116
link = (MemoryListLink *)DMem_ClientAllocate(sizeof(MemoryListLink));
117
if (link != NULL) {
118
link->header = header;
119
link->header->listEnter = link;
120
link->next = MemoryList.next;
121
link->freed = FALSE;
122
MemoryList.next = link;
123
}
124
125
return link;
126
}
127
128
static int DMem_VerifyGuardArea(const byte_t * area) {
129
int nbyte;
130
131
for ( nbyte = 0; nbyte < MAX_GUARD_BYTES; nbyte++ ) {
132
if (area[nbyte] != ByteGuard) {
133
return FALSE;
134
}
135
}
136
return TRUE;
137
}
138
139
static void DMem_VerifyHeader(MemoryBlockHeader * header) {
140
DASSERTMSG( DMem_ClientCheckPtr(header, sizeof(MemoryBlockHeader)), "Invalid header" );
141
DASSERTMSG( DMem_VerifyGuardArea(header->guard), "Header corruption, possible underwrite" );
142
DASSERTMSG( header->linenumber > 0 && header->linenumber < MAX_LINENUM, "Header corruption, bad line number" );
143
DASSERTMSG( header->size <= DMemGlobalState.biggestBlock, "Header corruption, block size is too large");
144
DASSERTMSG( header->order <= DMemGlobalState.totalAllocs, "Header corruption, block order out of range");
145
}
146
147
static void DMem_VerifyTail(MemoryBlockTail * tail) {
148
DASSERTMSG( DMem_ClientCheckPtr(tail, sizeof(MemoryBlockTail)), "Tail corruption, invalid pointer");
149
DASSERTMSG( DMem_VerifyGuardArea(tail->guard), "Tail corruption, possible overwrite" );
150
}
151
152
static MemoryBlockHeader * DMem_VerifyBlock(void * memptr) {
153
MemoryBlockHeader * header;
154
MemoryBlockTail * tail;
155
156
/* check if the pointer is valid */
157
DASSERTMSG( DMem_ClientCheckPtr(memptr, 1), "Invalid pointer");
158
159
/* check if the block header is valid */
160
header = (MemoryBlockHeader *)((byte_t *)memptr - sizeof(MemoryBlockHeader));
161
DMem_VerifyHeader(header);
162
/* check that the memory itself is valid */
163
DASSERTMSG( DMem_ClientCheckPtr(memptr, DMEM_MIN(MAX_CHECK_BYTES,header->size)), "Block memory invalid" );
164
/* check that the pointer to the alloc list is valid */
165
DASSERTMSG( DMem_ClientCheckPtr(header->listEnter, sizeof(MemoryListLink)), "Header corruption, alloc list pointer invalid" );
166
/* check the tail of the block for overruns */
167
tail = (MemoryBlockTail *) ( (byte_t *)memptr + header->size );
168
DMem_VerifyTail(tail);
169
170
return header;
171
}
172
173
static MemoryBlockHeader * DMem_GetHeader(void * memptr) {
174
MemoryBlockHeader * header = DMem_VerifyBlock(memptr);
175
return header;
176
}
177
178
/*
179
* Should be called before any other DMem_XXX function
180
*/
181
void DMem_Initialize() {
182
DMemMutex = DMutex_Create();
183
DMutex_Enter(DMemMutex);
184
DMemGlobalState.pfnAlloc = NULL;
185
DMemGlobalState.pfnFree = NULL;
186
DMemGlobalState.pfnCheckPtr = NULL;
187
DMemGlobalState.biggestBlock = 0;
188
DMemGlobalState.maxHeap = INT_MAX;
189
DMemGlobalState.totalHeapUsed = 0;
190
DMemGlobalState.failNextAlloc = FALSE;
191
DMemGlobalState.totalAllocs = 0;
192
DMutex_Exit(DMemMutex);
193
}
194
195
void DMem_Shutdown() {
196
DMutex_Destroy(DMemMutex);
197
}
198
/*
199
* Allocates a block of memory, reserving extra space at the start and end of the
200
* block to store debug info on where the block was allocated, it's size, and
201
* 'guard' areas to catch overwrite/underwrite bugs
202
*/
203
void * DMem_AllocateBlock(size_t size, const char * filename, int linenumber) {
204
MemoryBlockHeader * header;
205
MemoryBlockTail * tail;
206
size_t debugBlockSize;
207
byte_t * memptr = NULL;
208
209
DMutex_Enter(DMemMutex);
210
if (DMemGlobalState.failNextAlloc) {
211
/* force an allocation failure if so ordered */
212
DMemGlobalState.failNextAlloc = FALSE; /* reset flag */
213
goto Exit;
214
}
215
216
/* allocate a block large enough to hold extra debug info */
217
debugBlockSize = sizeof(MemoryBlockHeader) + size + sizeof(MemoryBlockTail);
218
header = (MemoryBlockHeader *)DMem_ClientAllocate(debugBlockSize);
219
if (header == NULL) {
220
goto Exit;
221
}
222
223
/* add block to list of allocated memory */
224
header->listEnter = DMem_TrackBlock(header);
225
if ( header->listEnter == NULL ) {
226
goto Exit;
227
}
228
229
/* store size of requested block */
230
header->size = size;
231
/* update maximum block size */
232
DMemGlobalState.biggestBlock = DMEM_MAX(header->size, DMemGlobalState.biggestBlock);
233
/* update used memory total */
234
DMemGlobalState.totalHeapUsed += header->size;
235
/* store filename and linenumber where allocation routine was called */
236
strncpy(header->filename, filename, FILENAME_MAX);
237
header->linenumber = linenumber;
238
/* store the order the block was allocated in */
239
header->order = DMemGlobalState.totalAllocs++;
240
/* initialize memory to a recognizable 'inited' value */
241
memptr = (byte_t *)header + sizeof(MemoryBlockHeader);
242
memset(memptr, ByteInited, size);
243
/* put guard area before block */
244
memset(header->guard, ByteGuard, MAX_GUARD_BYTES);
245
/* put guard area after block */
246
tail = (MemoryBlockTail *)(memptr + size);
247
memset(tail->guard, ByteGuard, MAX_GUARD_BYTES);
248
249
Exit:
250
DMutex_Exit(DMemMutex);
251
return memptr;
252
}
253
254
/*
255
* Frees block of memory allocated with DMem_AllocateBlock
256
*/
257
void DMem_FreeBlock(void * memptr) {
258
MemoryBlockHeader * header;
259
260
DMutex_Enter(DMemMutex);
261
if ( memptr == NULL) {
262
goto Exit;
263
}
264
265
/* get the debug block header preceding the allocated memory */
266
header = DMem_GetHeader(memptr);
267
/* fill memory with recognizable 'freed' value */
268
memset(memptr, ByteFreed, header->size);
269
/* mark block as freed */
270
header->listEnter->freed = TRUE;
271
/* update used memory total */
272
DMemGlobalState.totalHeapUsed -= header->size;
273
Exit:
274
DMutex_Exit(DMemMutex);
275
}
276
277
static void DMem_DumpHeader(MemoryBlockHeader * header) {
278
char report[FILENAME_MAX+MAX_DECIMAL_DIGITS*3+1];
279
static const char * reportFormat =
280
"file: %s, line %d\n"
281
"size: %d bytes\n"
282
"order: %d\n"
283
"-------";
284
285
DMem_VerifyHeader(header);
286
sprintf(report, reportFormat, header->filename, header->linenumber, header->size, header->order);
287
DTRACE_PRINTLN(report);
288
}
289
290
/*
291
* Call this function at shutdown time to report any leaked blocks
292
*/
293
void DMem_ReportLeaks() {
294
MemoryListLink * link;
295
296
DMutex_Enter(DMemMutex);
297
298
/* Force memory leaks to be output regardless of trace settings */
299
DTrace_EnableFile(THIS_FILE, TRUE);
300
DTRACE_PRINTLN("--------------------------");
301
DTRACE_PRINTLN("Debug Memory Manager Leaks");
302
DTRACE_PRINTLN("--------------------------");
303
304
/* walk through allocated list and dump any blocks not marked as freed */
305
link = MemoryList.next;
306
while (link != NULL) {
307
if ( !link->freed ) {
308
DMem_DumpHeader(link->header);
309
}
310
link = link->next;
311
}
312
313
DMutex_Exit(DMemMutex);
314
}
315
316
void DMem_SetAllocCallback( DMEM_ALLOCFN pfn ) {
317
DMutex_Enter(DMemMutex);
318
DMemGlobalState.pfnAlloc = pfn;
319
DMutex_Exit(DMemMutex);
320
}
321
322
void DMem_SetFreeCallback( DMEM_FREEFN pfn ) {
323
DMutex_Enter(DMemMutex);
324
DMemGlobalState.pfnFree = pfn;
325
DMutex_Exit(DMemMutex);
326
}
327
328
void DMem_SetCheckPtrCallback( DMEM_CHECKPTRFN pfn ) {
329
DMutex_Enter(DMemMutex);
330
DMemGlobalState.pfnCheckPtr = pfn;
331
DMutex_Exit(DMemMutex);
332
}
333
334
void DMem_DisableMutex() {
335
DMemMutex = NULL;
336
}
337
338
#endif /* defined(DEBUG) */
339
340
/* The following line is only here to prevent compiler warnings
341
* on release (non-debug) builds
342
*/
343
static int dummyVariable = 0;
344
345