@@ -932,61 +932,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
932
932
set -> header .name ,chunk );
933
933
#endif
934
934
935
- /*
936
- * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
937
- * allocated area already is >= the new size. (In particular, we always
938
- * fall out here if the requested size is a decrease.)
939
- */
940
- if (oldsize >=size )
941
- {
942
- #ifdef MEMORY_CONTEXT_CHECKING
943
- Size oldrequest = chunk -> requested_size ;
944
-
945
- #ifdef RANDOMIZE_ALLOCATED_MEMORY
946
- /* We can only fill the extra space if we know the prior request */
947
- if (size > oldrequest )
948
- randomize_mem ((char * )pointer + oldrequest ,
949
- size - oldrequest );
950
- #endif
951
-
952
- chunk -> requested_size = size ;
953
- VALGRIND_MAKE_MEM_NOACCESS (& chunk -> requested_size ,
954
- sizeof (chunk -> requested_size ));
955
-
956
- /*
957
- * If this is an increase, mark any newly-available part UNDEFINED.
958
- * Otherwise, mark the obsolete part NOACCESS.
959
- */
960
- if (size > oldrequest )
961
- VALGRIND_MAKE_MEM_UNDEFINED ((char * )pointer + oldrequest ,
962
- size - oldrequest );
963
- else
964
- VALGRIND_MAKE_MEM_NOACCESS ((char * )pointer + size ,
965
- oldsize - size );
966
-
967
- /* set mark to catch clobber of "unused" space */
968
- if (size < oldsize )
969
- set_sentinel (pointer ,size );
970
- #else /* !MEMORY_CONTEXT_CHECKING */
971
-
972
- /*
973
- * We don't have the information to determine whether we're growing
974
- * the old request or shrinking it, so we conservatively mark the
975
- * entire new allocation DEFINED.
976
- */
977
- VALGRIND_MAKE_MEM_NOACCESS (pointer ,oldsize );
978
- VALGRIND_MAKE_MEM_DEFINED (pointer ,size );
979
- #endif
980
-
981
- return pointer ;
982
- }
983
-
984
935
if (oldsize > set -> allocChunkLimit )
985
936
{
986
937
/*
987
938
* The chunk must have been allocated as a single-chunk block. Use
988
- * realloc() to make the containing block bigger with minimum space
989
- * wastage.
939
+ * realloc() to make the containing block bigger, or smaller, with
940
+ *minimum space wastage.
990
941
*/
991
942
AllocBlock block = (AllocBlock ) (((char * )chunk )- ALLOC_BLOCKHDRSZ );
992
943
Size chksize ;
@@ -1000,11 +951,19 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1000
951
if (block -> aset != set ||
1001
952
block -> freeptr != block -> endptr ||
1002
953
block -> freeptr != ((char * )block )+
1003
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
954
+ (oldsize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1004
955
elog (ERROR ,"could not find block containing chunk %p" ,chunk );
1005
956
957
+ /*
958
+ * Even if the new request is less than set->allocChunkLimit, we stick
959
+ * with the single-chunk block approach. Therefore we need
960
+ * chunk->size to be bigger than set->allocChunkLimit, so we don't get
961
+ * confused about the chunk's status in future calls.
962
+ */
963
+ chksize = Max (size ,set -> allocChunkLimit + 1 );
964
+ chksize = MAXALIGN (chksize );
965
+
1006
966
/* Do the realloc */
1007
- chksize = MAXALIGN (size );
1008
967
blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ;
1009
968
block = (AllocBlock )realloc (block ,blksize );
1010
969
if (block == NULL )
@@ -1025,17 +984,21 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1025
984
#ifdef MEMORY_CONTEXT_CHECKING
1026
985
#ifdef RANDOMIZE_ALLOCATED_MEMORY
1027
986
/* We can only fill the extra space if we know the prior request */
1028
- randomize_mem ((char * )pointer + chunk -> requested_size ,
1029
- size - chunk -> requested_size );
987
+ if (size > chunk -> requested_size )
988
+ randomize_mem ((char * )pointer + chunk -> requested_size ,
989
+ size - chunk -> requested_size );
1030
990
#endif
1031
991
1032
992
/*
1033
- * realloc() (or randomize_mem()) will have leftthe newly-allocated
993
+ * realloc() (or randomize_mem()) will have leftany newly-allocated
1034
994
* part UNDEFINED, but we may need to adjust trailing bytes from the
1035
995
* old allocation.
1036
996
*/
1037
- VALGRIND_MAKE_MEM_UNDEFINED ((char * )pointer + chunk -> requested_size ,
1038
- oldsize - chunk -> requested_size );
997
+ #ifdef USE_VALGRIND
998
+ if (oldsize > chunk -> requested_size )
999
+ VALGRIND_MAKE_MEM_UNDEFINED ((char * )pointer + chunk -> requested_size ,
1000
+ oldsize - chunk -> requested_size );
1001
+ #endif
1039
1002
1040
1003
chunk -> requested_size = size ;
1041
1004
VALGRIND_MAKE_MEM_NOACCESS (& chunk -> requested_size ,
@@ -1059,15 +1022,64 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1059
1022
1060
1023
return pointer ;
1061
1024
}
1025
+
1026
+ /*
1027
+ * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
1028
+ * allocated area already is >= the new size. (In particular, we will
1029
+ * fall out here if the requested size is a decrease.)
1030
+ */
1031
+ else if (oldsize >=size )
1032
+ {
1033
+ #ifdef MEMORY_CONTEXT_CHECKING
1034
+ Size oldrequest = chunk -> requested_size ;
1035
+
1036
+ #ifdef RANDOMIZE_ALLOCATED_MEMORY
1037
+ /* We can only fill the extra space if we know the prior request */
1038
+ if (size > oldrequest )
1039
+ randomize_mem ((char * )pointer + oldrequest ,
1040
+ size - oldrequest );
1041
+ #endif
1042
+
1043
+ chunk -> requested_size = size ;
1044
+ VALGRIND_MAKE_MEM_NOACCESS (& chunk -> requested_size ,
1045
+ sizeof (chunk -> requested_size ));
1046
+
1047
+ /*
1048
+ * If this is an increase, mark any newly-available part UNDEFINED.
1049
+ * Otherwise, mark the obsolete part NOACCESS.
1050
+ */
1051
+ if (size > oldrequest )
1052
+ VALGRIND_MAKE_MEM_UNDEFINED ((char * )pointer + oldrequest ,
1053
+ size - oldrequest );
1054
+ else
1055
+ VALGRIND_MAKE_MEM_NOACCESS ((char * )pointer + size ,
1056
+ oldsize - size );
1057
+
1058
+ /* set mark to catch clobber of "unused" space */
1059
+ if (size < oldsize )
1060
+ set_sentinel (pointer ,size );
1061
+ #else /* !MEMORY_CONTEXT_CHECKING */
1062
+
1063
+ /*
1064
+ * We don't have the information to determine whether we're growing
1065
+ * the old request or shrinking it, so we conservatively mark the
1066
+ * entire new allocation DEFINED.
1067
+ */
1068
+ VALGRIND_MAKE_MEM_NOACCESS (pointer ,oldsize );
1069
+ VALGRIND_MAKE_MEM_DEFINED (pointer ,size );
1070
+ #endif
1071
+
1072
+ return pointer ;
1073
+ }
1062
1074
else
1063
1075
{
1064
1076
/*
1065
- *Small- chunk case. We just do this by brute force, ie, allocate a
1066
- * new chunk and copy the data. Since we know the existing data isn't
1067
- * huge, this won't involve any great memcpy expense, so it's not
1068
- * worth being smarter. (At one time we tried to avoid memcpy when it
1069
- * was possible to enlarge the chunk in-place, but that turns out to
1070
- * misbehave unpleasantly for repeated cycles of
1077
+ *Enlarge-a-small- chunk case. We just do this by brute force, ie,
1078
+ *allocate a new chunk and copy the data. Since we know the existing
1079
+ *data isn't huge, this won't involve any great memcpy expense, so
1080
+ *it's not worth being smarter. (At one time we tried to avoid
1081
+ *memcpy when it was possible to enlarge the chunk in-place, but that
1082
+ *turns out to misbehave unpleasantly for repeated cycles of
1071
1083
* palloc/repalloc/pfree: the eventually freed chunks go into the
1072
1084
* wrong freelist for the next initial palloc request, and so we leak
1073
1085
* memory indefinitely. See pgsql-hackers archives for 2007-08-11.)