PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
shm_toc.c File Reference
#include "postgres.h"
#include "port/atomics.h"
#include "storage/shm_toc.h"
#include "storage/spin.h"
Include dependency graph for shm_toc.c:

Go to the source code of this file.

Data Structures

struct  shm_toc_entry
 
struct  shm_toc
 

Typedefs

typedef struct shm_toc_entry shm_toc_entry
 

Functions

shm_tocshm_toc_create (uint64 magic, void *address, Size nbytes)
 
shm_tocshm_toc_attach (uint64 magic, void *address)
 
void * shm_toc_allocate (shm_toc *toc, Size nbytes)
 
Size shm_toc_freespace (shm_toc *toc)
 
void shm_toc_insert (shm_toc *toc, uint64 key, void *address)
 
void * shm_toc_lookup (shm_toc *toc, uint64 key, bool noError)
 
Size shm_toc_estimate (shm_toc_estimator *e)
 

Typedef Documentation

◆ shm_toc_entry

typedef struct shm_toc_entry shm_toc_entry

Function Documentation

◆ shm_toc_allocate()

void * shm_toc_allocate ( shm_toc toc,
Size  nbytes 
)

Definition at line 88 of file shm_toc.c.

89{
90 volatile shm_toc *vtoc = toc;
91 Size total_bytes;
92 Size allocated_bytes;
93 Size nentry;
94 Size toc_bytes;
95
96 /*
97 * Make sure request is well-aligned. XXX: MAXALIGN is not enough,
98 * because atomic ops might need a wider alignment. We don't have a
99 * proper definition for the minimum to make atomic ops safe, but
100 * BUFFERALIGN ought to be enough.
101 */
102 nbytes = BUFFERALIGN(nbytes);
103
105
106 total_bytes = vtoc->toc_total_bytes;
107 allocated_bytes = vtoc->toc_allocated_bytes;
108 nentry = vtoc->toc_nentry;
109 toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry)
110 + allocated_bytes;
111
112 /* Check for memory exhaustion and overflow. */
113 if (toc_bytes + nbytes > total_bytes || toc_bytes + nbytes < toc_bytes)
114 {
117 (errcode(ERRCODE_OUT_OF_MEMORY),
118 errmsg("out of shared memory")));
119 }
120 vtoc->toc_allocated_bytes += nbytes;
121
123
124 return ((char *) toc) + (total_bytes - allocated_bytes - nbytes);
125}
#define BUFFERALIGN(LEN)
Definition: c.h:767
size_t Size
Definition: c.h:559
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
struct shm_toc_entry shm_toc_entry
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
Size toc_total_bytes
Definition: shm_toc.c:30
uint32 toc_nentry
Definition: shm_toc.c:32
slock_t toc_mutex
Definition: shm_toc.c:29
Size toc_allocated_bytes
Definition: shm_toc.c:31

References BUFFERALIGN, ereport, errcode(), errmsg(), ERROR, SpinLockAcquire, SpinLockRelease, shm_toc::toc_allocated_bytes, shm_toc::toc_mutex, shm_toc::toc_nentry, and shm_toc::toc_total_bytes.

Referenced by _brin_begin_parallel(), _bt_begin_parallel(), ExecAggInitializeDSM(), ExecAppendInitializeDSM(), ExecBitmapHeapInitializeDSM(), ExecCustomScanInitializeDSM(), ExecForeignScanInitializeDSM(), ExecHashInitializeDSM(), ExecHashJoinInitializeDSM(), ExecIncrementalSortInitializeDSM(), ExecIndexOnlyScanInitializeDSM(), ExecIndexScanInitializeDSM(), ExecInitParallelPlan(), ExecMemoizeInitializeDSM(), ExecParallelSetupTupleQueues(), ExecSeqScanInitializeDSM(), ExecSortInitializeDSM(), GetSessionDsmHandle(), InitializeParallelDSM(), pa_setup_dsm(), parallel_vacuum_init(), and setup_dynamic_shared_memory().

◆ shm_toc_attach()

shm_toc * shm_toc_attach ( uint64  magic,
void *  address 
)

Definition at line 64 of file shm_toc.c.

65{
66 shm_toc *toc = (shm_toc *) address;
67
68 if (toc->toc_magic != magic)
69 return NULL;
70
72 Assert(toc->toc_total_bytes > offsetof(shm_toc, toc_entry));
73
74 return toc;
75}
#define Assert(condition)
Definition: c.h:812
uint64 toc_magic
Definition: shm_toc.c:28

References Assert, shm_toc::toc_allocated_bytes, shm_toc::toc_magic, and shm_toc::toc_total_bytes.

Referenced by AttachSession(), ParallelApplyWorkerMain(), ParallelWorkerMain(), and test_shm_mq_main().

◆ shm_toc_create()

shm_toc * shm_toc_create ( uint64  magic,
void *  address,
Size  nbytes 
)

Definition at line 40 of file shm_toc.c.

41{
42 shm_toc *toc = (shm_toc *) address;
43
44 Assert(nbytes > offsetof(shm_toc, toc_entry));
45 toc->toc_magic = magic;
47
48 /*
49 * The alignment code in shm_toc_allocate() assumes that the starting
50 * value is buffer-aligned.
51 */
52 toc->toc_total_bytes = BUFFERALIGN_DOWN(nbytes);
53 toc->toc_allocated_bytes = 0;
54 toc->toc_nentry = 0;
55
56 return toc;
57}
#define BUFFERALIGN_DOWN(LEN)
Definition: c.h:778
#define SpinLockInit(lock)
Definition: spin.h:57

References Assert, BUFFERALIGN_DOWN, SpinLockInit, shm_toc::toc_allocated_bytes, shm_toc::toc_magic, shm_toc::toc_mutex, shm_toc::toc_nentry, and shm_toc::toc_total_bytes.

Referenced by GetSessionDsmHandle(), InitializeParallelDSM(), pa_setup_dsm(), and setup_dynamic_shared_memory().

◆ shm_toc_estimate()

Size shm_toc_estimate ( shm_toc_estimator e)

Definition at line 263 of file shm_toc.c.

264{
265 Size sz;
266
267 sz = offsetof(shm_toc, toc_entry);
268 sz = add_size(sz, mul_size(e->number_of_keys, sizeof(shm_toc_entry)));
269 sz = add_size(sz, e->space_for_chunks);
270
271 return BUFFERALIGN(sz);
272}
e
Definition: preproc-init.c:82
Size add_size(Size s1, Size s2)
Definition: shmem.c:488
Size mul_size(Size s1, Size s2)
Definition: shmem.c:505
Definition: shm_toc.c:21

References add_size(), BUFFERALIGN, and mul_size().

Referenced by GetSessionDsmHandle(), InitializeParallelDSM(), pa_setup_dsm(), and setup_dynamic_shared_memory().

◆ shm_toc_freespace()

Size shm_toc_freespace ( shm_toc toc)

Definition at line 131 of file shm_toc.c.

132{
133 volatile shm_toc *vtoc = toc;
134 Size total_bytes;
135 Size allocated_bytes;
136 Size nentry;
137 Size toc_bytes;
138
140 total_bytes = vtoc->toc_total_bytes;
141 allocated_bytes = vtoc->toc_allocated_bytes;
142 nentry = vtoc->toc_nentry;
144
145 toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry);
146 Assert(allocated_bytes + BUFFERALIGN(toc_bytes) <= total_bytes);
147 return total_bytes - (allocated_bytes + BUFFERALIGN(toc_bytes));
148}

References Assert, BUFFERALIGN, SpinLockAcquire, SpinLockRelease, shm_toc::toc_allocated_bytes, shm_toc::toc_mutex, shm_toc::toc_nentry, and shm_toc::toc_total_bytes.

◆ shm_toc_insert()

void shm_toc_insert ( shm_toc toc,
uint64  key,
void *  address 
)

Definition at line 171 of file shm_toc.c.

172{
173 volatile shm_toc *vtoc = toc;
174 Size total_bytes;
175 Size allocated_bytes;
176 Size nentry;
177 Size toc_bytes;
178 Size offset;
179
180 /* Relativize pointer. */
181 Assert(address > (void *) toc);
182 offset = ((char *) address) - (char *) toc;
183
185
186 total_bytes = vtoc->toc_total_bytes;
187 allocated_bytes = vtoc->toc_allocated_bytes;
188 nentry = vtoc->toc_nentry;
189 toc_bytes = offsetof(shm_toc, toc_entry) + nentry * sizeof(shm_toc_entry)
190 + allocated_bytes;
191
192 /* Check for memory exhaustion and overflow. */
193 if (toc_bytes + sizeof(shm_toc_entry) > total_bytes ||
194 toc_bytes + sizeof(shm_toc_entry) < toc_bytes ||
195 nentry >= PG_UINT32_MAX)
196 {
199 (errcode(ERRCODE_OUT_OF_MEMORY),
200 errmsg("out of shared memory")));
201 }
202
203 Assert(offset < total_bytes);
204 vtoc->toc_entry[nentry].key = key;
205 vtoc->toc_entry[nentry].offset = offset;
206
207 /*
208 * By placing a write barrier after filling in the entry and before
209 * updating the number of entries, we make it safe to read the TOC
210 * unlocked.
211 */
213
214 vtoc->toc_nentry++;
215
217}
#define pg_write_barrier()
Definition: atomics.h:157
#define PG_UINT32_MAX
Definition: c.h:544
Size offset
Definition: shm_toc.c:23
uint64 key
Definition: shm_toc.c:22
shm_toc_entry toc_entry[FLEXIBLE_ARRAY_MEMBER]
Definition: shm_toc.c:33

References Assert, ereport, errcode(), errmsg(), ERROR, shm_toc_entry::key, sort-test::key, shm_toc_entry::offset, PG_UINT32_MAX, pg_write_barrier, SpinLockAcquire, SpinLockRelease, shm_toc::toc_allocated_bytes, shm_toc::toc_entry, shm_toc::toc_mutex, shm_toc::toc_nentry, and shm_toc::toc_total_bytes.

Referenced by _brin_begin_parallel(), _bt_begin_parallel(), ExecAggInitializeDSM(), ExecAppendInitializeDSM(), ExecBitmapHeapInitializeDSM(), ExecCustomScanInitializeDSM(), ExecForeignScanInitializeDSM(), ExecHashInitializeDSM(), ExecHashJoinInitializeDSM(), ExecIncrementalSortInitializeDSM(), ExecIndexOnlyScanInitializeDSM(), ExecIndexScanInitializeDSM(), ExecInitParallelPlan(), ExecMemoizeInitializeDSM(), ExecParallelSetupTupleQueues(), ExecSeqScanInitializeDSM(), ExecSortInitializeDSM(), GetSessionDsmHandle(), InitializeParallelDSM(), pa_setup_dsm(), parallel_vacuum_init(), and setup_dynamic_shared_memory().

◆ shm_toc_lookup()

void * shm_toc_lookup ( shm_toc toc,
uint64  key,
bool  noError 
)

Definition at line 232 of file shm_toc.c.

233{
234 uint32 nentry;
235 uint32 i;
236
237 /*
238 * Read the number of entries before we examine any entry. We assume that
239 * reading a uint32 is atomic.
240 */
241 nentry = toc->toc_nentry;
243
244 /* Now search for a matching entry. */
245 for (i = 0; i < nentry; ++i)
246 {
247 if (toc->toc_entry[i].key == key)
248 return ((char *) toc) + toc->toc_entry[i].offset;
249 }
250
251 /* No matching entry was found. */
252 if (!noError)
253 elog(ERROR, "could not find key " UINT64_FORMAT " in shm TOC at %p",
254 key, toc);
255 return NULL;
256}
#define pg_read_barrier()
Definition: atomics.h:156
#define UINT64_FORMAT
Definition: c.h:504
uint32_t uint32
Definition: c.h:485
#define elog(elevel,...)
Definition: elog.h:225
int i
Definition: isn.c:72

References elog, ERROR, i, shm_toc_entry::key, sort-test::key, pg_read_barrier, shm_toc::toc_entry, shm_toc::toc_nentry, and UINT64_FORMAT.

Referenced by _brin_parallel_build_main(), _bt_parallel_build_main(), attach_to_queues(), AttachSession(), ExecAggInitializeWorker(), ExecAppendInitializeWorker(), ExecBitmapHeapInitializeWorker(), ExecCustomScanInitializeWorker(), ExecCustomScanReInitializeDSM(), ExecForeignScanInitializeWorker(), ExecForeignScanReInitializeDSM(), ExecHashInitializeWorker(), ExecHashJoinInitializeWorker(), ExecHashJoinReInitializeDSM(), ExecIncrementalSortInitializeWorker(), ExecIndexOnlyScanInitializeWorker(), ExecIndexScanInitializeWorker(), ExecMemoizeInitializeWorker(), ExecParallelGetQueryDesc(), ExecParallelGetReceiver(), ExecParallelReinitialize(), ExecParallelSetupTupleQueues(), ExecSeqScanInitializeWorker(), ExecSortInitializeWorker(), parallel_vacuum_main(), ParallelApplyWorkerMain(), ParallelQueryMain(), ParallelWorkerMain(), ReinitializeParallelDSM(), test_shm_mq_main(), and WaitForParallelWorkersToFinish().