Skip to content

Commit bfd12cc

Browse files
committed
Make useful infrastructure from aset.c generally available.
An upcoming patch introduces a new type of memory context. To avoid duplicating debugging infrastructure within aset.c, move useful pieces to memdebug.[ch]. While touching aset.c, fix printf format code in AllocFree* debug macros. Author: Tomas Vondra Reviewed-By: Andres Freund Discussion: https://postgr.es/m/b3b2245c-b37a-e1e5-ebc4-857c914bc747@2ndquadrant.com
1 parent 1513dbe commit bfd12cc

File tree

4 files changed

+144
-114
lines changed

4 files changed

+144
-114
lines changed

src/backend/utils/mmgr/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ subdir = src/backend/utils/mmgr
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = aset.o dsa.o freepage.o mcxt.o portalmem.o
15+
OBJS = aset.o dsa.o freepage.o mcxt.o memdebug.o portalmem.o
1616

1717
include $(top_srcdir)/src/backend/common.mk

src/backend/utils/mmgr/aset.c

Lines changed: 2 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -41,46 +41,6 @@
4141
* chunks as chunks. Anything "large" is passed off to malloc(). Change
4242
* the number of freelists to change the small/large boundary.
4343
*
44-
*
45-
* About CLOBBER_FREED_MEMORY:
46-
*
47-
* If this symbol is defined, all freed memory is overwritten with 0x7F's.
48-
* This is useful for catching places that reference already-freed memory.
49-
*
50-
* About MEMORY_CONTEXT_CHECKING:
51-
*
52-
* Since we usually round request sizes up to the next power of 2, there
53-
* is often some unused space immediately after a requested data area.
54-
* Thus, if someone makes the common error of writing past what they've
55-
* requested, the problem is likely to go unnoticed ... until the day when
56-
* there *isn't* any wasted space, perhaps because of different memory
57-
* alignment on a new platform, or some other effect. To catch this sort
58-
* of problem, the MEMORY_CONTEXT_CHECKING option stores 0x7E just beyond
59-
* the requested space whenever the request is less than the actual chunk
60-
* size, and verifies that the byte is undamaged when the chunk is freed.
61-
*
62-
*
63-
* About USE_VALGRIND and Valgrind client requests:
64-
*
65-
* Valgrind provides "client request" macros that exchange information with
66-
* the host Valgrind (if any). Under !USE_VALGRIND, memdebug.h stubs out
67-
* currently-used macros.
68-
*
69-
* When running under Valgrind, we want a NOACCESS memory region both before
70-
* and after the allocation. The chunk header is tempting as the preceding
71-
* region, but mcxt.c expects to able to examine the standard chunk header
72-
* fields. Therefore, we use, when available, the requested_size field and
73-
* any subsequent padding. requested_size is made NOACCESS before returning
74-
* a chunk pointer to a caller. However, to reduce client request traffic,
75-
* it is kept DEFINED in chunks on the free list.
76-
*
77-
* The rounded-up capacity of the chunk usually acts as a post-allocation
78-
* NOACCESS region. If the request consumes precisely the entire chunk,
79-
* there is no such region; another chunk header may immediately follow. In
80-
* that case, Valgrind will not detect access beyond the end of the chunk.
81-
*
82-
* See also the cooperating Valgrind client requests in mcxt.c.
83-
*
8444
*-------------------------------------------------------------------------
8545
*/
8646

@@ -296,10 +256,10 @@ static const unsigned char LogTable256[256] =
296256
*/
297257
#ifdef HAVE_ALLOCINFO
298258
#define AllocFreeInfo(_cxt, _chunk) \
299-
fprintf(stderr, "AllocFree: %s: %p, %d\n", \
259+
fprintf(stderr, "AllocFree: %s: %p, %zu\n", \
300260
(_cxt)->header.name, (_chunk), (_chunk)->size)
301261
#define AllocAllocInfo(_cxt, _chunk) \
302-
fprintf(stderr, "AllocAlloc: %s: %p, %d\n", \
262+
fprintf(stderr, "AllocAlloc: %s: %p, %zu\n", \
303263
(_cxt)->header.name, (_chunk), (_chunk)->size)
304264
#else
305265
#define AllocFreeInfo(_cxt, _chunk)
@@ -345,77 +305,6 @@ AllocSetFreeIndex(Size size)
345305
return idx;
346306
}
347307

348-
#ifdef CLOBBER_FREED_MEMORY
349-
350-
/* Wipe freed memory for debugging purposes */
351-
static void
352-
wipe_mem(void *ptr, size_t size)
353-
{
354-
VALGRIND_MAKE_MEM_UNDEFINED(ptr, size);
355-
memset(ptr, 0x7F, size);
356-
VALGRIND_MAKE_MEM_NOACCESS(ptr, size);
357-
}
358-
#endif
359-
360-
#ifdef MEMORY_CONTEXT_CHECKING
361-
static void
362-
set_sentinel(void *base, Size offset)
363-
{
364-
char *ptr = (char *) base + offset;
365-
366-
VALGRIND_MAKE_MEM_UNDEFINED(ptr, 1);
367-
*ptr = 0x7E;
368-
VALGRIND_MAKE_MEM_NOACCESS(ptr, 1);
369-
}
370-
371-
static bool
372-
sentinel_ok(const void *base, Size offset)
373-
{
374-
const char *ptr = (const char *) base + offset;
375-
bool ret;
376-
377-
VALGRIND_MAKE_MEM_DEFINED(ptr, 1);
378-
ret = *ptr == 0x7E;
379-
VALGRIND_MAKE_MEM_NOACCESS(ptr, 1);
380-
381-
return ret;
382-
}
383-
#endif
384-
385-
#ifdef RANDOMIZE_ALLOCATED_MEMORY
386-
387-
/*
388-
* Fill a just-allocated piece of memory with "random" data. It's not really
389-
* very random, just a repeating sequence with a length that's prime. What
390-
* we mainly want out of it is to have a good probability that two palloc's
391-
* of the same number of bytes start out containing different data.
392-
*
393-
* The region may be NOACCESS, so make it UNDEFINED first to avoid errors as
394-
* we fill it. Filling the region makes it DEFINED, so make it UNDEFINED
395-
* again afterward. Whether to finally make it UNDEFINED or NOACCESS is
396-
* fairly arbitrary. UNDEFINED is more convenient for AllocSetRealloc(), and
397-
* other callers have no preference.
398-
*/
399-
static void
400-
randomize_mem(char *ptr, size_t size)
401-
{
402-
static int save_ctr = 1;
403-
size_t remaining = size;
404-
int ctr;
405-
406-
ctr = save_ctr;
407-
VALGRIND_MAKE_MEM_UNDEFINED(ptr, size);
408-
while (remaining-- > 0)
409-
{
410-
*ptr++ = ctr;
411-
if (++ctr > 251)
412-
ctr = 1;
413-
}
414-
VALGRIND_MAKE_MEM_UNDEFINED(ptr - size, size);
415-
save_ctr = ctr;
416-
}
417-
#endif /* RANDOMIZE_ALLOCATED_MEMORY */
418-
419308

420309
/*
421310
* Public routines

src/backend/utils/mmgr/memdebug.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* memdebug.c
4+
* Declarations used in memory context implementations, not part of the
5+
* public API of the memory management subsystem.
6+
*
7+
*
8+
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
9+
* Portions Copyright (c) 1994, Regents of the University of California
10+
*
11+
* src/backend/utils/memdebug.c
12+
*
13+
*
14+
* About CLOBBER_FREED_MEMORY:
15+
*
16+
* If this symbol is defined, all freed memory is overwritten with 0x7F's.
17+
* This is useful for catching places that reference already-freed memory.
18+
*
19+
* About MEMORY_CONTEXT_CHECKING:
20+
*
21+
* Since we usually round request sizes up to the next power of 2, there
22+
* is often some unused space immediately after a requested data area.
23+
* Thus, if someone makes the common error of writing past what they've
24+
* requested, the problem is likely to go unnoticed ... until the day when
25+
* there *isn't* any wasted space, perhaps because of different memory
26+
* alignment on a new platform, or some other effect. To catch this sort
27+
* of problem, the MEMORY_CONTEXT_CHECKING option stores 0x7E just beyond
28+
* the requested space whenever the request is less than the actual chunk
29+
* size, and verifies that the byte is undamaged when the chunk is freed.
30+
*
31+
*
32+
* About USE_VALGRIND and Valgrind client requests:
33+
*
34+
* Valgrind provides "client request" macros that exchange information with
35+
* the host Valgrind (if any). Under !USE_VALGRIND, memdebug.h stubs out
36+
* currently-used macros.
37+
*
38+
* When running under Valgrind, we want a NOACCESS memory region both before
39+
* and after the allocation. The chunk header is tempting as the preceding
40+
* region, but mcxt.c expects to able to examine the standard chunk header
41+
* fields. Therefore, we use, when available, the requested_size field and
42+
* any subsequent padding. requested_size is made NOACCESS before returning
43+
* a chunk pointer to a caller. However, to reduce client request traffic,
44+
* it is kept DEFINED in chunks on the free list.
45+
*
46+
* The rounded-up capacity of the chunk usually acts as a post-allocation
47+
* NOACCESS region. If the request consumes precisely the entire chunk,
48+
* there is no such region; another chunk header may immediately follow. In
49+
* that case, Valgrind will not detect access beyond the end of the chunk.
50+
*
51+
* See also the cooperating Valgrind client requests in mcxt.c.
52+
*
53+
*-------------------------------------------------------------------------
54+
*/
55+
56+
#include "postgres.h"
57+
58+
#include "utils/memdebug.h"
59+
60+
#ifdef RANDOMIZE_ALLOCATED_MEMORY
61+
62+
/*
63+
* Fill a just-allocated piece of memory with "random" data. It's not really
64+
* very random, just a repeating sequence with a length that's prime. What
65+
* we mainly want out of it is to have a good probability that two palloc's
66+
* of the same number of bytes start out containing different data.
67+
*
68+
* The region may be NOACCESS, so make it UNDEFINED first to avoid errors as
69+
* we fill it. Filling the region makes it DEFINED, so make it UNDEFINED
70+
* again afterward. Whether to finally make it UNDEFINED or NOACCESS is
71+
* fairly arbitrary. UNDEFINED is more convenient for SlabRealloc(), and
72+
* other callers have no preference.
73+
*/
74+
void
75+
randomize_mem(char *ptr, size_t size)
76+
{
77+
static int save_ctr = 1;
78+
size_t remaining = size;
79+
int ctr;
80+
81+
ctr = save_ctr;
82+
VALGRIND_MAKE_MEM_UNDEFINED(ptr, size);
83+
while (remaining-- > 0)
84+
{
85+
*ptr++ = ctr;
86+
if (++ctr > 251)
87+
ctr = 1;
88+
}
89+
VALGRIND_MAKE_MEM_UNDEFINED(ptr - size, size);
90+
save_ctr = ctr;
91+
}
92+
93+
#endif /* RANDOMIZE_ALLOCATED_MEMORY */

src/include/utils/memdebug.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,52 @@
3131
#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size) do {} while (0)
3232
#endif
3333

34+
35+
#ifdef CLOBBER_FREED_MEMORY
36+
37+
/* Wipe freed memory for debugging purposes */
38+
static inline void
39+
wipe_mem(void *ptr, size_t size)
40+
{
41+
VALGRIND_MAKE_MEM_UNDEFINED(ptr, size);
42+
memset(ptr, 0x7F, size);
43+
VALGRIND_MAKE_MEM_NOACCESS(ptr, size);
44+
}
45+
46+
#endif /* CLOBBER_FREED_MEMORY */
47+
48+
#ifdef MEMORY_CONTEXT_CHECKING
49+
50+
static inline void
51+
set_sentinel(void *base, Size offset)
52+
{
53+
char *ptr = (char *) base + offset;
54+
55+
VALGRIND_MAKE_MEM_UNDEFINED(ptr, 1);
56+
*ptr = 0x7E;
57+
VALGRIND_MAKE_MEM_NOACCESS(ptr, 1);
58+
}
59+
60+
static inline bool
61+
sentinel_ok(const void *base, Size offset)
62+
{
63+
const char *ptr = (const char *) base + offset;
64+
bool ret;
65+
66+
VALGRIND_MAKE_MEM_DEFINED(ptr, 1);
67+
ret = *ptr == 0x7E;
68+
VALGRIND_MAKE_MEM_NOACCESS(ptr, 1);
69+
70+
return ret;
71+
}
72+
73+
#endif /* MEMORY_CONTEXT_CHECKING */
74+
75+
#ifdef RANDOMIZE_ALLOCATED_MEMORY
76+
77+
void randomize_mem(char *ptr, size_t size);
78+
79+
#endif /* RANDOMIZE_ALLOCATED_MEMORY */
80+
81+
3482
#endif /* MEMDEBUG_H */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy