@@ -1110,62 +1110,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
11101110 set -> header .name , chunk );
11111111#endif
11121112
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-
11631113 if (oldsize > set -> allocChunkLimit )
11641114 {
11651115 /*
11661116 * 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.
11691119 */
11701120 AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
11711121 Size chksize ;
@@ -1180,11 +1130,19 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
11801130 if (block -> aset != set ||
11811131 block -> freeptr != block -> endptr ||
11821132 block -> freeptr != ((char * ) block ) +
1183- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1133+ (oldsize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
11841134 elog (ERROR , "could not find block containing chunk %p" , chunk );
11851135
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+
11861145 /* Do the realloc */
1187- chksize = MAXALIGN (size );
11881146 blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ;
11891147 oldblksize = block -> endptr - ((char * )block );
11901148
@@ -1214,17 +1172,21 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
12141172#ifdef MEMORY_CONTEXT_CHECKING
12151173#ifdef RANDOMIZE_ALLOCATED_MEMORY
12161174 /* 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 );
12191178#endif
12201179
12211180 /*
1222- * realloc() (or randomize_mem()) will have left the newly-allocated
1181+ * realloc() (or randomize_mem()) will have left any newly-allocated
12231182 * part UNDEFINED, but we may need to adjust trailing bytes from the
12241183 * old allocation.
12251184 */
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
12281190
12291191 chunk -> requested_size = size ;
12301192
@@ -1249,15 +1211,65 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
12491211
12501212 return pointer ;
12511213 }
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+ }
12521264 else
12531265 {
12541266 /*
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
12611273 * palloc/repalloc/pfree: the eventually freed chunks go into the
12621274 * wrong freelist for the next initial palloc request, and so we leak
12631275 * memory indefinitely. See pgsql-hackers archives for 2007-08-11.)
0 commit comments