1 /*------------------------------------------------------------------------- 2 * 3 * dsa.h 4 * Dynamic shared memory areas. 5 * 6 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group 7 * Portions Copyright (c) 1994, Regents of the University of California 8 * 9 * IDENTIFICATION 10 * src/include/utils/dsa.h 11 * 12 *------------------------------------------------------------------------- 13 */ 14 #ifndef DSA_H 15 #define DSA_H 16 17 #include "port/atomics.h" 18 #include "storage/dsm.h" 19 20 /* The opaque type used for an area. */ 21 struct dsa_area; 22 typedef struct dsa_area dsa_area; 23 24 /* 25 * If this system only uses a 32-bit value for size_t, then use the 32-bit 26 * implementation of DSA. This limits the amount of DSA that can be created 27 * to something significantly less than the entire 4GB address space because 28 * the DSA pointer must encode both a segment identifier and an offset, but 29 * that shouldn't be a significant limitation in practice. 30 * 31 * If this system doesn't support atomic operations on 64-bit values, then 32 * we fall back to 32-bit dsa_pointer for lack of other options. 33 * 34 * For testing purposes, USE_SMALL_DSA_POINTER can be defined to force the use 35 * of 32-bit dsa_pointer even on systems capable of supporting a 64-bit 36 * dsa_pointer. 37 */ 38 #if SIZEOF_SIZE_T == 4 || !defined(PG_HAVE_ATOMIC_U64_SUPPORT) || \ 39 defined(USE_SMALL_DSA_POINTER) 40 #define SIZEOF_DSA_POINTER 4 41 #else 42 #define SIZEOF_DSA_POINTER 8 43 #endif 44 45 /* 46 * The type of 'relative pointers' to memory allocated by a dynamic shared 47 * area. dsa_pointer values can be shared with other processes, but must be 48 * converted to backend-local pointers before they can be dereferenced. See 49 * dsa_get_address. Also, an atomic version and appropriately sized atomic 50 * operations. 51 */ 52 #if SIZEOF_DSA_POINTER == 4 53 typedef uint32 dsa_pointer; 54 typedef pg_atomic_uint32 dsa_pointer_atomic; 55 #define dsa_pointer_atomic_init pg_atomic_init_u32 56 #define dsa_pointer_atomic_read pg_atomic_read_u32 57 #define dsa_pointer_atomic_write pg_atomic_write_u32 58 #define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u32 59 #define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u32 60 #define DSA_POINTER_FORMAT "%08x" 61 #else 62 typedef uint64 dsa_pointer; 63 typedef pg_atomic_uint64 dsa_pointer_atomic; 64 #define dsa_pointer_atomic_init pg_atomic_init_u64 65 #define dsa_pointer_atomic_read pg_atomic_read_u64 66 #define dsa_pointer_atomic_write pg_atomic_write_u64 67 #define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u64 68 #define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u64 69 #define DSA_POINTER_FORMAT "%016" INT64_MODIFIER "x" 70 #endif 71 72 /* Flags for dsa_allocate_extended. */ 73 #define DSA_ALLOC_HUGE 0x01 /* allow huge allocation (> 1 GB) */ 74 #define DSA_ALLOC_NO_OOM 0x02 /* no failure if out-of-memory */ 75 #define DSA_ALLOC_ZERO 0x04 /* zero allocated memory */ 76 77 /* A sentinel value for dsa_pointer used to indicate failure to allocate. */ 78 #define InvalidDsaPointer ((dsa_pointer) 0) 79 80 /* Check if a dsa_pointer value is valid. */ 81 #define DsaPointerIsValid(x) ((x) != InvalidDsaPointer) 82 83 /* Allocate uninitialized memory with error on out-of-memory. */ 84 #define dsa_allocate(area, size) \ 85 dsa_allocate_extended(area, size, 0) 86 87 /* Allocate zero-initialized memory with error on out-of-memory. */ 88 #define dsa_allocate0(area, size) \ 89 dsa_allocate_extended(area, size, DSA_ALLOC_ZERO) 90 91 /* 92 * The type used for dsa_area handles. dsa_handle values can be shared with 93 * other processes, so that they can attach to them. This provides a way to 94 * share allocated storage with other processes. 95 * 96 * The handle for a dsa_area is currently implemented as the dsm_handle 97 * for the first DSM segment backing this dynamic storage area, but client 98 * code shouldn't assume that is true. 99 */ 100 typedef dsm_handle dsa_handle; 101 102 extern dsa_area *dsa_create(int tranche_id); 103 extern dsa_area *dsa_create_in_place(void *place, size_t size, 104 int tranche_id, dsm_segment *segment); 105 extern dsa_area *dsa_attach(dsa_handle handle); 106 extern dsa_area *dsa_attach_in_place(void *place, dsm_segment *segment); 107 extern void dsa_release_in_place(void *place); 108 extern void dsa_on_dsm_detach_release_in_place(dsm_segment *, Datum); 109 extern void dsa_on_shmem_exit_release_in_place(int, Datum); 110 extern void dsa_pin_mapping(dsa_area *area); 111 extern void dsa_detach(dsa_area *area); 112 extern void dsa_pin(dsa_area *area); 113 extern void dsa_unpin(dsa_area *area); 114 extern void dsa_set_size_limit(dsa_area *area, size_t limit); 115 extern size_t dsa_minimum_size(void); 116 extern dsa_handle dsa_get_handle(dsa_area *area); 117 extern dsa_pointer dsa_allocate_extended(dsa_area *area, size_t size, int flags); 118 extern void dsa_free(dsa_area *area, dsa_pointer dp); 119 extern void *dsa_get_address(dsa_area *area, dsa_pointer dp); 120 extern void dsa_trim(dsa_area *area); 121 extern void dsa_dump(dsa_area *area); 122 123 #endif /* DSA_H */ 124