@@ -1110,62 +1110,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1110
1110
set -> header .name , chunk );
1111
1111
#endif
1112
1112
1113
- /*
1114
- * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
1115
- * allocated area already is >= the new size. (In particular, we always
1116
- * fall out here if the requested size is a decrease.)
1117
- */
1118
- if (oldsize >= size )
1119
- {
1120
- #ifdef MEMORY_CONTEXT_CHECKING
1121
- Size oldrequest = chunk -> requested_size ;
1122
-
1123
- #ifdef RANDOMIZE_ALLOCATED_MEMORY
1124
- /* We can only fill the extra space if we know the prior request */
1125
- if (size > oldrequest )
1126
- randomize_mem ((char * ) pointer + oldrequest ,
1127
- size - oldrequest );
1128
- #endif
1129
-
1130
- chunk -> requested_size = size ;
1131
-
1132
- /*
1133
- * If this is an increase, mark any newly-available part UNDEFINED.
1134
- * Otherwise, mark the obsolete part NOACCESS.
1135
- */
1136
- if (size > oldrequest )
1137
- VALGRIND_MAKE_MEM_UNDEFINED ((char * ) pointer + oldrequest ,
1138
- size - oldrequest );
1139
- else
1140
- VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size ,
1141
- oldsize - size );
1142
-
1143
- /* set mark to catch clobber of "unused" space */
1144
- if (size < oldsize )
1145
- set_sentinel (pointer , size );
1146
- #else /* !MEMORY_CONTEXT_CHECKING */
1147
-
1148
- /*
1149
- * We don't have the information to determine whether we're growing
1150
- * the old request or shrinking it, so we conservatively mark the
1151
- * entire new allocation DEFINED.
1152
- */
1153
- VALGRIND_MAKE_MEM_NOACCESS (pointer , oldsize );
1154
- VALGRIND_MAKE_MEM_DEFINED (pointer , size );
1155
- #endif
1156
-
1157
- /* Disallow external access to private part of chunk header. */
1158
- VALGRIND_MAKE_MEM_NOACCESS (chunk , ALLOCCHUNK_PRIVATE_LEN );
1159
-
1160
- return pointer ;
1161
- }
1162
-
1163
1113
if (oldsize > set -> allocChunkLimit )
1164
1114
{
1165
1115
/*
1166
1116
* The chunk must have been allocated as a single-chunk block. Use
1167
- * realloc() to make the containing block bigger with minimum space
1168
- * wastage.
1117
+ * realloc() to make the containing block bigger, or smaller, with
1118
+ * minimum space wastage.
1169
1119
*/
1170
1120
AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
1171
1121
Size chksize ;
@@ -1180,11 +1130,19 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1180
1130
if (block -> aset != set ||
1181
1131
block -> freeptr != block -> endptr ||
1182
1132
block -> freeptr != ((char * ) block ) +
1183
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1133
+ (oldsize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1184
1134
elog (ERROR , "could not find block containing chunk %p" , chunk );
1185
1135
1136
+ /*
1137
+ * Even if the new request is less than set->allocChunkLimit, we stick
1138
+ * with the single-chunk block approach. Therefore we need
1139
+ * chunk->size to be bigger than set->allocChunkLimit, so we don't get
1140
+ * confused about the chunk's status in future calls.
1141
+ */
1142
+ chksize = Max (size , set -> allocChunkLimit + 1 );
1143
+ chksize = MAXALIGN (chksize );
1144
+
1186
1145
/* Do the realloc */
1187
- chksize = MAXALIGN (size );
1188
1146
blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ;
1189
1147
oldblksize = block -> endptr - ((char * )block );
1190
1148
@@ -1214,17 +1172,21 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1214
1172
#ifdef MEMORY_CONTEXT_CHECKING
1215
1173
#ifdef RANDOMIZE_ALLOCATED_MEMORY
1216
1174
/* We can only fill the extra space if we know the prior request */
1217
- randomize_mem ((char * ) pointer + chunk -> requested_size ,
1218
- size - chunk -> requested_size );
1175
+ if (size > chunk -> requested_size )
1176
+ randomize_mem ((char * ) pointer + chunk -> requested_size ,
1177
+ size - chunk -> requested_size );
1219
1178
#endif
1220
1179
1221
1180
/*
1222
- * realloc() (or randomize_mem()) will have left the newly-allocated
1181
+ * realloc() (or randomize_mem()) will have left any newly-allocated
1223
1182
* part UNDEFINED, but we may need to adjust trailing bytes from the
1224
1183
* old allocation.
1225
1184
*/
1226
- VALGRIND_MAKE_MEM_UNDEFINED ((char * ) pointer + chunk -> requested_size ,
1227
- oldsize - chunk -> requested_size );
1185
+ #ifdef USE_VALGRIND
1186
+ if (oldsize > chunk -> requested_size )
1187
+ VALGRIND_MAKE_MEM_UNDEFINED ((char * ) pointer + chunk -> requested_size ,
1188
+ oldsize - chunk -> requested_size );
1189
+ #endif
1228
1190
1229
1191
chunk -> requested_size = size ;
1230
1192
@@ -1249,15 +1211,65 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1249
1211
1250
1212
return pointer ;
1251
1213
}
1214
+
1215
+ /*
1216
+ * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
1217
+ * allocated area already is >= the new size. (In particular, we will
1218
+ * fall out here if the requested size is a decrease.)
1219
+ */
1220
+ else if (oldsize >= size )
1221
+ {
1222
+ #ifdef MEMORY_CONTEXT_CHECKING
1223
+ Size oldrequest = chunk -> requested_size ;
1224
+
1225
+ #ifdef RANDOMIZE_ALLOCATED_MEMORY
1226
+ /* We can only fill the extra space if we know the prior request */
1227
+ if (size > oldrequest )
1228
+ randomize_mem ((char * ) pointer + oldrequest ,
1229
+ size - oldrequest );
1230
+ #endif
1231
+
1232
+ chunk -> requested_size = size ;
1233
+
1234
+ /*
1235
+ * If this is an increase, mark any newly-available part UNDEFINED.
1236
+ * Otherwise, mark the obsolete part NOACCESS.
1237
+ */
1238
+ if (size > oldrequest )
1239
+ VALGRIND_MAKE_MEM_UNDEFINED ((char * ) pointer + oldrequest ,
1240
+ size - oldrequest );
1241
+ else
1242
+ VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size ,
1243
+ oldsize - size );
1244
+
1245
+ /* set mark to catch clobber of "unused" space */
1246
+ if (size < oldsize )
1247
+ set_sentinel (pointer , size );
1248
+ #else /* !MEMORY_CONTEXT_CHECKING */
1249
+
1250
+ /*
1251
+ * We don't have the information to determine whether we're growing
1252
+ * the old request or shrinking it, so we conservatively mark the
1253
+ * entire new allocation DEFINED.
1254
+ */
1255
+ VALGRIND_MAKE_MEM_NOACCESS (pointer , oldsize );
1256
+ VALGRIND_MAKE_MEM_DEFINED (pointer , size );
1257
+ #endif
1258
+
1259
+ /* Disallow external access to private part of chunk header. */
1260
+ VALGRIND_MAKE_MEM_NOACCESS (chunk , ALLOCCHUNK_PRIVATE_LEN );
1261
+
1262
+ return pointer ;
1263
+ }
1252
1264
else
1253
1265
{
1254
1266
/*
1255
- * Small- chunk case. We just do this by brute force, ie, allocate a
1256
- * new chunk and copy the data. Since we know the existing data isn't
1257
- * huge, this won't involve any great memcpy expense, so it's not
1258
- * worth being smarter. (At one time we tried to avoid memcpy when it
1259
- * was possible to enlarge the chunk in-place, but that turns out to
1260
- * misbehave unpleasantly for repeated cycles of
1267
+ * Enlarge-a-small- chunk case. We just do this by brute force, ie,
1268
+ * allocate a new chunk and copy the data. Since we know the existing
1269
+ * data isn't huge, this won't involve any great memcpy expense, so
1270
+ * it's not worth being smarter. (At one time we tried to avoid
1271
+ * memcpy when it was possible to enlarge the chunk in-place, but that
1272
+ * turns out to misbehave unpleasantly for repeated cycles of
1261
1273
* palloc/repalloc/pfree: the eventually freed chunks go into the
1262
1274
* wrong freelist for the next initial palloc request, and so we leak
1263
1275
* memory indefinitely. See pgsql-hackers archives for 2007-08-11.)
0 commit comments