@@ -1084,62 +1084,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1084
1084
set -> header .name , chunk );
1085
1085
#endif
1086
1086
1087
- /*
1088
- * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
1089
- * allocated area already is >= the new size. (In particular, we always
1090
- * fall out here if the requested size is a decrease.)
1091
- */
1092
- if (oldsize >= size )
1093
- {
1094
- #ifdef MEMORY_CONTEXT_CHECKING
1095
- Size oldrequest = chunk -> requested_size ;
1096
-
1097
- #ifdef RANDOMIZE_ALLOCATED_MEMORY
1098
- /* We can only fill the extra space if we know the prior request */
1099
- if (size > oldrequest )
1100
- randomize_mem ((char * ) pointer + oldrequest ,
1101
- size - oldrequest );
1102
- #endif
1103
-
1104
- chunk -> requested_size = size ;
1105
-
1106
- /*
1107
- * If this is an increase, mark any newly-available part UNDEFINED.
1108
- * Otherwise, mark the obsolete part NOACCESS.
1109
- */
1110
- if (size > oldrequest )
1111
- VALGRIND_MAKE_MEM_UNDEFINED ((char * ) pointer + oldrequest ,
1112
- size - oldrequest );
1113
- else
1114
- VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size ,
1115
- oldsize - size );
1116
-
1117
- /* set mark to catch clobber of "unused" space */
1118
- if (size < oldsize )
1119
- set_sentinel (pointer , size );
1120
- #else /* !MEMORY_CONTEXT_CHECKING */
1121
-
1122
- /*
1123
- * We don't have the information to determine whether we're growing
1124
- * the old request or shrinking it, so we conservatively mark the
1125
- * entire new allocation DEFINED.
1126
- */
1127
- VALGRIND_MAKE_MEM_NOACCESS (pointer , oldsize );
1128
- VALGRIND_MAKE_MEM_DEFINED (pointer , size );
1129
- #endif
1130
-
1131
- /* Disallow external access to private part of chunk header. */
1132
- VALGRIND_MAKE_MEM_NOACCESS (chunk , ALLOCCHUNK_PRIVATE_LEN );
1133
-
1134
- return pointer ;
1135
- }
1136
-
1137
1087
if (oldsize > set -> allocChunkLimit )
1138
1088
{
1139
1089
/*
1140
1090
* The chunk must have been allocated as a single-chunk block. Use
1141
- * realloc() to make the containing block bigger with minimum space
1142
- * wastage.
1091
+ * realloc() to make the containing block bigger, or smaller, with
1092
+ * minimum space wastage.
1143
1093
*/
1144
1094
AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
1145
1095
Size chksize ;
@@ -1153,11 +1103,19 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1153
1103
if (block -> aset != set ||
1154
1104
block -> freeptr != block -> endptr ||
1155
1105
block -> freeptr != ((char * ) block ) +
1156
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1106
+ (oldsize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1157
1107
elog (ERROR , "could not find block containing chunk %p" , chunk );
1158
1108
1109
+ /*
1110
+ * Even if the new request is less than set->allocChunkLimit, we stick
1111
+ * with the single-chunk block approach. Therefore we need
1112
+ * chunk->size to be bigger than set->allocChunkLimit, so we don't get
1113
+ * confused about the chunk's status in future calls.
1114
+ */
1115
+ chksize = Max (size , set -> allocChunkLimit + 1 );
1116
+ chksize = MAXALIGN (chksize );
1117
+
1159
1118
/* Do the realloc */
1160
- chksize = MAXALIGN (size );
1161
1119
blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ;
1162
1120
block = (AllocBlock ) realloc (block , blksize );
1163
1121
if (block == NULL )
@@ -1182,17 +1140,21 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1182
1140
#ifdef MEMORY_CONTEXT_CHECKING
1183
1141
#ifdef RANDOMIZE_ALLOCATED_MEMORY
1184
1142
/* We can only fill the extra space if we know the prior request */
1185
- randomize_mem ((char * ) pointer + chunk -> requested_size ,
1186
- size - chunk -> requested_size );
1143
+ if (size > chunk -> requested_size )
1144
+ randomize_mem ((char * ) pointer + chunk -> requested_size ,
1145
+ size - chunk -> requested_size );
1187
1146
#endif
1188
1147
1189
1148
/*
1190
- * realloc() (or randomize_mem()) will have left the newly-allocated
1149
+ * realloc() (or randomize_mem()) will have left any newly-allocated
1191
1150
* part UNDEFINED, but we may need to adjust trailing bytes from the
1192
1151
* old allocation.
1193
1152
*/
1194
- VALGRIND_MAKE_MEM_UNDEFINED ((char * ) pointer + chunk -> requested_size ,
1195
- oldsize - chunk -> requested_size );
1153
+ #ifdef USE_VALGRIND
1154
+ if (oldsize > chunk -> requested_size )
1155
+ VALGRIND_MAKE_MEM_UNDEFINED ((char * ) pointer + chunk -> requested_size ,
1156
+ oldsize - chunk -> requested_size );
1157
+ #endif
1196
1158
1197
1159
chunk -> requested_size = size ;
1198
1160
@@ -1217,15 +1179,65 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1217
1179
1218
1180
return pointer ;
1219
1181
}
1182
+
1183
+ /*
1184
+ * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
1185
+ * allocated area already is >= the new size. (In particular, we will
1186
+ * fall out here if the requested size is a decrease.)
1187
+ */
1188
+ else if (oldsize >= size )
1189
+ {
1190
+ #ifdef MEMORY_CONTEXT_CHECKING
1191
+ Size oldrequest = chunk -> requested_size ;
1192
+
1193
+ #ifdef RANDOMIZE_ALLOCATED_MEMORY
1194
+ /* We can only fill the extra space if we know the prior request */
1195
+ if (size > oldrequest )
1196
+ randomize_mem ((char * ) pointer + oldrequest ,
1197
+ size - oldrequest );
1198
+ #endif
1199
+
1200
+ chunk -> requested_size = size ;
1201
+
1202
+ /*
1203
+ * If this is an increase, mark any newly-available part UNDEFINED.
1204
+ * Otherwise, mark the obsolete part NOACCESS.
1205
+ */
1206
+ if (size > oldrequest )
1207
+ VALGRIND_MAKE_MEM_UNDEFINED ((char * ) pointer + oldrequest ,
1208
+ size - oldrequest );
1209
+ else
1210
+ VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size ,
1211
+ oldsize - size );
1212
+
1213
+ /* set mark to catch clobber of "unused" space */
1214
+ if (size < oldsize )
1215
+ set_sentinel (pointer , size );
1216
+ #else /* !MEMORY_CONTEXT_CHECKING */
1217
+
1218
+ /*
1219
+ * We don't have the information to determine whether we're growing
1220
+ * the old request or shrinking it, so we conservatively mark the
1221
+ * entire new allocation DEFINED.
1222
+ */
1223
+ VALGRIND_MAKE_MEM_NOACCESS (pointer , oldsize );
1224
+ VALGRIND_MAKE_MEM_DEFINED (pointer , size );
1225
+ #endif
1226
+
1227
+ /* Disallow external access to private part of chunk header. */
1228
+ VALGRIND_MAKE_MEM_NOACCESS (chunk , ALLOCCHUNK_PRIVATE_LEN );
1229
+
1230
+ return pointer ;
1231
+ }
1220
1232
else
1221
1233
{
1222
1234
/*
1223
- * Small- chunk case. We just do this by brute force, ie, allocate a
1224
- * new chunk and copy the data. Since we know the existing data isn't
1225
- * huge, this won't involve any great memcpy expense, so it's not
1226
- * worth being smarter. (At one time we tried to avoid memcpy when it
1227
- * was possible to enlarge the chunk in-place, but that turns out to
1228
- * misbehave unpleasantly for repeated cycles of
1235
+ * Enlarge-a-small- chunk case. We just do this by brute force, ie,
1236
+ * allocate a new chunk and copy the data. Since we know the existing
1237
+ * data isn't huge, this won't involve any great memcpy expense, so
1238
+ * it's not worth being smarter. (At one time we tried to avoid
1239
+ * memcpy when it was possible to enlarge the chunk in-place, but that
1240
+ * turns out to misbehave unpleasantly for repeated cycles of
1229
1241
* palloc/repalloc/pfree: the eventually freed chunks go into the
1230
1242
* wrong freelist for the next initial palloc request, and so we leak
1231
1243
* memory indefinitely. See pgsql-hackers archives for 2007-08-11.)
0 commit comments