/*------------------------------------------------------------------------- * * mspan.h * Memory span management. * * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/utils/mspan.h * *------------------------------------------------------------------------- */ #ifndef MSPAN_H #define MSPAN_H #include "utils/aspace_map.h" /* * Relative pointers. * * These are intended to be used when storing an address that may be * relative either to the base of the processes address space or some * dynamic shared memory segment mapped therein. * * The idea here is that you declare a relative pointer as relptr(type) * and then use relptr_access to dereference it and relptr_store to change * it. The use of a union here is a hack, because what's stored in the * relptr is always a Size, never an actual pointer. But including a pointer * in the union allows us to use stupid macro tricks to provide some measure * of type-safety. */ #define relptr(type) union { type *relptr_type; Size relptr_off; } #define relptr_access(base, rp) \ (AssertVariableIsOfTypeMacro(base, char *), \ (__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \ (base + (rp).relptr_off))) #define relptr_is_null(rp) \ ((rp).relptr_off == 0) #define relptr_store(base, rp, val) \ (AssertVariableIsOfTypeMacro(base, char *), \ AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \ (rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base))) /* * Flags that can be associated with memory allocations. */ #define MSPAN_ALLOW_HUGE 0x0001 /* allow allocations > 1 GB */ #define MSPAN_SOFT_FAIL 0x0002 /* return NULL on failure */ /* * Large objects - and the superblocks used to satisfy smaller allocations - * are allocated from free lists. Each free list except the last holds * available spans of one particular size; the final free list holds all * the remaining ones. */ #define MSPAN_NUM_FREE_LISTS 256 /* Forward declarations. */ struct mspan; struct mspan_context; struct mspan_manager; typedef struct mspan mspan; typedef struct mspan_context mspan_context; typedef struct mspan_manager mspan_manager; /* * One mspan_manager is needed for each allocation space. This means that * we have one for our own address space, which is stored in a static variable; * and one for each dynamic shared memory segment in which we want to use * this facility, which should be stored within that segment. */ struct mspan_manager { Size npages; /* # of managed pages in dsm; 0 for private */ Size base; /* offset of page 0 within dsm; 0 for private */ Size boundary; /* first unallocated page in dsm; 0 for private */ Size ncontexts; /* # of outstanding contexts */ Size nsyschunks; /* # of chunks allocated from OS */ relptr(mspan) span_of_spans; /* superblock for span descriptors */ relptr(mspan_context) freecontext; /* allocatable context object */ aspace_map page_map; /* map pages to mspans */ relptr(mspan) freelist[MSPAN_NUM_FREE_LISTS]; /* spans for freespace */ }; /* Manager for backend-private address space. */ extern mspan_manager private_mspan_manager; /* Initialization a manager in private or dynamic shared memory. */ extern void mspan_initialize_private_manager(mspan_manager *); extern mspan_manager *mspan_initialize_dsm_manager(dsm_segment *, void *, Size nbytes); /* Create or destroy a memory context. */ extern mspan_context *mspan_context_create(dsm_segment *, mspan_manager *); extern void mspan_context_destroy(dsm_segment *, mspan_context *); /* Allocate or free memory. */ extern void *mspan_alloc(dsm_segment *, mspan_context *, Size size, int flags); extern void *mspan_free(dsm_segment *, void *); #endif