PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
aset.c File Reference
#include "postgres.h"
#include "utils/memdebug.h"
#include "utils/memutils.h"
Include dependency graph for aset.c:

Go to the source code of this file.

Data Structures

struct  AllocSetContext
 
struct  AllocBlockData
 
struct  AllocChunkData
 

Macros

#define ALLOC_MINBITS   3 /* smallest chunk size is 8 bytes */
 
#define ALLOCSET_NUM_FREELISTS   11
 
#define ALLOC_CHUNK_LIMIT   (1 << (ALLOCSET_NUM_FREELISTS-1+ALLOC_MINBITS))
 
#define ALLOC_CHUNK_FRACTION   4
 
#define ALLOC_BLOCKHDRSZ   MAXALIGN(sizeof(AllocBlockData))
 
#define ALLOC_CHUNKHDRSZ   sizeof(struct AllocChunkData)
 
#define AllocPointerIsValid(pointer)   PointerIsValid(pointer)
 
#define AllocSetIsValid(set)   PointerIsValid(set)
 
#define AllocPointerGetChunk(ptr)   ((AllocChunk)(((char *)(ptr)) - ALLOC_CHUNKHDRSZ))
 
#define AllocChunkGetPointer(chk)   ((AllocPointer)(((char *)(chk)) + ALLOC_CHUNKHDRSZ))
 
#define LT16(n)   n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
 
#define AllocFreeInfo(_cxt, _chunk)
 
#define AllocAllocInfo(_cxt, _chunk)
 

Typedefs

typedef struct AllocBlockDataAllocBlock
 
typedef struct AllocChunkDataAllocChunk
 
typedef void * AllocPointer
 
typedef struct AllocSetContext AllocSetContext
 
typedef AllocSetContextAllocSet
 
typedef struct AllocBlockData AllocBlockData
 
typedef struct AllocChunkData AllocChunkData
 

Functions

static void * AllocSetAlloc (MemoryContext context, Size size)
 
static void AllocSetFree (MemoryContext context, void *pointer)
 
static void * AllocSetRealloc (MemoryContext context, void *pointer, Size size)
 
static void AllocSetInit (MemoryContext context)
 
static void AllocSetReset (MemoryContext context)
 
static void AllocSetDelete (MemoryContext context)
 
static Size AllocSetGetChunkSpace (MemoryContext context, void *pointer)
 
static bool AllocSetIsEmpty (MemoryContext context)
 
static void AllocSetStats (MemoryContext context, int level, bool print, MemoryContextCounters *totals)
 
static int AllocSetFreeIndex (Size size)
 
MemoryContext AllocSetContextCreate (MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
 

Variables

static MemoryContextMethods AllocSetMethods
 
static const unsigned char LogTable256 [256]
 

Macro Definition Documentation

#define ALLOC_BLOCKHDRSZ   MAXALIGN(sizeof(AllocBlockData))
#define ALLOC_CHUNK_FRACTION   4

Definition at line 85 of file aset.c.

Referenced by AllocSetContextCreate().

#define ALLOC_CHUNK_LIMIT   (1 << (ALLOCSET_NUM_FREELISTS-1+ALLOC_MINBITS))

Definition at line 83 of file aset.c.

Referenced by AllocSetContextCreate().

#define ALLOC_CHUNKHDRSZ   sizeof(struct AllocChunkData)
#define ALLOC_MINBITS   3 /* smallest chunk size is 8 bytes */

Definition at line 81 of file aset.c.

Referenced by AllocSetAlloc(), and AllocSetFreeIndex().

#define AllocAllocInfo (   _cxt,
  _chunk 
)

Definition at line 259 of file aset.c.

Referenced by AllocSetAlloc().

#define AllocChunkGetPointer (   chk)    ((AllocPointer)(((char *)(chk)) + ALLOC_CHUNKHDRSZ))

Definition at line 195 of file aset.c.

Referenced by AllocSetAlloc(), and AllocSetRealloc().

#define AllocFreeInfo (   _cxt,
  _chunk 
)

Definition at line 258 of file aset.c.

Referenced by AllocSetFree().

#define AllocPointerGetChunk (   ptr)    ((AllocChunk)(((char *)(ptr)) - ALLOC_CHUNKHDRSZ))

Definition at line 193 of file aset.c.

Referenced by AllocSetFree(), AllocSetGetChunkSpace(), and AllocSetRealloc().

#define AllocPointerIsValid (   pointer)    PointerIsValid(pointer)

Definition at line 185 of file aset.c.

#define ALLOCSET_NUM_FREELISTS   11

Definition at line 82 of file aset.c.

Referenced by AllocSetFreeIndex(), and AllocSetStats().

#define AllocSetIsValid (   set)    PointerIsValid(set)

Definition at line 191 of file aset.c.

Referenced by AllocSetAlloc(), AllocSetDelete(), and AllocSetReset().

#define LT16 (   n)    n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n

Definition at line 237 of file aset.c.

Typedef Documentation

Definition at line 102 of file aset.c.

Definition at line 103 of file aset.c.

Definition at line 109 of file aset.c.

Definition at line 134 of file aset.c.

Function Documentation

static void * AllocSetAlloc ( MemoryContext  context,
Size  size 
)
static

Definition at line 562 of file aset.c.

References ALLOC_BLOCKHDRSZ, ALLOC_CHUNKHDRSZ, ALLOC_MINBITS, AllocAllocInfo, AllocChunkGetPointer, AllocSetContext::allocChunkLimit, AllocSetFreeIndex(), AllocSetIsValid, AllocBlockData::aset, AllocChunkData::aset, Assert, AssertArg, AllocSetContext::blocks, AllocBlockData::endptr, AllocSetContext::freelist, AllocBlockData::freeptr, AllocSetContext::initBlockSize, AllocSetContext::keeper, malloc, MAXALIGN, AllocSetContext::maxBlockSize, AllocBlockData::next, AllocSetContext::nextBlockSize, NULL, AllocBlockData::prev, AllocChunkData::size, VALGRIND_MAKE_MEM_NOACCESS, and VALGRIND_MAKE_MEM_UNDEFINED.

Referenced by AllocSetRealloc().

563 {
564  AllocSet set = (AllocSet) context;
565  AllocBlock block;
566  AllocChunk chunk;
567  int fidx;
568  Size chunk_size;
569  Size blksize;
570 
572 
573  /*
574  * If requested size exceeds maximum for chunks, allocate an entire block
575  * for this request.
576  */
577  if (size > set->allocChunkLimit)
578  {
579  chunk_size = MAXALIGN(size);
580  blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
581  block = (AllocBlock) malloc(blksize);
582  if (block == NULL)
583  return NULL;
584  block->aset = set;
585  block->freeptr = block->endptr = ((char *) block) + blksize;
586 
587  chunk = (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ);
588  chunk->aset = set;
589  chunk->size = chunk_size;
590 #ifdef MEMORY_CONTEXT_CHECKING
591  /* Valgrind: Will be made NOACCESS below. */
592  chunk->requested_size = size;
593  /* set mark to catch clobber of "unused" space */
594  if (size < chunk_size)
595  set_sentinel(AllocChunkGetPointer(chunk), size);
596 #endif
597 #ifdef RANDOMIZE_ALLOCATED_MEMORY
598  /* fill the allocated space with junk */
599  randomize_mem((char *) AllocChunkGetPointer(chunk), size);
600 #endif
601 
602  /*
603  * Stick the new block underneath the active allocation block, if any,
604  * so that we don't lose the use of the space remaining therein.
605  */
606  if (set->blocks != NULL)
607  {
608  block->prev = set->blocks;
609  block->next = set->blocks->next;
610  if (block->next)
611  block->next->prev = block;
612  set->blocks->next = block;
613  }
614  else
615  {
616  block->prev = NULL;
617  block->next = NULL;
618  set->blocks = block;
619  }
620 
621  AllocAllocInfo(set, chunk);
622 
623  /*
624  * Chunk's metadata fields remain DEFINED. The requested allocation
625  * itself can be NOACCESS or UNDEFINED; our caller will soon make it
626  * UNDEFINED. Make extra space at the end of the chunk, if any,
627  * NOACCESS.
628  */
629  VALGRIND_MAKE_MEM_NOACCESS((char *) chunk + ALLOC_CHUNKHDRSZ,
630  chunk_size - ALLOC_CHUNKHDRSZ);
631 
632  return AllocChunkGetPointer(chunk);
633  }
634 
635  /*
636  * Request is small enough to be treated as a chunk. Look in the
637  * corresponding free list to see if there is a free chunk we could reuse.
638  * If one is found, remove it from the free list, make it again a member
639  * of the alloc set and return its data address.
640  */
641  fidx = AllocSetFreeIndex(size);
642  chunk = set->freelist[fidx];
643  if (chunk != NULL)
644  {
645  Assert(chunk->size >= size);
646 
647  set->freelist[fidx] = (AllocChunk) chunk->aset;
648 
649  chunk->aset = (void *) set;
650 
651 #ifdef MEMORY_CONTEXT_CHECKING
652  /* Valgrind: Free list requested_size should be DEFINED. */
653  chunk->requested_size = size;
654  VALGRIND_MAKE_MEM_NOACCESS(&chunk->requested_size,
655  sizeof(chunk->requested_size));
656  /* set mark to catch clobber of "unused" space */
657  if (size < chunk->size)
658  set_sentinel(AllocChunkGetPointer(chunk), size);
659 #endif
660 #ifdef RANDOMIZE_ALLOCATED_MEMORY
661  /* fill the allocated space with junk */
662  randomize_mem((char *) AllocChunkGetPointer(chunk), size);
663 #endif
664 
665  AllocAllocInfo(set, chunk);
666  return AllocChunkGetPointer(chunk);
667  }
668 
669  /*
670  * Choose the actual chunk size to allocate.
671  */
672  chunk_size = (1 << ALLOC_MINBITS) << fidx;
673  Assert(chunk_size >= size);
674 
675  /*
676  * If there is enough room in the active allocation block, we will put the
677  * chunk into that block. Else must start a new one.
678  */
679  if ((block = set->blocks) != NULL)
680  {
681  Size availspace = block->endptr - block->freeptr;
682 
683  if (availspace < (chunk_size + ALLOC_CHUNKHDRSZ))
684  {
685  /*
686  * The existing active (top) block does not have enough room for
687  * the requested allocation, but it might still have a useful
688  * amount of space in it. Once we push it down in the block list,
689  * we'll never try to allocate more space from it. So, before we
690  * do that, carve up its free space into chunks that we can put on
691  * the set's freelists.
692  *
693  * Because we can only get here when there's less than
694  * ALLOC_CHUNK_LIMIT left in the block, this loop cannot iterate
695  * more than ALLOCSET_NUM_FREELISTS-1 times.
696  */
697  while (availspace >= ((1 << ALLOC_MINBITS) + ALLOC_CHUNKHDRSZ))
698  {
699  Size availchunk = availspace - ALLOC_CHUNKHDRSZ;
700  int a_fidx = AllocSetFreeIndex(availchunk);
701 
702  /*
703  * In most cases, we'll get back the index of the next larger
704  * freelist than the one we need to put this chunk on. The
705  * exception is when availchunk is exactly a power of 2.
706  */
707  if (availchunk != ((Size) 1 << (a_fidx + ALLOC_MINBITS)))
708  {
709  a_fidx--;
710  Assert(a_fidx >= 0);
711  availchunk = ((Size) 1 << (a_fidx + ALLOC_MINBITS));
712  }
713 
714  chunk = (AllocChunk) (block->freeptr);
715 
716  /* Prepare to initialize the chunk header. */
717  VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
718 
719  block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
720  availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
721 
722  chunk->size = availchunk;
723 #ifdef MEMORY_CONTEXT_CHECKING
724  chunk->requested_size = 0; /* mark it free */
725 #endif
726  chunk->aset = (void *) set->freelist[a_fidx];
727  set->freelist[a_fidx] = chunk;
728  }
729 
730  /* Mark that we need to create a new block */
731  block = NULL;
732  }
733  }
734 
735  /*
736  * Time to create a new regular (multi-chunk) block?
737  */
738  if (block == NULL)
739  {
740  Size required_size;
741 
742  /*
743  * The first such block has size initBlockSize, and we double the
744  * space in each succeeding block, but not more than maxBlockSize.
745  */
746  blksize = set->nextBlockSize;
747  set->nextBlockSize <<= 1;
748  if (set->nextBlockSize > set->maxBlockSize)
749  set->nextBlockSize = set->maxBlockSize;
750 
751  /*
752  * If initBlockSize is less than ALLOC_CHUNK_LIMIT, we could need more
753  * space... but try to keep it a power of 2.
754  */
755  required_size = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
756  while (blksize < required_size)
757  blksize <<= 1;
758 
759  /* Try to allocate it */
760  block = (AllocBlock) malloc(blksize);
761 
762  /*
763  * We could be asking for pretty big blocks here, so cope if malloc
764  * fails. But give up if there's less than a meg or so available...
765  */
766  while (block == NULL && blksize > 1024 * 1024)
767  {
768  blksize >>= 1;
769  if (blksize < required_size)
770  break;
771  block = (AllocBlock) malloc(blksize);
772  }
773 
774  if (block == NULL)
775  return NULL;
776 
777  block->aset = set;
778  block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
779  block->endptr = ((char *) block) + blksize;
780 
781  /*
782  * If this is the first block of the set, make it the "keeper" block.
783  * Formerly, a keeper block could only be created during context
784  * creation, but allowing it to happen here lets us have fast reset
785  * cycling even for contexts created with minContextSize = 0; that way
786  * we don't have to force space to be allocated in contexts that might
787  * never need any space. Don't mark an oversize block as a keeper,
788  * however.
789  */
790  if (set->keeper == NULL && blksize == set->initBlockSize)
791  set->keeper = block;
792 
793  /* Mark unallocated space NOACCESS. */
795  blksize - ALLOC_BLOCKHDRSZ);
796 
797  block->prev = NULL;
798  block->next = set->blocks;
799  if (block->next)
800  block->next->prev = block;
801  set->blocks = block;
802  }
803 
804  /*
805  * OK, do the allocation
806  */
807  chunk = (AllocChunk) (block->freeptr);
808 
809  /* Prepare to initialize the chunk header. */
810  VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
811 
812  block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
813  Assert(block->freeptr <= block->endptr);
814 
815  chunk->aset = (void *) set;
816  chunk->size = chunk_size;
817 #ifdef MEMORY_CONTEXT_CHECKING
818  chunk->requested_size = size;
819  VALGRIND_MAKE_MEM_NOACCESS(&chunk->requested_size,
820  sizeof(chunk->requested_size));
821  /* set mark to catch clobber of "unused" space */
822  if (size < chunk->size)
823  set_sentinel(AllocChunkGetPointer(chunk), size);
824 #endif
825 #ifdef RANDOMIZE_ALLOCATED_MEMORY
826  /* fill the allocated space with junk */
827  randomize_mem((char *) AllocChunkGetPointer(chunk), size);
828 #endif
829 
830  AllocAllocInfo(set, chunk);
831  return AllocChunkGetPointer(chunk);
832 }
Size initBlockSize
Definition: aset.c:127
AllocBlock blocks
Definition: aset.c:124
#define AllocSetIsValid(set)
Definition: aset.c:191
#define VALGRIND_MAKE_MEM_UNDEFINED(addr, size)
Definition: memdebug.h:28
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition: memdebug.h:27
static int AllocSetFreeIndex(Size size)
Definition: aset.c:271
#define AllocChunkGetPointer(chk)
Definition: aset.c:195
#define ALLOC_BLOCKHDRSZ
Definition: aset.c:99
AllocBlock keeper
Definition: aset.c:131
AllocSet aset
Definition: aset.c:150
char * freeptr
Definition: aset.c:153
#define malloc(a)
Definition: header.h:50
char * endptr
Definition: aset.c:154
#define ALLOC_CHUNKHDRSZ
Definition: aset.c:100
AllocBlock next
Definition: aset.c:152
#define AssertArg(condition)
Definition: c.h:677
struct AllocBlockData * AllocBlock
Definition: aset.c:102
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]
Definition: aset.c:125
Size nextBlockSize
Definition: aset.c:129
AllocBlock prev
Definition: aset.c:151
Size allocChunkLimit
Definition: aset.c:130
struct AllocChunkData * AllocChunk
Definition: aset.c:103
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
size_t Size
Definition: c.h:356
#define MAXALIGN(LEN)
Definition: c.h:588
void * aset
Definition: aset.c:176
AllocSetContext * AllocSet
Definition: aset.c:134
#define ALLOC_MINBITS
Definition: aset.c:81
Size maxBlockSize
Definition: aset.c:128
#define AllocAllocInfo(_cxt, _chunk)
Definition: aset.c:259
Size size
Definition: aset.c:164
MemoryContext AllocSetContextCreate ( MemoryContext  parent,
const char *  name,
Size  minContextSize,
Size  initBlockSize,
Size  maxBlockSize 
)

Definition at line 322 of file aset.c.

References ALLOC_BLOCKHDRSZ, ALLOC_CHUNK_FRACTION, ALLOC_CHUNK_LIMIT, ALLOC_CHUNKHDRSZ, AllocSetContext::allocChunkLimit, AllocHugeSizeIsValid, ALLOCSET_SEPARATE_THRESHOLD, AllocSetMethods, AllocBlockData::aset, AllocSetContext::blocks, elog, AllocBlockData::endptr, ereport, errcode(), errdetail(), errmsg(), ERROR, AllocBlockData::freeptr, AllocSetContext::initBlockSize, AllocSetContext::keeper, malloc, MAXALIGN, AllocSetContext::maxBlockSize, MemoryContextCreate(), MemoryContextStats(), name, AllocBlockData::next, AllocSetContext::nextBlockSize, NULL, offsetof, AllocBlockData::prev, StaticAssertStmt, T_AllocSetContext, TopMemoryContext, and VALGRIND_MAKE_MEM_NOACCESS.

Referenced by _bt_preprocess_array_keys(), _SPI_make_plan_non_temp(), _SPI_save_plan(), afterTriggerAddEvent(), afterTriggerInvokeEvents(), AllocateSnapshotBuilder(), ApplyLauncherMain(), ApplyWorkerMain(), AtStart_Memory(), AtSubStart_Memory(), AutoVacLauncherMain(), BackgroundWriterMain(), begin_heap_rewrite(), BeginCopy(), blbuild(), blinsert(), brin_build_desc(), brin_new_memtuple(), bringetbitmap(), brininsert(), bt_check_every_level(), btvacuumscan(), BuildCachedPlan(), BuildEventTriggerCache(), BuildRelationExtStatistics(), CheckpointerMain(), cluster(), compile_plperl_function(), compile_pltcl_function(), CompleteCachedPlan(), compute_index_stats(), CopyCachedPlan(), CopyTo(), CreateCachedPlan(), CreateCacheMemoryContext(), CreateExecutorState(), CreateExprContext(), CreatePortal(), CreateStandaloneExprContext(), createTempGistContext(), createTrgmNFA(), DiscreteKnapsack(), do_analyze_rel(), do_autovacuum(), do_compile(), do_start_worker(), each_worker(), each_worker_jsonb(), elements_worker(), elements_worker_jsonb(), EnablePortalManager(), EventTriggerBeginCompleteQuery(), EventTriggerInvoke(), exec_parse_message(), exec_replication_command(), ExecHashTableCreate(), ExecInitFunctionScan(), ExecInitRecursiveUnion(), ExecInitSetOp(), ExecInitSubPlan(), ExecInitTableFuncScan(), ExecInitUnique(), ExecInitWindowAgg(), expand_array(), file_acquire_sample_rows(), fill_hba_view(), geqo_eval(), get_stmt_mcontext(), GetLocalBufferStorage(), gin_xlog_startup(), ginbeginscan(), ginbuild(), ginbulkdelete(), gininsert(), ginInsertCleanup(), ginPlaceToPage(), gistrescan(), HandleParallelMessages(), hash_create(), index_register(), init_MultiFuncCall(), init_sql_fcache(), initArrayResult(), initArrayResultArr(), initGISTstate(), initialize_peragg(), InitXLogInsert(), inline_function(), inline_set_returning_function(), libpqrcv_processTuples(), load_domaintype_info(), load_hba(), load_ident(), load_relcache_init_file(), load_tzoffsets(), logicalrep_relmap_init(), LogicalRepApplyLoop(), lookup_ts_dictionary_cache(), materializeQueryResult(), mdinit(), MemoryContextInit(), mXactCachePut(), NIStartBuild(), ParallelWorkerMain(), PerformAuthentication(), pg_decode_startup(), pgoutput_startup(), pgstat_setup_memcxt(), plperl_return_next(), plperl_spi_prepare(), plpgsql_compile_inline(), plpgsql_estate_setup(), plpython_inline_handler(), pltcl_SPI_prepare(), PLy_cursor_plan(), PLy_cursor_query(), PLy_get_scratch_context(), PLy_procedure_create(), PLy_spi_execute_fetch_result(), PLy_spi_prepare(), PLyObject_ToComposite(), PLyString_ToComposite(), PortalCreateHoldStore(), postgresAcquireSampleRowsFunc(), postgresBeginDirectModify(), postgresBeginForeignModify(), postgresBeginForeignScan(), PostgresMain(), PostmasterMain(), printtup_startup(), publicationListToArray(), rebuild_database_list(), ReindexMultipleTables(), RelationBuildPartitionDesc(), RelationBuildPartitionKey(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationInitIndexAccessInfo(), ReorderBufferAllocate(), ResetUnloggedRelations(), RevalidateCachedQuery(), sepgsql_avc_init(), spg_xlog_startup(), spgbeginscan(), spgbuild(), spginsert(), SPI_connect(), spi_dest_startup(), StartupDecodingContext(), strlist_to_textarray(), tokenize_file(), tqueueReceiveSlot(), tuplesort_begin_common(), union_tuples(), vacuum(), WalWriterMain(), and XLOGShmemInit().

327 {
328  AllocSet set;
329 
331  MAXALIGN(sizeof(AllocChunkData)),
332  "padding calculation in AllocChunkData is wrong");
333 
334  /*
335  * First, validate allocation parameters. (If we're going to throw an
336  * error, we should do so before the context is created, not after.) We
337  * somewhat arbitrarily enforce a minimum 1K block size.
338  */
339  if (initBlockSize != MAXALIGN(initBlockSize) ||
340  initBlockSize < 1024)
341  elog(ERROR, "invalid initBlockSize for memory context: %zu",
342  initBlockSize);
343  if (maxBlockSize != MAXALIGN(maxBlockSize) ||
344  maxBlockSize < initBlockSize ||
345  !AllocHugeSizeIsValid(maxBlockSize)) /* must be safe to double */
346  elog(ERROR, "invalid maxBlockSize for memory context: %zu",
347  maxBlockSize);
348  if (minContextSize != 0 &&
349  (minContextSize != MAXALIGN(minContextSize) ||
350  minContextSize <= ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
351  elog(ERROR, "invalid minContextSize for memory context: %zu",
352  minContextSize);
353 
354  /* Do the type-independent part of context creation */
356  sizeof(AllocSetContext),
358  parent,
359  name);
360 
361  /* Save allocation parameters */
362  set->initBlockSize = initBlockSize;
363  set->maxBlockSize = maxBlockSize;
364  set->nextBlockSize = initBlockSize;
365 
366  /*
367  * Compute the allocation chunk size limit for this context. It can't be
368  * more than ALLOC_CHUNK_LIMIT because of the fixed number of freelists.
369  * If maxBlockSize is small then requests exceeding the maxBlockSize, or
370  * even a significant fraction of it, should be treated as large chunks
371  * too. For the typical case of maxBlockSize a power of 2, the chunk size
372  * limit will be at most 1/8th maxBlockSize, so that given a stream of
373  * requests that are all the maximum chunk size we will waste at most
374  * 1/8th of the allocated space.
375  *
376  * We have to have allocChunkLimit a power of two, because the requested
377  * and actually-allocated sizes of any chunk must be on the same side of
378  * the limit, else we get confused about whether the chunk is "big".
379  *
380  * Also, allocChunkLimit must not exceed ALLOCSET_SEPARATE_THRESHOLD.
381  */
383  "ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
384 
386  while ((Size) (set->allocChunkLimit + ALLOC_CHUNKHDRSZ) >
387  (Size) ((maxBlockSize - ALLOC_BLOCKHDRSZ) / ALLOC_CHUNK_FRACTION))
388  set->allocChunkLimit >>= 1;
389 
390  /*
391  * Grab always-allocated space, if requested
392  */
393  if (minContextSize > 0)
394  {
395  Size blksize = minContextSize;
396  AllocBlock block;
397 
398  block = (AllocBlock) malloc(blksize);
399  if (block == NULL)
400  {
402  ereport(ERROR,
403  (errcode(ERRCODE_OUT_OF_MEMORY),
404  errmsg("out of memory"),
405  errdetail("Failed while creating memory context \"%s\".",
406  name)));
407  }
408  block->aset = set;
409  block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
410  block->endptr = ((char *) block) + blksize;
411  block->prev = NULL;
412  block->next = set->blocks;
413  if (block->next)
414  block->next->prev = block;
415  set->blocks = block;
416  /* Mark block as not to be released at reset time */
417  set->keeper = block;
418 
419  /* Mark unallocated space NOACCESS; leave the block header alone. */
421  blksize - ALLOC_BLOCKHDRSZ);
422  }
423 
424  return (MemoryContext) set;
425 }
Size initBlockSize
Definition: aset.c:127
AllocBlock blocks
Definition: aset.c:124
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition: memdebug.h:27
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ALLOC_BLOCKHDRSZ
Definition: aset.c:99
AllocBlock keeper
Definition: aset.c:131
AllocSet aset
Definition: aset.c:150
char * freeptr
Definition: aset.c:153
#define malloc(a)
Definition: header.h:50
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:757
#define ERROR
Definition: elog.h:43
#define ALLOC_CHUNK_LIMIT
Definition: aset.c:83
void MemoryContextStats(MemoryContext context)
Definition: mcxt.c:438
char * endptr
Definition: aset.c:154
#define ALLOCSET_SEPARATE_THRESHOLD
Definition: memutils.h:192
int errdetail(const char *fmt,...)
Definition: elog.c:873
MemoryContext MemoryContextCreate(NodeTag tag, Size size, MemoryContextMethods *methods, MemoryContext parent, const char *name)
Definition: mcxt.c:640
#define ALLOC_CHUNKHDRSZ
Definition: aset.c:100
static MemoryContextMethods AllocSetMethods
Definition: aset.c:219
AllocBlock next
Definition: aset.c:152
#define ereport(elevel, rest)
Definition: elog.h:122
MemoryContext TopMemoryContext
Definition: mcxt.c:43
#define ALLOC_CHUNK_FRACTION
Definition: aset.c:85
struct AllocBlockData * AllocBlock
Definition: aset.c:102
Size nextBlockSize
Definition: aset.c:129
AllocBlock prev
Definition: aset.c:151
Size allocChunkLimit
Definition: aset.c:130
#define NULL
Definition: c.h:229
size_t Size
Definition: c.h:356
#define MAXALIGN(LEN)
Definition: c.h:588
const char * name
Definition: encode.c:521
#define AllocHugeSizeIsValid(size)
Definition: memutils.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
AllocSetContext * AllocSet
Definition: aset.c:134
#define elog
Definition: elog.h:219
Size maxBlockSize
Definition: aset.c:128
#define offsetof(type, field)
Definition: c.h:555
static void AllocSetDelete ( MemoryContext  context)
static

Definition at line 523 of file aset.c.

References AllocSetIsValid, AssertArg, AllocSetContext::blocks, free, AllocSetContext::freelist, AllocBlockData::freeptr, AllocSetContext::keeper, MemSetAligned, AllocBlockData::next, next, and NULL.

524 {
525  AllocSet set = (AllocSet) context;
526  AllocBlock block = set->blocks;
527 
529 
530 #ifdef MEMORY_CONTEXT_CHECKING
531  /* Check for corruption and leaks before freeing */
532  AllocSetCheck(context);
533 #endif
534 
535  /* Make it look empty, just in case... */
536  MemSetAligned(set->freelist, 0, sizeof(set->freelist));
537  set->blocks = NULL;
538  set->keeper = NULL;
539 
540  while (block != NULL)
541  {
542  AllocBlock next = block->next;
543 
544 #ifdef CLOBBER_FREED_MEMORY
545  wipe_mem(block, block->freeptr - ((char *) block));
546 #endif
547  free(block);
548  block = next;
549  }
550 }
#define MemSetAligned(start, val, len)
Definition: c.h:890
AllocBlock blocks
Definition: aset.c:124
static int32 next
Definition: blutils.c:210
#define AllocSetIsValid(set)
Definition: aset.c:191
AllocBlock keeper
Definition: aset.c:131
char * freeptr
Definition: aset.c:153
AllocBlock next
Definition: aset.c:152
#define AssertArg(condition)
Definition: c.h:677
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]
Definition: aset.c:125
#define free(a)
Definition: header.h:65
#define NULL
Definition: c.h:229
AllocSetContext * AllocSet
Definition: aset.c:134
static void AllocSetFree ( MemoryContext  context,
void *  pointer 
)
static

Definition at line 839 of file aset.c.

References ALLOC_BLOCKHDRSZ, ALLOC_CHUNKHDRSZ, AllocSetContext::allocChunkLimit, AllocFreeInfo, AllocPointerGetChunk, AllocSetFreeIndex(), AllocBlockData::aset, AllocChunkData::aset, AllocSetContext::blocks, elog, AllocBlockData::endptr, ERROR, free, AllocSetContext::freelist, AllocBlockData::freeptr, AllocSetContext::header, MemoryContextData::name, AllocBlockData::next, AllocBlockData::prev, AllocChunkData::size, VALGRIND_MAKE_MEM_DEFINED, and WARNING.

Referenced by AllocSetRealloc().

840 {
841  AllocSet set = (AllocSet) context;
842  AllocChunk chunk = AllocPointerGetChunk(pointer);
843 
844  AllocFreeInfo(set, chunk);
845 
846 #ifdef MEMORY_CONTEXT_CHECKING
847  VALGRIND_MAKE_MEM_DEFINED(&chunk->requested_size,
848  sizeof(chunk->requested_size));
849  /* Test for someone scribbling on unused space in chunk */
850  if (chunk->requested_size < chunk->size)
851  if (!sentinel_ok(pointer, chunk->requested_size))
852  elog(WARNING, "detected write past chunk end in %s %p",
853  set->header.name, chunk);
854 #endif
855 
856  if (chunk->size > set->allocChunkLimit)
857  {
858  /*
859  * Big chunks are certain to have been allocated as single-chunk
860  * blocks. Just unlink that block and return it to malloc().
861  */
862  AllocBlock block = (AllocBlock) (((char *) chunk) - ALLOC_BLOCKHDRSZ);
863 
864  /*
865  * Try to verify that we have a sane block pointer: it should
866  * reference the correct aset, and freeptr and endptr should point
867  * just past the chunk.
868  */
869  if (block->aset != set ||
870  block->freeptr != block->endptr ||
871  block->freeptr != ((char *) block) +
873  elog(ERROR, "could not find block containing chunk %p", chunk);
874 
875  /* OK, remove block from aset's list and free it */
876  if (block->prev)
877  block->prev->next = block->next;
878  else
879  set->blocks = block->next;
880  if (block->next)
881  block->next->prev = block->prev;
882 #ifdef CLOBBER_FREED_MEMORY
883  wipe_mem(block, block->freeptr - ((char *) block));
884 #endif
885  free(block);
886  }
887  else
888  {
889  /* Normal case, put the chunk into appropriate freelist */
890  int fidx = AllocSetFreeIndex(chunk->size);
891 
892  chunk->aset = (void *) set->freelist[fidx];
893 
894 #ifdef CLOBBER_FREED_MEMORY
895  wipe_mem(pointer, chunk->size);
896 #endif
897 
898 #ifdef MEMORY_CONTEXT_CHECKING
899  /* Reset requested_size to 0 in chunks that are on freelist */
900  chunk->requested_size = 0;
901 #endif
902  set->freelist[fidx] = chunk;
903  }
904 }
#define AllocFreeInfo(_cxt, _chunk)
Definition: aset.c:258
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
AllocBlock blocks
Definition: aset.c:124
MemoryContextData header
Definition: aset.c:122
static int AllocSetFreeIndex(Size size)
Definition: aset.c:271
#define ALLOC_BLOCKHDRSZ
Definition: aset.c:99
AllocSet aset
Definition: aset.c:150
char * freeptr
Definition: aset.c:153
#define ERROR
Definition: elog.h:43
char * endptr
Definition: aset.c:154
#define ALLOC_CHUNKHDRSZ
Definition: aset.c:100
AllocBlock next
Definition: aset.c:152
#define WARNING
Definition: elog.h:40
struct AllocBlockData * AllocBlock
Definition: aset.c:102
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]
Definition: aset.c:125
AllocBlock prev
Definition: aset.c:151
#define free(a)
Definition: header.h:65
Size allocChunkLimit
Definition: aset.c:130
void * aset
Definition: aset.c:176
AllocSetContext * AllocSet
Definition: aset.c:134
#define elog
Definition: elog.h:219
Size size
Definition: aset.c:164
#define AllocPointerGetChunk(ptr)
Definition: aset.c:193
static int AllocSetFreeIndex ( Size  size)
inlinestatic

Definition at line 271 of file aset.c.

References ALLOC_MINBITS, ALLOCSET_NUM_FREELISTS, Assert, idx(), and LogTable256.

Referenced by AllocSetAlloc(), and AllocSetFree().

272 {
273  int idx;
274  unsigned int t,
275  tsize;
276 
277  if (size > (1 << ALLOC_MINBITS))
278  {
279  tsize = (size - 1) >> ALLOC_MINBITS;
280 
281  /*
282  * At this point we need to obtain log2(tsize)+1, ie, the number of
283  * not-all-zero bits at the right. We used to do this with a
284  * shift-and-count loop, but this function is enough of a hotspot to
285  * justify micro-optimization effort. The best approach seems to be
286  * to use a lookup table. Note that this code assumes that
287  * ALLOCSET_NUM_FREELISTS <= 17, since we only cope with two bytes of
288  * the tsize value.
289  */
290  t = tsize >> 8;
291  idx = t ? LogTable256[t] + 8 : LogTable256[tsize];
292 
294  }
295  else
296  idx = 0;
297 
298  return idx;
299 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define ALLOCSET_NUM_FREELISTS
Definition: aset.c:82
static const unsigned char LogTable256[256]
Definition: aset.c:239
#define Assert(condition)
Definition: c.h:675
#define ALLOC_MINBITS
Definition: aset.c:81
static Size AllocSetGetChunkSpace ( MemoryContext  context,
void *  pointer 
)
static

Definition at line 1114 of file aset.c.

References ALLOC_CHUNKHDRSZ, AllocPointerGetChunk, and AllocChunkData::size.

1115 {
1116  AllocChunk chunk = AllocPointerGetChunk(pointer);
1117 
1118  return chunk->size + ALLOC_CHUNKHDRSZ;
1119 }
#define ALLOC_CHUNKHDRSZ
Definition: aset.c:100
Size size
Definition: aset.c:164
#define AllocPointerGetChunk(ptr)
Definition: aset.c:193
static void AllocSetInit ( MemoryContext  context)
static

Definition at line 440 of file aset.c.

441 {
442  /*
443  * Since MemoryContextCreate already zeroed the context node, we don't
444  * have to do anything here: it's already OK.
445  */
446 }
static bool AllocSetIsEmpty ( MemoryContext  context)
static

Definition at line 1126 of file aset.c.

References MemoryContextData::isReset.

1127 {
1128  /*
1129  * For now, we say "empty" only if the context is new or just reset. We
1130  * could examine the freelists to determine if all space has been freed,
1131  * but it's not really worth the trouble for present uses of this
1132  * functionality.
1133  */
1134  if (context->isReset)
1135  return true;
1136  return false;
1137 }
static void * AllocSetRealloc ( MemoryContext  context,
void *  pointer,
Size  size 
)
static

Definition at line 919 of file aset.c.

References ALLOC_BLOCKHDRSZ, ALLOC_CHUNKHDRSZ, AllocChunkGetPointer, AllocSetContext::allocChunkLimit, AllocPointerGetChunk, AllocSetAlloc(), AllocSetFree(), AllocBlockData::aset, AllocSetContext::blocks, elog, AllocBlockData::endptr, ERROR, AllocBlockData::freeptr, AllocSetContext::header, MAXALIGN, MemoryContextData::name, AllocBlockData::next, NULL, AllocBlockData::prev, realloc, AllocChunkData::size, VALGRIND_MAKE_MEM_DEFINED, VALGRIND_MAKE_MEM_NOACCESS, VALGRIND_MAKE_MEM_UNDEFINED, and WARNING.

920 {
921  AllocSet set = (AllocSet) context;
922  AllocChunk chunk = AllocPointerGetChunk(pointer);
923  Size oldsize = chunk->size;
924 
925 #ifdef MEMORY_CONTEXT_CHECKING
926  VALGRIND_MAKE_MEM_DEFINED(&chunk->requested_size,
927  sizeof(chunk->requested_size));
928  /* Test for someone scribbling on unused space in chunk */
929  if (chunk->requested_size < oldsize)
930  if (!sentinel_ok(pointer, chunk->requested_size))
931  elog(WARNING, "detected write past chunk end in %s %p",
932  set->header.name, chunk);
933 #endif
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  if (oldsize > set->allocChunkLimit)
985  {
986  /*
987  * 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.
990  */
991  AllocBlock block = (AllocBlock) (((char *) chunk) - ALLOC_BLOCKHDRSZ);
992  Size chksize;
993  Size blksize;
994 
995  /*
996  * Try to verify that we have a sane block pointer: it should
997  * reference the correct aset, and freeptr and endptr should point
998  * just past the chunk.
999  */
1000  if (block->aset != set ||
1001  block->freeptr != block->endptr ||
1002  block->freeptr != ((char *) block) +
1003  (chunk->size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
1004  elog(ERROR, "could not find block containing chunk %p", chunk);
1005 
1006  /* Do the realloc */
1007  chksize = MAXALIGN(size);
1008  blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
1009  block = (AllocBlock) realloc(block, blksize);
1010  if (block == NULL)
1011  return NULL;
1012  block->freeptr = block->endptr = ((char *) block) + blksize;
1013 
1014  /* Update pointers since block has likely been moved */
1015  chunk = (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ);
1016  pointer = AllocChunkGetPointer(chunk);
1017  if (block->prev)
1018  block->prev->next = block;
1019  else
1020  set->blocks = block;
1021  if (block->next)
1022  block->next->prev = block;
1023  chunk->size = chksize;
1024 
1025 #ifdef MEMORY_CONTEXT_CHECKING
1026 #ifdef RANDOMIZE_ALLOCATED_MEMORY
1027  /* 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);
1030 #endif
1031 
1032  /*
1033  * realloc() (or randomize_mem()) will have left the newly-allocated
1034  * part UNDEFINED, but we may need to adjust trailing bytes from the
1035  * old allocation.
1036  */
1037  VALGRIND_MAKE_MEM_UNDEFINED((char *) pointer + chunk->requested_size,
1038  oldsize - chunk->requested_size);
1039 
1040  chunk->requested_size = size;
1041  VALGRIND_MAKE_MEM_NOACCESS(&chunk->requested_size,
1042  sizeof(chunk->requested_size));
1043 
1044  /* set mark to catch clobber of "unused" space */
1045  if (size < chunk->size)
1046  set_sentinel(pointer, size);
1047 #else /* !MEMORY_CONTEXT_CHECKING */
1048 
1049  /*
1050  * We don't know how much of the old chunk size was the actual
1051  * allocation; it could have been as small as one byte. We have to be
1052  * conservative and just mark the entire old portion DEFINED.
1053  */
1054  VALGRIND_MAKE_MEM_DEFINED(pointer, oldsize);
1055 #endif
1056 
1057  /* Make any trailing alignment padding NOACCESS. */
1058  VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size, chksize - size);
1059 
1060  return pointer;
1061  }
1062  else
1063  {
1064  /*
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
1071  * palloc/repalloc/pfree: the eventually freed chunks go into the
1072  * wrong freelist for the next initial palloc request, and so we leak
1073  * memory indefinitely. See pgsql-hackers archives for 2007-08-11.)
1074  */
1075  AllocPointer newPointer;
1076 
1077  /* allocate new chunk */
1078  newPointer = AllocSetAlloc((MemoryContext) set, size);
1079 
1080  /* leave immediately if request was not completed */
1081  if (newPointer == NULL)
1082  return NULL;
1083 
1084  /*
1085  * AllocSetAlloc() just made the region NOACCESS. Change it to
1086  * UNDEFINED for the moment; memcpy() will then transfer definedness
1087  * from the old allocation to the new. If we know the old allocation,
1088  * copy just that much. Otherwise, make the entire old chunk defined
1089  * to avoid errors as we copy the currently-NOACCESS trailing bytes.
1090  */
1091  VALGRIND_MAKE_MEM_UNDEFINED(newPointer, size);
1092 #ifdef MEMORY_CONTEXT_CHECKING
1093  oldsize = chunk->requested_size;
1094 #else
1095  VALGRIND_MAKE_MEM_DEFINED(pointer, oldsize);
1096 #endif
1097 
1098  /* transfer existing data (certain to fit) */
1099  memcpy(newPointer, pointer, oldsize);
1100 
1101  /* free old chunk */
1102  AllocSetFree((MemoryContext) set, pointer);
1103 
1104  return newPointer;
1105  }
1106 }
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
Definition: memdebug.h:26
AllocBlock blocks
Definition: aset.c:124
MemoryContextData header
Definition: aset.c:122
void * AllocPointer
Definition: aset.c:109
#define VALGRIND_MAKE_MEM_UNDEFINED(addr, size)
Definition: memdebug.h:28
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition: memdebug.h:27
#define AllocChunkGetPointer(chk)
Definition: aset.c:195
#define ALLOC_BLOCKHDRSZ
Definition: aset.c:99
AllocSet aset
Definition: aset.c:150
char * freeptr
Definition: aset.c:153
#define ERROR
Definition: elog.h:43
char * endptr
Definition: aset.c:154
#define ALLOC_CHUNKHDRSZ
Definition: aset.c:100
AllocBlock next
Definition: aset.c:152
#define WARNING
Definition: elog.h:40
struct AllocBlockData * AllocBlock
Definition: aset.c:102
AllocBlock prev
Definition: aset.c:151
Size allocChunkLimit
Definition: aset.c:130
struct AllocChunkData * AllocChunk
Definition: aset.c:103
#define NULL
Definition: c.h:229
static void AllocSetFree(MemoryContext context, void *pointer)
Definition: aset.c:839
size_t Size
Definition: c.h:356
#define MAXALIGN(LEN)
Definition: c.h:588
#define realloc(a, b)
Definition: header.h:60
static void * AllocSetAlloc(MemoryContext context, Size size)
Definition: aset.c:562
AllocSetContext * AllocSet
Definition: aset.c:134
#define elog
Definition: elog.h:219
Size size
Definition: aset.c:164
#define AllocPointerGetChunk(ptr)
Definition: aset.c:193
static void AllocSetReset ( MemoryContext  context)
static

Definition at line 460 of file aset.c.

References ALLOC_BLOCKHDRSZ, AllocSetIsValid, AssertArg, AllocSetContext::blocks, free, AllocSetContext::freelist, AllocBlockData::freeptr, AllocSetContext::initBlockSize, AllocSetContext::keeper, MemSetAligned, AllocBlockData::next, next, AllocSetContext::nextBlockSize, NULL, AllocBlockData::prev, and VALGRIND_MAKE_MEM_NOACCESS.

461 {
462  AllocSet set = (AllocSet) context;
463  AllocBlock block;
464 
466 
467 #ifdef MEMORY_CONTEXT_CHECKING
468  /* Check for corruption and leaks before freeing */
469  AllocSetCheck(context);
470 #endif
471 
472  /* Clear chunk freelists */
473  MemSetAligned(set->freelist, 0, sizeof(set->freelist));
474 
475  block = set->blocks;
476 
477  /* New blocks list is either empty or just the keeper block */
478  set->blocks = set->keeper;
479 
480  while (block != NULL)
481  {
482  AllocBlock next = block->next;
483 
484  if (block == set->keeper)
485  {
486  /* Reset the block, but don't return it to malloc */
487  char *datastart = ((char *) block) + ALLOC_BLOCKHDRSZ;
488 
489 #ifdef CLOBBER_FREED_MEMORY
490  wipe_mem(datastart, block->freeptr - datastart);
491 #else
492  /* wipe_mem() would have done this */
493  VALGRIND_MAKE_MEM_NOACCESS(datastart, block->freeptr - datastart);
494 #endif
495  block->freeptr = datastart;
496  block->prev = NULL;
497  block->next = NULL;
498  }
499  else
500  {
501  /* Normal case, release the block */
502 #ifdef CLOBBER_FREED_MEMORY
503  wipe_mem(block, block->freeptr - ((char *) block));
504 #endif
505  free(block);
506  }
507  block = next;
508  }
509 
510  /* Reset block size allocation sequence, too */
511  set->nextBlockSize = set->initBlockSize;
512 }
#define MemSetAligned(start, val, len)
Definition: c.h:890
Size initBlockSize
Definition: aset.c:127
AllocBlock blocks
Definition: aset.c:124
static int32 next
Definition: blutils.c:210
#define AllocSetIsValid(set)
Definition: aset.c:191
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
Definition: memdebug.h:27
#define ALLOC_BLOCKHDRSZ
Definition: aset.c:99
AllocBlock keeper
Definition: aset.c:131
char * freeptr
Definition: aset.c:153
AllocBlock next
Definition: aset.c:152
#define AssertArg(condition)
Definition: c.h:677
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]
Definition: aset.c:125
Size nextBlockSize
Definition: aset.c:129
AllocBlock prev
Definition: aset.c:151
#define free(a)
Definition: header.h:65
#define NULL
Definition: c.h:229
AllocSetContext * AllocSet
Definition: aset.c:134
static void AllocSetStats ( MemoryContext  context,
int  level,
bool  print,
MemoryContextCounters totals 
)
static

Definition at line 1148 of file aset.c.

References ALLOC_CHUNKHDRSZ, ALLOCSET_NUM_FREELISTS, AllocChunkData::aset, AllocSetContext::blocks, AllocBlockData::endptr, MemoryContextCounters::freechunks, AllocSetContext::freelist, AllocBlockData::freeptr, MemoryContextCounters::freespace, AllocSetContext::header, i, MemoryContextData::name, MemoryContextCounters::nblocks, AllocBlockData::next, NULL, AllocChunkData::size, and MemoryContextCounters::totalspace.

1150 {
1151  AllocSet set = (AllocSet) context;
1152  Size nblocks = 0;
1153  Size freechunks = 0;
1154  Size totalspace = 0;
1155  Size freespace = 0;
1156  AllocBlock block;
1157  int fidx;
1158 
1159  for (block = set->blocks; block != NULL; block = block->next)
1160  {
1161  nblocks++;
1162  totalspace += block->endptr - ((char *) block);
1163  freespace += block->endptr - block->freeptr;
1164  }
1165  for (fidx = 0; fidx < ALLOCSET_NUM_FREELISTS; fidx++)
1166  {
1167  AllocChunk chunk;
1168 
1169  for (chunk = set->freelist[fidx]; chunk != NULL;
1170  chunk = (AllocChunk) chunk->aset)
1171  {
1172  freechunks++;
1173  freespace += chunk->size + ALLOC_CHUNKHDRSZ;
1174  }
1175  }
1176 
1177  if (print)
1178  {
1179  int i;
1180 
1181  for (i = 0; i < level; i++)
1182  fprintf(stderr, " ");
1183  fprintf(stderr,
1184  "%s: %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n",
1185  set->header.name, totalspace, nblocks, freespace, freechunks,
1186  totalspace - freespace);
1187  }
1188 
1189  if (totals)
1190  {
1191  totals->nblocks += nblocks;
1192  totals->freechunks += freechunks;
1193  totals->totalspace += totalspace;
1194  totals->freespace += freespace;
1195  }
1196 }
AllocBlock blocks
Definition: aset.c:124
void print(const void *obj)
Definition: print.c:35
MemoryContextData header
Definition: aset.c:122
char * freeptr
Definition: aset.c:153
char * endptr
Definition: aset.c:154
#define ALLOCSET_NUM_FREELISTS
Definition: aset.c:82
#define ALLOC_CHUNKHDRSZ
Definition: aset.c:100
AllocBlock next
Definition: aset.c:152
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]
Definition: aset.c:125
#define NULL
Definition: c.h:229
size_t Size
Definition: c.h:356
void * aset
Definition: aset.c:176
int i
AllocSetContext * AllocSet
Definition: aset.c:134
Size size
Definition: aset.c:164

Variable Documentation

MemoryContextMethods AllocSetMethods
static
Initial value:
= {
}
static void AllocSetInit(MemoryContext context)
Definition: aset.c:440
static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer)
Definition: aset.c:1114
static void AllocSetReset(MemoryContext context)
Definition: aset.c:460
static void * AllocSetRealloc(MemoryContext context, void *pointer, Size size)
Definition: aset.c:919
static bool AllocSetIsEmpty(MemoryContext context)
Definition: aset.c:1126
static void AllocSetFree(MemoryContext context, void *pointer)
Definition: aset.c:839
static void AllocSetStats(MemoryContext context, int level, bool print, MemoryContextCounters *totals)
Definition: aset.c:1148
static void AllocSetDelete(MemoryContext context)
Definition: aset.c:523
static void * AllocSetAlloc(MemoryContext context, Size size)
Definition: aset.c:562

Definition at line 219 of file aset.c.

Referenced by AllocSetContextCreate().

const unsigned char LogTable256[256]
static
Initial value:
=
{
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
LT16(5), LT16(6), LT16(6), LT16(7), LT16(7), LT16(7), LT16(7),
LT16(8), LT16(8), LT16(8), LT16(8), LT16(8), LT16(8), LT16(8), LT16(8)
}
#define LT16(n)
Definition: aset.c:237

Definition at line 239 of file aset.c.

Referenced by AllocSetFreeIndex().