PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
shm_toc.h File Reference
#include "storage/shmem.h"
Include dependency graph for shm_toc.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  shm_toc_estimator
 

Macros

#define shm_toc_initialize_estimator(e)   ((e)->space_for_chunks = 0, (e)->number_of_keys = 0)
 
#define shm_toc_estimate_chunk(e, sz)   ((e)->space_for_chunks = add_size((e)->space_for_chunks, BUFFERALIGN(sz)))
 
#define shm_toc_estimate_keys(e, cnt)   ((e)->number_of_keys = add_size((e)->number_of_keys, cnt))
 

Typedefs

typedef struct shm_toc shm_toc
 

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)
 

Macro Definition Documentation

#define shm_toc_initialize_estimator (   e)    ((e)->space_for_chunks = 0, (e)->number_of_keys = 0)

Typedef Documentation

Definition at line 28 of file shm_toc.h.

Function Documentation

void* shm_toc_allocate ( shm_toc toc,
Size  nbytes 
)

Definition at line 88 of file shm_toc.c.

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

Referenced by ExecBitmapHeapInitializeDSM(), ExecCustomScanInitializeDSM(), ExecForeignScanInitializeDSM(), ExecIndexOnlyScanInitializeDSM(), ExecIndexScanInitializeDSM(), ExecInitParallelPlan(), ExecParallelSetupTupleQueues(), ExecSeqScanInitializeDSM(), ExecSortInitializeDSM(), GetSessionDsmHandle(), InitializeParallelDSM(), and setup_dynamic_shared_memory().

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 
104  SpinLockAcquire(&toc->toc_mutex);
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  {
115  SpinLockRelease(&toc->toc_mutex);
116  ereport(ERROR,
117  (errcode(ERRCODE_OUT_OF_MEMORY),
118  errmsg("out of shared memory")));
119  }
120  vtoc->toc_allocated_bytes += nbytes;
121 
122  SpinLockRelease(&toc->toc_mutex);
123 
124  return ((char *) toc) + (total_bytes - allocated_bytes - nbytes);
125 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
uint32 toc_nentry
Definition: shm_toc.c:32
#define ereport(elevel, rest)
Definition: elog.h:122
Size toc_total_bytes
Definition: shm_toc.c:30
slock_t toc_mutex
Definition: shm_toc.c:29
#define SpinLockRelease(lock)
Definition: spin.h:64
struct shm_toc_entry shm_toc_entry
size_t Size
Definition: c.h:350
Size toc_allocated_bytes
Definition: shm_toc.c:31
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define BUFFERALIGN(LEN)
Definition: c.h:578
#define offsetof(type, field)
Definition: c.h:549
shm_toc* shm_toc_attach ( uint64  magic,
void *  address 
)

Definition at line 64 of file shm_toc.c.

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

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

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 }
uint64 toc_magic
Definition: shm_toc.c:28
Size toc_total_bytes
Definition: shm_toc.c:30
#define Assert(condition)
Definition: c.h:681
Size toc_allocated_bytes
Definition: shm_toc.c:31
#define offsetof(type, field)
Definition: c.h:549
shm_toc* shm_toc_create ( uint64  magic,
void *  address,
Size  nbytes 
)

Definition at line 40 of file shm_toc.c.

References Assert, BUFFERALIGN_DOWN, offsetof, 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(), and setup_dynamic_shared_memory().

41 {
42  shm_toc *toc = (shm_toc *) address;
43 
44  Assert(nbytes > offsetof(shm_toc, toc_entry));
45  toc->toc_magic = magic;
46  SpinLockInit(&toc->toc_mutex);
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 }
uint64 toc_magic
Definition: shm_toc.c:28
#define SpinLockInit(lock)
Definition: spin.h:60
uint32 toc_nentry
Definition: shm_toc.c:32
Size toc_total_bytes
Definition: shm_toc.c:30
slock_t toc_mutex
Definition: shm_toc.c:29
#define BUFFERALIGN_DOWN(LEN)
Definition: c.h:589
#define Assert(condition)
Definition: c.h:681
Size toc_allocated_bytes
Definition: shm_toc.c:31
#define offsetof(type, field)
Definition: c.h:549
Size shm_toc_estimate ( shm_toc_estimator e)

Definition at line 263 of file shm_toc.c.

References add_size(), BUFFERALIGN, mul_size(), shm_toc_estimator::number_of_keys, offsetof, and shm_toc_estimator::space_for_chunks.

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

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 }
Size number_of_keys
Definition: shm_toc.h:46
Definition: shm_toc.c:20
Size space_for_chunks
Definition: shm_toc.h:45
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:350
#define BUFFERALIGN(LEN)
Definition: c.h:578
#define offsetof(type, field)
Definition: c.h:549
Size shm_toc_freespace ( shm_toc toc)

Definition at line 131 of file shm_toc.c.

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

132 {
133  volatile shm_toc *vtoc = toc;
134  Size total_bytes;
135  Size allocated_bytes;
136  Size nentry;
137  Size toc_bytes;
138 
139  SpinLockAcquire(&toc->toc_mutex);
140  total_bytes = vtoc->toc_total_bytes;
141  allocated_bytes = vtoc->toc_allocated_bytes;
142  nentry = vtoc->toc_nentry;
143  SpinLockRelease(&toc->toc_mutex);
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 }
#define SpinLockAcquire(lock)
Definition: spin.h:62
uint32 toc_nentry
Definition: shm_toc.c:32
Size toc_total_bytes
Definition: shm_toc.c:30
slock_t toc_mutex
Definition: shm_toc.c:29
#define SpinLockRelease(lock)
Definition: spin.h:64
struct shm_toc_entry shm_toc_entry
#define Assert(condition)
Definition: c.h:681
size_t Size
Definition: c.h:350
Size toc_allocated_bytes
Definition: shm_toc.c:31
#define BUFFERALIGN(LEN)
Definition: c.h:578
#define offsetof(type, field)
Definition: c.h:549
void shm_toc_insert ( shm_toc toc,
uint64  key,
void *  address 
)

Definition at line 171 of file shm_toc.c.

References Assert, ereport, errcode(), errmsg(), ERROR, shm_toc_entry::key, shm_toc_entry::offset, offsetof, 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 ExecBitmapHeapInitializeDSM(), ExecCustomScanInitializeDSM(), ExecForeignScanInitializeDSM(), ExecIndexOnlyScanInitializeDSM(), ExecIndexScanInitializeDSM(), ExecInitParallelPlan(), ExecParallelSetupTupleQueues(), ExecSeqScanInitializeDSM(), ExecSortInitializeDSM(), GetSessionDsmHandle(), InitializeParallelDSM(), and setup_dynamic_shared_memory().

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 
184  SpinLockAcquire(&toc->toc_mutex);
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  {
197  SpinLockRelease(&toc->toc_mutex);
198  ereport(ERROR,
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 
216  SpinLockRelease(&toc->toc_mutex);
217 }
shm_toc_entry toc_entry[FLEXIBLE_ARRAY_MEMBER]
Definition: shm_toc.c:33
int errcode(int sqlerrcode)
Definition: elog.c:575
Size offset
Definition: shm_toc.c:23
#define PG_UINT32_MAX
Definition: c.h:326
Definition: shm_toc.c:20
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
uint32 toc_nentry
Definition: shm_toc.c:32
#define ereport(elevel, rest)
Definition: elog.h:122
Size toc_total_bytes
Definition: shm_toc.c:30
slock_t toc_mutex
Definition: shm_toc.c:29
#define SpinLockRelease(lock)
Definition: spin.h:64
struct shm_toc_entry shm_toc_entry
#define Assert(condition)
Definition: c.h:681
size_t Size
Definition: c.h:350
Size toc_allocated_bytes
Definition: shm_toc.c:31
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define pg_write_barrier()
Definition: atomics.h:162
uint64 key
Definition: shm_toc.c:22
#define offsetof(type, field)
Definition: c.h:549
void* shm_toc_lookup ( shm_toc toc,
uint64  key,
bool  noError 
)

Definition at line 232 of file shm_toc.c.

References elog, ERROR, i, shm_toc_entry::key, shm_toc_entry::offset, pg_read_barrier, shm_toc::toc_entry, shm_toc::toc_nentry, and UINT64_FORMAT.

Referenced by attach_to_queues(), AttachSession(), ExecBitmapHeapInitializeWorker(), ExecCustomScanInitializeWorker(), ExecCustomScanReInitializeDSM(), ExecForeignScanInitializeWorker(), ExecForeignScanReInitializeDSM(), ExecIndexOnlyScanInitializeWorker(), ExecIndexScanInitializeWorker(), ExecParallelGetQueryDesc(), ExecParallelGetReceiver(), ExecParallelSetupTupleQueues(), ExecSeqScanInitializeWorker(), ExecSortInitializeWorker(), ParallelQueryMain(), ParallelWorkerMain(), ReinitializeParallelDSM(), test_shm_mq_main(), and WaitForParallelWorkersToFinish().

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;
242  pg_read_barrier();
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 }
shm_toc_entry toc_entry[FLEXIBLE_ARRAY_MEMBER]
Definition: shm_toc.c:33
Size offset
Definition: shm_toc.c:23
#define ERROR
Definition: elog.h:43
uint32 toc_nentry
Definition: shm_toc.c:32
unsigned int uint32
Definition: c.h:258
#define pg_read_barrier()
Definition: atomics.h:161
int i
uint64 key
Definition: shm_toc.c:22
#define elog
Definition: elog.h:219
#define UINT64_FORMAT
Definition: c.h:301