Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit88177f7

Browse files
committed
Code review for palloc0 patch --- avoid dangerous and unnecessary
practice of evaluating MemSet's arguments multiple times, except forthe special case of newNode(), where we can assume the argument isa constant sizeof() operator.Also, add GetMemoryChunkContext() to mcxt.c's API, in preparation forfixing recent GEQO breakage.
1 parente64c7fe commit88177f7

File tree

6 files changed

+160
-52
lines changed

6 files changed

+160
-52
lines changed

‎src/backend/nodes/nodes.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,19 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/nodes/nodes.c,v 1.18 2002/11/10 02:17:25 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/nodes/nodes.c,v 1.19 2002/12/16 16:22:46 tgl Exp $
1313
*
1414
* HISTORY
1515
* Andrew YuOct 20, 1994file creation
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
1919
#include"postgres.h"
20+
2021
#include"nodes/nodes.h"
2122

2223
/*
23-
* newNode -
24-
* create a new node of the specified size and tag the node with the
25-
* specified tag.
26-
*
27-
* !WARNING!: Avoid using newNode directly. You should be using the
28-
* macro makeNode. eg. to create a Resdom node, use makeNode(Resdom)
29-
*
24+
* Support for newNode() macro
3025
*/
31-
Node*newNodeMacroHolder;
3226

27+
Node*newNodeMacroHolder;

‎src/backend/utils/mmgr/mcxt.c

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
*
1616
* IDENTIFICATION
17-
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.37 2002/12/15 21:01:34 tgl Exp $
17+
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.38 2002/12/16 16:22:46 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -257,6 +257,35 @@ GetMemoryChunkSpace(void *pointer)
257257
pointer);
258258
}
259259

260+
/*
261+
* GetMemoryChunkContext
262+
*Given a currently-allocated chunk, determine the context
263+
*it belongs to.
264+
*/
265+
MemoryContext
266+
GetMemoryChunkContext(void*pointer)
267+
{
268+
StandardChunkHeader*header;
269+
270+
/*
271+
* Try to detect bogus pointers handed to us, poorly though we can.
272+
* Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
273+
* allocated chunk.
274+
*/
275+
Assert(pointer!=NULL);
276+
Assert(pointer== (void*)MAXALIGN(pointer));
277+
278+
/*
279+
* OK, it's probably safe to look at the chunk header.
280+
*/
281+
header= (StandardChunkHeader*)
282+
((char*)pointer-STANDARDCHUNKHEADERSIZE);
283+
284+
AssertArg(MemoryContextIsValid(header->context));
285+
286+
returnheader->context;
287+
}
288+
260289
/*
261290
* MemoryContextStats
262291
*Print statistics about the named context and all its descendants.
@@ -453,25 +482,52 @@ MemoryContextAlloc(MemoryContext context, Size size)
453482
}
454483

455484
/*
456-
*MemoryContextAllocPalloc0
485+
*MemoryContextAllocZero
457486
*Like MemoryContextAlloc, but clears allocated memory
458487
*
459488
*We could just call MemoryContextAlloc then clear the memory, but this
460-
*functioniscalled too many times, so wehave a separate version.
489+
*isa very common combination, so weprovide the combined operation.
461490
*/
462491
void*
463-
MemoryContextAllocPalloc0(MemoryContextcontext,Sizesize)
492+
MemoryContextAllocZero(MemoryContextcontext,Sizesize)
464493
{
465494
void*ret;
466495

467496
AssertArg(MemoryContextIsValid(context));
468497

469498
if (!AllocSizeIsValid(size))
470-
elog(ERROR,"MemoryContextAllocZero: invalid request size %lu",
499+
elog(ERROR,"MemoryContextAlloc: invalid request size %lu",
471500
(unsigned long)size);
472501

473502
ret= (*context->methods->alloc) (context,size);
503+
504+
MemSetAligned(ret,0,size);
505+
506+
returnret;
507+
}
508+
509+
/*
510+
* MemoryContextAllocZeroAligned
511+
*MemoryContextAllocZero where length is suitable for MemSetLoop
512+
*
513+
*This might seem overly specialized, but it's not because newNode()
514+
*is so often called with compile-time-constant sizes.
515+
*/
516+
void*
517+
MemoryContextAllocZeroAligned(MemoryContextcontext,Sizesize)
518+
{
519+
void*ret;
520+
521+
AssertArg(MemoryContextIsValid(context));
522+
523+
if (!AllocSizeIsValid(size))
524+
elog(ERROR,"MemoryContextAlloc: invalid request size %lu",
525+
(unsigned long)size);
526+
527+
ret= (*context->methods->alloc) (context,size);
528+
474529
MemSetLoop(ret,0,size);
530+
475531
returnret;
476532
}
477533

‎src/include/c.h

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
15-
* $Id: c.h,v 1.133 2002/12/05 04:04:48 momjian Exp $
15+
* $Id: c.h,v 1.134 2002/12/16 16:22:46 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -579,38 +579,78 @@ typedef NameData *Name;
579579
*memset() functions. More research needs to be done, perhaps with
580580
*platform-specific MEMSET_LOOP_LIMIT values or tests in configure.
581581
*
582-
*MemSet has been split into two parts so MemSetTest can be optimized
583-
*away for constant 'val' and 'len'. This is used by palloc0().
584-
*
585-
*Note, arguments are evaluated more than once.
586-
*
587582
*bjm 2002-10-08
588583
*/
584+
#defineMemSet(start,val,len) \
585+
do \
586+
{ \
587+
int32 * _start = (int32 *) (start); \
588+
int_val = (val); \
589+
Size_len = (len); \
590+
\
591+
if ((((long) _start) & INT_ALIGN_MASK) == 0 && \
592+
(_len & INT_ALIGN_MASK) == 0 && \
593+
_val == 0 && \
594+
_len <= MEMSET_LOOP_LIMIT) \
595+
{ \
596+
int32 * _stop = (int32 *) ((char *) _start + _len); \
597+
while (_start < _stop) \
598+
*_start++ = 0; \
599+
} \
600+
else \
601+
memset((char *) _start, _val, _len); \
602+
} while (0)
603+
604+
#defineMEMSET_LOOP_LIMIT 1024
605+
606+
/*
607+
* MemSetAligned is the same as MemSet except it omits the test to see if
608+
* "start" is word-aligned. This is okay to use if the caller knows a-priori
609+
* that the pointer is suitably aligned (typically, because he just got it
610+
* from palloc(), which always delivers a max-aligned pointer).
611+
*/
612+
#defineMemSetAligned(start,val,len) \
613+
do \
614+
{ \
615+
int32 * _start = (int32 *) (start); \
616+
int_val = (val); \
617+
Size_len = (len); \
618+
\
619+
if ((_len & INT_ALIGN_MASK) == 0 && \
620+
_val == 0 && \
621+
_len <= MEMSET_LOOP_LIMIT) \
622+
{ \
623+
int32 * _stop = (int32 *) ((char *) _start + _len); \
624+
while (_start < _stop) \
625+
*_start++ = 0; \
626+
} \
627+
else \
628+
memset((char *) _start, _val, _len); \
629+
} while (0)
630+
631+
632+
/*
633+
* MemSetTest/MemSetLoop are a variant version that allow all the tests in
634+
* MemSet to be done at compile time in cases where "val" and "len" are
635+
* constants *and* we know the "start" pointer must be word-aligned.
636+
* If MemSetTest succeeds, then it is okay to use MemSetLoop, otherwise use
637+
* MemSetAligned. Beware of multiple evaluations of the arguments when using
638+
* this approach.
639+
*/
589640
#defineMemSetTest(val,len) \
590641
( ((len) & INT_ALIGN_MASK) == 0 && \
591642
(len) <= MEMSET_LOOP_LIMIT && \
592643
(val) == 0 )
593644

594645
#defineMemSetLoop(start,val,len) \
595-
do \
596-
{ \
597-
int32 * _start = (int32 *) (start); \
598-
int32 * _stop = (int32 *) ((char *) _start + (len)); \
599-
\
600-
while (_start < _stop) \
601-
*_start++ = 0; \
602-
} while (0)
603-
604-
#defineMemSet(start,val,len) \
605-
do \
606-
{ \
607-
if (MemSetTest(val, len) && ((long)(start) & INT_ALIGN_MASK) == 0 ) \
608-
MemSetLoop(start, val, len); \
609-
else \
610-
memset((char *)(start), (val), (len)); \
611-
} while (0)
612-
613-
#defineMEMSET_LOOP_LIMIT 1024
646+
do \
647+
{ \
648+
int32 * _start = (int32 *) (start); \
649+
int32 * _stop = (int32 *) ((char *) _start + (Size) (len)); \
650+
\
651+
while (_start < _stop) \
652+
*_start++ = 0; \
653+
} while (0)
614654

615655

616656
/* ----------------------------------------------------------------

‎src/include/nodes/nodes.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: nodes.h,v 1.133 2002/12/14 00:17:59 tgl Exp $
10+
* $Id: nodes.h,v 1.134 2002/12/16 16:22:46 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -293,18 +293,24 @@ typedef struct Node
293293
#definenodeTag(nodeptr)(((Node*)(nodeptr))->type)
294294

295295
/*
296+
* newNode -
297+
* create a new node of the specified size and tag the node with the
298+
* specified tag.
299+
*
300+
* !WARNING!: Avoid using newNode directly. You should be using the
301+
* macro makeNode. eg. to create a Query node, use makeNode(Query)
302+
*
296303
*There is no way to dereference the palloc'ed pointer to assign the
297-
*tag, and return the pointer itself, so we need a holder variable.
298-
*Fortunately, thisfunction isn't recursive so we just define
304+
*tag, andalsoreturn the pointer itself, so we need a holder variable.
305+
*Fortunately, thismacro isn't recursive so we just define
299306
*a global variable for this purpose.
300307
*/
301308
externNode*newNodeMacroHolder;
302309

303310
#definenewNode(size,tag) \
304311
( \
305312
AssertMacro((size) >= sizeof(Node)),/* need the tag, at least */ \
306-
\
307-
newNodeMacroHolder = (Node *) palloc0(size), \
313+
newNodeMacroHolder = (Node *) palloc0fast(size), \
308314
newNodeMacroHolder->type = (tag), \
309315
newNodeMacroHolder \
310316
)

‎src/include/utils/memutils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
13-
* $Id: memutils.h,v 1.49 2002/12/15 21:01:34 tgl Exp $
13+
* $Id: memutils.h,v 1.50 2002/12/16 16:22:46 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -83,6 +83,7 @@ extern void MemoryContextResetChildren(MemoryContext context);
8383
externvoidMemoryContextDeleteChildren(MemoryContextcontext);
8484
externvoidMemoryContextResetAndDeleteChildren(MemoryContextcontext);
8585
externSizeGetMemoryChunkSpace(void*pointer);
86+
externMemoryContextGetMemoryChunkContext(void*pointer);
8687
externvoidMemoryContextStats(MemoryContextcontext);
8788

8889
#ifdefMEMORY_CONTEXT_CHECKING

‎src/include/utils/palloc.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
2222
* Portions Copyright (c) 1994, Regents of the University of California
2323
*
24-
* $Id: palloc.h,v 1.23 2002/11/13 00:37:06 momjian Exp $
24+
* $Id: palloc.h,v 1.24 2002/12/16 16:22:46 tgl Exp $
2525
*
2626
*-------------------------------------------------------------------------
2727
*/
@@ -46,15 +46,25 @@ extern DLLIMPORT MemoryContext CurrentMemoryContext;
4646
* Fundamental memory-allocation operations (more are in utils/memutils.h)
4747
*/
4848
externvoid*MemoryContextAlloc(MemoryContextcontext,Sizesize);
49-
externvoid*MemoryContextAllocPalloc0(MemoryContextcontext,Sizesize);
49+
externvoid*MemoryContextAllocZero(MemoryContextcontext,Sizesize);
50+
externvoid*MemoryContextAllocZeroAligned(MemoryContextcontext,Sizesize);
5051

5152
#definepalloc(sz)MemoryContextAlloc(CurrentMemoryContext, (sz))
5253

53-
/* We assume palloc() is already int-aligned */
54-
#definepalloc0(sz)\
55-
( MemSetTest(0, (sz)) ? \
56-
MemoryContextAllocPalloc0(CurrentMemoryContext, (sz)) : \
57-
memset(palloc(sz), 0, (sz)))
54+
#definepalloc0(sz)MemoryContextAllocZero(CurrentMemoryContext, (sz))
55+
56+
/*
57+
* The result of palloc() is always word-aligned, so we can skip testing
58+
* alignment of the pointer when deciding which MemSet variant to use.
59+
* Note that this variant does not offer any advantage, and should not be
60+
* used, unless its "sz" argument is a compile-time constant; therefore, the
61+
* issue that it evaluates the argument multiple times isn't a problem in
62+
* practice.
63+
*/
64+
#definepalloc0fast(sz)\
65+
( MemSetTest(0, sz) ? \
66+
MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \
67+
MemoryContextAllocZero(CurrentMemoryContext, sz) )
5868

5969
externvoidpfree(void*pointer);
6070

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp