PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
dsm.c File Reference
#include "postgres.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "lib/ilist.h"
#include "miscadmin.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
#include "storage/lwlock.h"
#include "storage/pg_shmem.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/resowner_private.h"
Include dependency graph for dsm.c:

Go to the source code of this file.

Data Structures

struct  dsm_segment_detach_callback
 
struct  dsm_segment
 
struct  dsm_control_item
 
struct  dsm_control_header
 

Macros

#define PG_DYNSHMEM_CONTROL_MAGIC   0x9a503d32
 
#define PG_DYNSHMEM_FIXED_SLOTS   64
 
#define PG_DYNSHMEM_SLOTS_PER_BACKEND   2
 
#define INVALID_CONTROL_SLOT   ((uint32) -1)
 

Typedefs

typedef struct
dsm_segment_detach_callback 
dsm_segment_detach_callback
 
typedef struct dsm_control_item dsm_control_item
 
typedef struct dsm_control_header dsm_control_header
 

Functions

static void dsm_cleanup_for_mmap (void)
 
static void dsm_postmaster_shutdown (int code, Datum arg)
 
static dsm_segmentdsm_create_descriptor (void)
 
static bool dsm_control_segment_sane (dsm_control_header *control, Size mapped_size)
 
static uint64 dsm_control_bytes_needed (uint32 nitems)
 
void dsm_postmaster_startup (PGShmemHeader *shim)
 
void dsm_cleanup_using_control_segment (dsm_handle old_control_handle)
 
static void dsm_backend_startup (void)
 
dsm_segmentdsm_create (Size size, int flags)
 
dsm_segmentdsm_attach (dsm_handle h)
 
void dsm_backend_shutdown (void)
 
void dsm_detach_all (void)
 
void * dsm_resize (dsm_segment *seg, Size size)
 
void * dsm_remap (dsm_segment *seg)
 
void dsm_detach (dsm_segment *seg)
 
void dsm_pin_mapping (dsm_segment *seg)
 
void dsm_unpin_mapping (dsm_segment *seg)
 
void dsm_pin_segment (dsm_segment *seg)
 
void dsm_unpin_segment (dsm_handle handle)
 
dsm_segmentdsm_find_mapping (dsm_handle h)
 
void * dsm_segment_address (dsm_segment *seg)
 
Size dsm_segment_map_length (dsm_segment *seg)
 
dsm_handle dsm_segment_handle (dsm_segment *seg)
 
void on_dsm_detach (dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
 
void cancel_on_dsm_detach (dsm_segment *seg, on_dsm_detach_callback function, Datum arg)
 
void reset_on_dsm_detach (void)
 

Variables

static bool dsm_init_done = false
 
static dlist_head dsm_segment_list = DLIST_STATIC_INIT(dsm_segment_list)
 
static dsm_handle dsm_control_handle
 
static dsm_control_headerdsm_control
 
static Size dsm_control_mapped_size = 0
 
static void * dsm_control_impl_private = NULL
 

Macro Definition Documentation

#define INVALID_CONTROL_SLOT   ((uint32) -1)
#define PG_DYNSHMEM_CONTROL_MAGIC   0x9a503d32

Definition at line 46 of file dsm.c.

Referenced by dsm_control_segment_sane(), and dsm_postmaster_startup().

#define PG_DYNSHMEM_FIXED_SLOTS   64

Definition at line 53 of file dsm.c.

Referenced by dsm_postmaster_startup().

#define PG_DYNSHMEM_SLOTS_PER_BACKEND   2

Definition at line 54 of file dsm.c.

Referenced by dsm_postmaster_startup().

Typedef Documentation

Function Documentation

void cancel_on_dsm_detach ( dsm_segment seg,
on_dsm_detach_callback  function,
Datum  arg 
)

Definition at line 1040 of file dsm.c.

References dsm_segment_detach_callback::arg, slist_mutable_iter::cur, dsm_segment_detach_callback::function, dsm_segment::on_detach, pfree(), slist_container, slist_delete_current(), and slist_foreach_modify.

Referenced by test_shm_mq_setup().

1042 {
1043  slist_mutable_iter iter;
1044 
1045  slist_foreach_modify(iter, &seg->on_detach)
1046  {
1048 
1050  if (cb->function == function && cb->arg == arg)
1051  {
1052  slist_delete_current(&iter);
1053  pfree(cb);
1054  break;
1055  }
1056  }
1057 }
slist_node * cur
Definition: ilist.h:241
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:716
void pfree(void *pointer)
Definition: mcxt.c:950
on_dsm_detach_callback function
Definition: dsm.c:61
slist_head on_detach
Definition: dsm.c:76
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
void * arg
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:652
dsm_segment* dsm_attach ( dsm_handle  h)

Definition at line 549 of file dsm.c.

References Assert, dsm_segment::control_slot, dlist_iter::cur, dlist_container, dlist_foreach, dsm_backend_startup(), dsm_create_descriptor(), dsm_detach(), dsm_impl_op(), dsm_init_done, DSM_OP_ATTACH, elog, ERROR, dsm_segment::handle, dsm_control_item::handle, i, dsm_segment::impl_private, INVALID_CONTROL_SLOT, IsUnderPostmaster, dsm_control_header::item, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), dsm_segment::mapped_address, dsm_segment::mapped_size, dsm_control_header::nitems, NULL, and dsm_control_item::refcnt.

Referenced by dsa_attach(), get_segment_by_index(), ParallelWorkerMain(), and test_shm_mq_main().

550 {
551  dsm_segment *seg;
552  dlist_iter iter;
553  uint32 i;
554  uint32 nitems;
555 
556  /* Unsafe in postmaster (and pointless in a stand-alone backend). */
558 
559  if (!dsm_init_done)
561 
562  /*
563  * Since this is just a debugging cross-check, we could leave it out
564  * altogether, or include it only in assert-enabled builds. But since the
565  * list of attached segments should normally be very short, let's include
566  * it always for right now.
567  *
568  * If you're hitting this error, you probably want to attempt to find an
569  * existing mapping via dsm_find_mapping() before calling dsm_attach() to
570  * create a new one.
571  */
573  {
574  seg = dlist_container(dsm_segment, node, iter.cur);
575  if (seg->handle == h)
576  elog(ERROR, "can't attach the same segment more than once");
577  }
578 
579  /* Create a new segment descriptor. */
580  seg = dsm_create_descriptor();
581  seg->handle = h;
582 
583  /* Bump reference count for this segment in shared memory. */
584  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
585  nitems = dsm_control->nitems;
586  for (i = 0; i < nitems; ++i)
587  {
588  /* If the reference count is 0, the slot is actually unused. */
589  if (dsm_control->item[i].refcnt == 0)
590  continue;
591 
592  /* If the handle doesn't match, it's not the slot we want. */
593  if (dsm_control->item[i].handle != seg->handle)
594  continue;
595 
596  /*
597  * If the reference count is 1, the slot is still in use, but the
598  * segment is in the process of going away. Treat that as if we
599  * didn't find a match.
600  */
601  if (dsm_control->item[i].refcnt == 1)
602  break;
603 
604  /* Otherwise we've found a match. */
605  dsm_control->item[i].refcnt++;
606  seg->control_slot = i;
607  break;
608  }
609  LWLockRelease(DynamicSharedMemoryControlLock);
610 
611  /*
612  * If we didn't find the handle we're looking for in the control segment,
613  * it probably means that everyone else who had it mapped, including the
614  * original creator, died before we got to this point. It's up to the
615  * caller to decide what to do about that.
616  */
618  {
619  dsm_detach(seg);
620  return NULL;
621  }
622 
623  /* Here's where we actually try to map the segment. */
625  &seg->mapped_address, &seg->mapped_size, ERROR);
626 
627  return seg;
628 }
Size mapped_size
Definition: dsm.c:75
dsm_handle handle
Definition: dsm.c:82
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
static void dsm_backend_startup(void)
Definition: dsm.c:405
static dlist_head dsm_segment_list
Definition: dsm.c:124
uint32 nitems
Definition: dsm.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define ERROR
Definition: elog.h:43
bool IsUnderPostmaster
Definition: globals.c:100
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
unsigned int uint32
Definition: c.h:268
void * mapped_address
Definition: dsm.c:74
dsm_handle handle
Definition: dsm.c:71
dlist_node * cur
Definition: ilist.h:161
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void * impl_private
Definition: dsm.c:73
uint32 control_slot
Definition: dsm.c:72
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static dsm_segment * dsm_create_descriptor(void)
Definition: dsm.c:1094
uint32 refcnt
Definition: dsm.c:83
static bool dsm_init_done
Definition: dsm.c:105
void dsm_detach(dsm_segment *seg)
Definition: dsm.c:714
int i
#define INVALID_CONTROL_SLOT
Definition: dsm.c:56
#define elog
Definition: elog.h:219
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
void dsm_backend_shutdown ( void  )

Definition at line 636 of file dsm.c.

References dlist_head_element, dlist_is_empty(), and dsm_detach().

Referenced by shmem_exit().

637 {
639  {
640  dsm_segment *seg;
641 
643  dsm_detach(seg);
644  }
645 }
static dlist_head dsm_segment_list
Definition: dsm.c:124
#define dlist_head_element(type, membername, lhead)
Definition: ilist.h:487
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
void dsm_detach(dsm_segment *seg)
Definition: dsm.c:714
static void dsm_backend_startup ( void  )
static

Definition at line 405 of file dsm.c.

References Assert, dsm_control_handle, dsm_control_impl_private, dsm_control_mapped_size, dsm_control_segment_sane(), DSM_IMPL_NONE, dsm_impl_op(), dsm_init_done, DSM_OP_ATTACH, DSM_OP_DETACH, dynamic_shared_memory_type, ereport, errcode(), errhint(), errmsg(), ERROR, FATAL, NULL, and WARNING.

Referenced by dsm_attach(), and dsm_create().

406 {
407  /* If dynamic shared memory is disabled, reject this. */
409  ereport(ERROR,
410  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
411  errmsg("dynamic shared memory is disabled"),
412  errhint("Set dynamic_shared_memory_type to a value other than \"none\".")));
413 
414 #ifdef EXEC_BACKEND
415  {
416  void *control_address = NULL;
417 
418  /* Attach control segment. */
421  &dsm_control_impl_private, &control_address,
423  dsm_control = control_address;
424  /* If control segment doesn't look sane, something is badly wrong. */
426  {
428  &dsm_control_impl_private, &control_address,
430  ereport(FATAL,
431  (errcode(ERRCODE_INTERNAL_ERROR),
432  errmsg("dynamic shared memory control segment is not valid")));
433  }
434  }
435 #endif
436 
437  dsm_init_done = true;
438 }
static void * dsm_control_impl_private
Definition: dsm.c:136
int errhint(const char *fmt,...)
Definition: elog.c:987
static dsm_handle dsm_control_handle
Definition: dsm.c:133
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
int dynamic_shared_memory_type
Definition: dsm_impl.c:112
#define ereport(elevel, rest)
Definition: elog.h:122
static bool dsm_control_segment_sane(dsm_control_header *control, Size mapped_size)
Definition: dsm.c:1128
#define WARNING
Definition: elog.h:40
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define DSM_IMPL_NONE
Definition: dsm_impl.h:17
static bool dsm_init_done
Definition: dsm.c:105
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Size dsm_control_mapped_size
Definition: dsm.c:135
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
static void dsm_cleanup_for_mmap ( void  )
static

Definition at line 292 of file dsm.c.

References AllocateDir(), buf, closedir(), dirent::d_name, DEBUG2, elog, ereport, errcode_for_file_access(), errmsg(), ERROR, FreeDir(), MAXPGPATH, NULL, PG_DYNSHMEM_DIR, PG_DYNSHMEM_MMAP_FILE_PREFIX, ReadDir(), snprintf(), and unlink().

Referenced by dsm_postmaster_startup().

293 {
294  DIR *dir;
295  struct dirent *dent;
296 
297  /* Open the directory; can't use AllocateDir in postmaster. */
298  if ((dir = AllocateDir(PG_DYNSHMEM_DIR)) == NULL)
299  ereport(ERROR,
301  errmsg("could not open directory \"%s\": %m",
302  PG_DYNSHMEM_DIR)));
303 
304  /* Scan for something with a name of the correct format. */
305  while ((dent = ReadDir(dir, PG_DYNSHMEM_DIR)) != NULL)
306  {
307  if (strncmp(dent->d_name, PG_DYNSHMEM_MMAP_FILE_PREFIX,
308  strlen(PG_DYNSHMEM_MMAP_FILE_PREFIX)) == 0)
309  {
310  char buf[MAXPGPATH];
311 
312  snprintf(buf, MAXPGPATH, PG_DYNSHMEM_DIR "/%s", dent->d_name);
313 
314  elog(DEBUG2, "removing file \"%s\"", buf);
315 
316  /* We found a matching file; so remove it. */
317  if (unlink(buf) != 0)
318  {
319  int save_errno;
320 
321  save_errno = errno;
322  closedir(dir);
323  errno = save_errno;
324 
325  ereport(ERROR,
327  errmsg("could not remove file \"%s\": %m", buf)));
328  }
329  }
330  }
331 
332  /* Cleanup complete. */
333  FreeDir(dir);
334 }
#define PG_DYNSHMEM_DIR
Definition: dsm_impl.h:51
int closedir(DIR *)
Definition: dirent.c:113
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
Definition: dirent.h:9
Definition: dirent.c:25
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define DEBUG2
Definition: elog.h:24
static char * buf
Definition: pg_test_fsync.c:65
int errcode_for_file_access(void)
Definition: elog.c:598
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2335
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_DYNSHMEM_MMAP_FILE_PREFIX
Definition: dsm_impl.h:52
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2444
void dsm_cleanup_using_control_segment ( dsm_handle  old_control_handle)

Definition at line 210 of file dsm.c.

References DEBUG1, DEBUG2, dsm_control_segment_sane(), DSM_IMPL_NONE, dsm_impl_op(), DSM_OP_ATTACH, DSM_OP_DESTROY, DSM_OP_DETACH, dynamic_shared_memory_type, elog, dsm_control_item::handle, i, dsm_control_header::item, LOG, dsm_control_header::nitems, NULL, and dsm_control_item::refcnt.

Referenced by PGSharedMemoryCreate().

211 {
212  void *mapped_address = NULL;
213  void *junk_mapped_address = NULL;
214  void *impl_private = NULL;
215  void *junk_impl_private = NULL;
216  Size mapped_size = 0;
217  Size junk_mapped_size = 0;
218  uint32 nitems;
219  uint32 i;
220  dsm_control_header *old_control;
221 
222  /* If dynamic shared memory is disabled, there's nothing to do. */
224  return;
225 
226  /*
227  * Try to attach the segment. If this fails, it probably just means that
228  * the operating system has been rebooted and the segment no longer
229  * exists, or an unrelated process has used the same shm ID. So just fall
230  * out quietly.
231  */
232  if (!dsm_impl_op(DSM_OP_ATTACH, old_control_handle, 0, &impl_private,
233  &mapped_address, &mapped_size, DEBUG1))
234  return;
235 
236  /*
237  * We've managed to reattach it, but the contents might not be sane. If
238  * they aren't, we disregard the segment after all.
239  */
240  old_control = (dsm_control_header *) mapped_address;
241  if (!dsm_control_segment_sane(old_control, mapped_size))
242  {
243  dsm_impl_op(DSM_OP_DETACH, old_control_handle, 0, &impl_private,
244  &mapped_address, &mapped_size, LOG);
245  return;
246  }
247 
248  /*
249  * OK, the control segment looks basically valid, so we can use it to get
250  * a list of segments that need to be removed.
251  */
252  nitems = old_control->nitems;
253  for (i = 0; i < nitems; ++i)
254  {
255  dsm_handle handle;
256  uint32 refcnt;
257 
258  /* If the reference count is 0, the slot is actually unused. */
259  refcnt = old_control->item[i].refcnt;
260  if (refcnt == 0)
261  continue;
262 
263  /* Log debugging information. */
264  handle = old_control->item[i].handle;
265  elog(DEBUG2, "cleaning up orphaned dynamic shared memory with ID %u (reference count %u)",
266  handle, refcnt);
267 
268  /* Destroy the referenced segment. */
269  dsm_impl_op(DSM_OP_DESTROY, handle, 0, &junk_impl_private,
270  &junk_mapped_address, &junk_mapped_size, LOG);
271  }
272 
273  /* Destroy the old control segment, too. */
274  elog(DEBUG2,
275  "cleaning up dynamic shared memory control segment with ID %u",
276  old_control_handle);
277  dsm_impl_op(DSM_OP_DESTROY, old_control_handle, 0, &impl_private,
278  &mapped_address, &mapped_size, LOG);
279 }
#define DEBUG1
Definition: elog.h:25
uint32 dsm_handle
Definition: dsm_impl.h:55
dsm_handle handle
Definition: dsm.c:82
#define LOG
Definition: elog.h:26
uint32 nitems
Definition: dsm.c:92
#define DEBUG2
Definition: elog.h:24
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
int dynamic_shared_memory_type
Definition: dsm_impl.c:112
unsigned int uint32
Definition: c.h:268
static bool dsm_control_segment_sane(dsm_control_header *control, Size mapped_size)
Definition: dsm.c:1128
#define NULL
Definition: c.h:229
#define DSM_IMPL_NONE
Definition: dsm_impl.h:17
size_t Size
Definition: c.h:356
uint32 refcnt
Definition: dsm.c:83
int i
#define elog
Definition: elog.h:219
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
static uint64 dsm_control_bytes_needed ( uint32  nitems)
static

Definition at line 1146 of file dsm.c.

References offsetof.

Referenced by dsm_control_segment_sane(), and dsm_postmaster_startup().

1147 {
1148  return offsetof(dsm_control_header, item)
1149  +sizeof(dsm_control_item) * (uint64) nitems;
1150 }
struct dsm_control_item dsm_control_item
#define offsetof(type, field)
Definition: c.h:555
static bool dsm_control_segment_sane ( dsm_control_header control,
Size  mapped_size 
)
static

Definition at line 1128 of file dsm.c.

References dsm_control_bytes_needed(), dsm_control_header::magic, dsm_control_header::maxitems, dsm_control_header::nitems, offsetof, and PG_DYNSHMEM_CONTROL_MAGIC.

Referenced by dsm_backend_startup(), dsm_cleanup_using_control_segment(), and dsm_postmaster_shutdown().

1129 {
1130  if (mapped_size < offsetof(dsm_control_header, item))
1131  return false; /* Mapped size too short to read header. */
1132  if (control->magic != PG_DYNSHMEM_CONTROL_MAGIC)
1133  return false; /* Magic number doesn't match. */
1134  if (dsm_control_bytes_needed(control->maxitems) > mapped_size)
1135  return false; /* Max item count won't fit in map. */
1136  if (control->nitems > control->maxitems)
1137  return false; /* Overfull. */
1138  return true;
1139 }
uint32 maxitems
Definition: dsm.c:93
static uint64 dsm_control_bytes_needed(uint32 nitems)
Definition: dsm.c:1146
uint32 nitems
Definition: dsm.c:92
uint32 magic
Definition: dsm.c:91
#define PG_DYNSHMEM_CONTROL_MAGIC
Definition: dsm.c:46
#define offsetof(type, field)
Definition: c.h:555
dsm_segment* dsm_create ( Size  size,
int  flags 
)

Definition at line 458 of file dsm.c.

References Assert, dsm_segment::control_slot, dlist_delete(), dsm_backend_startup(), dsm_create_descriptor(), DSM_CREATE_NULL_IF_MAXSEGMENTS, DSM_HANDLE_INVALID, dsm_impl_op(), dsm_init_done, DSM_OP_CREATE, DSM_OP_DESTROY, ereport, errcode(), errmsg(), ERROR, dsm_segment::handle, dsm_control_item::handle, i, dsm_segment::impl_private, dsm_control_item::impl_private_pm_handle, IsUnderPostmaster, dsm_control_header::item, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), dsm_segment::mapped_address, dsm_segment::mapped_size, dsm_control_header::maxitems, dsm_control_header::nitems, dsm_segment::node, NULL, pfree(), dsm_control_item::pinned, random(), dsm_control_item::refcnt, ResourceOwnerForgetDSM(), dsm_segment::resowner, and WARNING.

Referenced by dsa_create(), InitializeParallelDSM(), make_new_segment(), and setup_dynamic_shared_memory().

459 {
460  dsm_segment *seg;
461  uint32 i;
462  uint32 nitems;
463 
464  /* Unsafe in postmaster (and pointless in a stand-alone backend). */
466 
467  if (!dsm_init_done)
469 
470  /* Create a new segment descriptor. */
471  seg = dsm_create_descriptor();
472 
473  /* Loop until we find an unused segment identifier. */
474  for (;;)
475  {
476  Assert(seg->mapped_address == NULL && seg->mapped_size == 0);
477  seg->handle = random();
478  if (seg->handle == DSM_HANDLE_INVALID) /* Reserve sentinel */
479  continue;
480  if (dsm_impl_op(DSM_OP_CREATE, seg->handle, size, &seg->impl_private,
481  &seg->mapped_address, &seg->mapped_size, ERROR))
482  break;
483  }
484 
485  /* Lock the control segment so we can register the new segment. */
486  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
487 
488  /* Search the control segment for an unused slot. */
489  nitems = dsm_control->nitems;
490  for (i = 0; i < nitems; ++i)
491  {
492  if (dsm_control->item[i].refcnt == 0)
493  {
494  dsm_control->item[i].handle = seg->handle;
495  /* refcnt of 1 triggers destruction, so start at 2 */
496  dsm_control->item[i].refcnt = 2;
498  dsm_control->item[i].pinned = false;
499  seg->control_slot = i;
500  LWLockRelease(DynamicSharedMemoryControlLock);
501  return seg;
502  }
503  }
504 
505  /* Verify that we can support an additional mapping. */
506  if (nitems >= dsm_control->maxitems)
507  {
508  if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0)
509  {
510  LWLockRelease(DynamicSharedMemoryControlLock);
512  &seg->mapped_address, &seg->mapped_size, WARNING);
513  if (seg->resowner != NULL)
514  ResourceOwnerForgetDSM(seg->resowner, seg);
515  dlist_delete(&seg->node);
516  pfree(seg);
517  return NULL;
518  }
519  ereport(ERROR,
520  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
521  errmsg("too many dynamic shared memory segments")));
522  }
523 
524  /* Enter the handle into a new array slot. */
525  dsm_control->item[nitems].handle = seg->handle;
526  /* refcnt of 1 triggers destruction, so start at 2 */
527  dsm_control->item[nitems].refcnt = 2;
529  dsm_control->item[nitems].pinned = false;
530  seg->control_slot = nitems;
531  dsm_control->nitems++;
532  LWLockRelease(DynamicSharedMemoryControlLock);
533 
534  return seg;
535 }
dlist_node node
Definition: dsm.c:69
uint32 maxitems
Definition: dsm.c:93
Size mapped_size
Definition: dsm.c:75
dsm_handle handle
Definition: dsm.c:82
long random(void)
Definition: random.c:22
int errcode(int sqlerrcode)
Definition: elog.c:575
static void dsm_backend_startup(void)
Definition: dsm.c:405
uint32 nitems
Definition: dsm.c:92
bool pinned
Definition: dsm.c:85
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define DSM_HANDLE_INVALID
Definition: dsm.h:23
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
#define DSM_CREATE_NULL_IF_MAXSEGMENTS
Definition: dsm.h:20
bool IsUnderPostmaster
Definition: globals.c:100
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
unsigned int uint32
Definition: c.h:268
void * mapped_address
Definition: dsm.c:74
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
dsm_handle handle
Definition: dsm.c:71
static dsm_control_header * dsm_control
Definition: dsm.c:134
ResourceOwner resowner
Definition: dsm.c:70
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void * impl_private
Definition: dsm.c:73
void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1254
uint32 control_slot
Definition: dsm.c:72
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static dsm_segment * dsm_create_descriptor(void)
Definition: dsm.c:1094
uint32 refcnt
Definition: dsm.c:83
static bool dsm_init_done
Definition: dsm.c:105
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void * impl_private_pm_handle
Definition: dsm.c:84
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
static dsm_segment * dsm_create_descriptor ( void  )
static

Definition at line 1094 of file dsm.c.

References dsm_segment::control_slot, CurrentResourceOwner, dlist_push_head(), dsm_segment::impl_private, INVALID_CONTROL_SLOT, dsm_segment::mapped_address, dsm_segment::mapped_size, MemoryContextAlloc(), dsm_segment::node, NULL, dsm_segment::on_detach, ResourceOwnerEnlargeDSMs(), ResourceOwnerRememberDSM(), dsm_segment::resowner, slist_init(), and TopMemoryContext.

Referenced by dsm_attach(), and dsm_create().

1095 {
1096  dsm_segment *seg;
1097 
1099 
1102 
1103  /* seg->handle must be initialized by the caller */
1105  seg->impl_private = NULL;
1106  seg->mapped_address = NULL;
1107  seg->mapped_size = 0;
1108 
1111 
1112  slist_init(&seg->on_detach);
1113 
1114  return seg;
1115 }
dlist_node node
Definition: dsm.c:69
void ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1245
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
Size mapped_size
Definition: dsm.c:75
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static dlist_head dsm_segment_list
Definition: dsm.c:124
static void slist_init(slist_head *head)
Definition: ilist.h:554
void ResourceOwnerEnlargeDSMs(ResourceOwner owner)
Definition: resowner.c:1234
void * mapped_address
Definition: dsm.c:74
MemoryContext TopMemoryContext
Definition: mcxt.c:43
slist_head on_detach
Definition: dsm.c:76
ResourceOwner resowner
Definition: dsm.c:70
#define NULL
Definition: c.h:229
void * impl_private
Definition: dsm.c:73
uint32 control_slot
Definition: dsm.c:72
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
#define INVALID_CONTROL_SLOT
Definition: dsm.c:56
void dsm_detach ( dsm_segment seg)

Definition at line 714 of file dsm.c.

References arg, dsm_segment_detach_callback::arg, Assert, dsm_segment::control_slot, dlist_delete(), dsm_impl_op(), DSM_OP_DESTROY, DSM_OP_DETACH, dsm_segment_detach_callback::function, dsm_segment::handle, dsm_control_item::handle, dsm_segment::impl_private, INVALID_CONTROL_SLOT, dsm_control_header::item, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), dsm_segment::mapped_address, dsm_segment::mapped_size, dsm_segment::node, NULL, dsm_segment::on_detach, pfree(), dsm_control_item::pinned, dsm_control_item::refcnt, ResourceOwnerForgetDSM(), dsm_segment::resowner, slist_container, slist_is_empty(), slist_pop_head_node(), and WARNING.

Referenced by check_for_freed_segments(), destroy_superblock(), DestroyParallelContext(), dsa_detach(), dsm_attach(), dsm_backend_shutdown(), dsm_detach_all(), ResourceOwnerReleaseInternal(), test_shm_mq(), test_shm_mq_main(), and test_shm_mq_pipelined().

715 {
716  /*
717  * Invoke registered callbacks. Just in case one of those callbacks
718  * throws a further error that brings us back here, pop the callback
719  * before invoking it, to avoid infinite error recursion.
720  */
721  while (!slist_is_empty(&seg->on_detach))
722  {
723  slist_node *node;
725  on_dsm_detach_callback function;
726  Datum arg;
727 
728  node = slist_pop_head_node(&seg->on_detach);
730  function = cb->function;
731  arg = cb->arg;
732  pfree(cb);
733 
734  function(seg, arg);
735  }
736 
737  /*
738  * Try to remove the mapping, if one exists. Normally, there will be, but
739  * maybe not, if we failed partway through a create or attach operation.
740  * We remove the mapping before decrementing the reference count so that
741  * the process that sees a zero reference count can be certain that no
742  * remaining mappings exist. Even if this fails, we pretend that it
743  * works, because retrying is likely to fail in the same way.
744  */
745  if (seg->mapped_address != NULL)
746  {
748  &seg->mapped_address, &seg->mapped_size, WARNING);
749  seg->impl_private = NULL;
750  seg->mapped_address = NULL;
751  seg->mapped_size = 0;
752  }
753 
754  /* Reduce reference count, if we previously increased it. */
756  {
757  uint32 refcnt;
758  uint32 control_slot = seg->control_slot;
759 
760  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
761  Assert(dsm_control->item[control_slot].handle == seg->handle);
762  Assert(dsm_control->item[control_slot].refcnt > 1);
763  refcnt = --dsm_control->item[control_slot].refcnt;
765  LWLockRelease(DynamicSharedMemoryControlLock);
766 
767  /* If new reference count is 1, try to destroy the segment. */
768  if (refcnt == 1)
769  {
770  /* A pinned segment should never reach 1. */
771  Assert(!dsm_control->item[control_slot].pinned);
772 
773  /*
774  * If we fail to destroy the segment here, or are killed before we
775  * finish doing so, the reference count will remain at 1, which
776  * will mean that nobody else can attach to the segment. At
777  * postmaster shutdown time, or when a new postmaster is started
778  * after a hard kill, another attempt will be made to remove the
779  * segment.
780  *
781  * The main case we're worried about here is being killed by a
782  * signal before we can finish removing the segment. In that
783  * case, it's important to be sure that the segment still gets
784  * removed. If we actually fail to remove the segment for some
785  * other reason, the postmaster may not have any better luck than
786  * we did. There's not much we can do about that, though.
787  */
788  if (dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
789  &seg->mapped_address, &seg->mapped_size, WARNING))
790  {
791  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
792  Assert(dsm_control->item[control_slot].handle == seg->handle);
793  Assert(dsm_control->item[control_slot].refcnt == 1);
794  dsm_control->item[control_slot].refcnt = 0;
795  LWLockRelease(DynamicSharedMemoryControlLock);
796  }
797  }
798  }
799 
800  /* Clean up our remaining backend-private data structures. */
801  if (seg->resowner != NULL)
802  ResourceOwnerForgetDSM(seg->resowner, seg);
803  dlist_delete(&seg->node);
804  pfree(seg);
805 }
dlist_node node
Definition: dsm.c:69
Size mapped_size
Definition: dsm.c:75
dsm_handle handle
Definition: dsm.c:82
void(* on_dsm_detach_callback)(dsm_segment *, Datum arg)
Definition: dsm.h:56
bool pinned
Definition: dsm.c:85
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void pfree(void *pointer)
Definition: mcxt.c:950
on_dsm_detach_callback function
Definition: dsm.c:61
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
unsigned int uint32
Definition: c.h:268
void * mapped_address
Definition: dsm.c:74
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
static slist_node * slist_pop_head_node(slist_head *head)
Definition: ilist.h:596
slist_head on_detach
Definition: dsm.c:76
static bool slist_is_empty(slist_head *head)
Definition: ilist.h:563
#define WARNING
Definition: elog.h:40
dsm_handle handle
Definition: dsm.c:71
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
uintptr_t Datum
Definition: postgres.h:372
static dsm_control_header * dsm_control
Definition: dsm.c:134
ResourceOwner resowner
Definition: dsm.c:70
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void * impl_private
Definition: dsm.c:73
void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1254
uint32 control_slot
Definition: dsm.c:72
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
uint32 refcnt
Definition: dsm.c:83
void * arg
#define INVALID_CONTROL_SLOT
Definition: dsm.c:56
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
void dsm_detach_all ( void  )

Definition at line 654 of file dsm.c.

References dlist_head_element, dlist_is_empty(), dsm_control, dsm_control_handle, dsm_control_impl_private, dsm_control_mapped_size, dsm_detach(), dsm_impl_op(), DSM_OP_DETACH, ERROR, and NULL.

Referenced by pgarch_start(), pgstat_start(), StartBackgroundWorker(), and SysLogger_Start().

655 {
656  void *control_address = dsm_control;
657 
659  {
660  dsm_segment *seg;
661 
663  dsm_detach(seg);
664  }
665 
666  if (control_address != NULL)
668  &dsm_control_impl_private, &control_address,
670 }
static void * dsm_control_impl_private
Definition: dsm.c:136
static dsm_handle dsm_control_handle
Definition: dsm.c:133
static dlist_head dsm_segment_list
Definition: dsm.c:124
#define ERROR
Definition: elog.h:43
#define dlist_head_element(type, membername, lhead)
Definition: ilist.h:487
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define NULL
Definition: c.h:229
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
void dsm_detach(dsm_segment *seg)
Definition: dsm.c:714
static Size dsm_control_mapped_size
Definition: dsm.c:135
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
dsm_segment* dsm_find_mapping ( dsm_handle  h)

Definition at line 969 of file dsm.c.

References dlist_iter::cur, dlist_container, dlist_foreach, dsm_segment::handle, and NULL.

970 {
971  dlist_iter iter;
972  dsm_segment *seg;
973 
975  {
976  seg = dlist_container(dsm_segment, node, iter.cur);
977  if (seg->handle == h)
978  return seg;
979  }
980 
981  return NULL;
982 }
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
static dlist_head dsm_segment_list
Definition: dsm.c:124
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
dsm_handle handle
Definition: dsm.c:71
dlist_node * cur
Definition: ilist.h:161
#define NULL
Definition: c.h:229
void dsm_pin_mapping ( dsm_segment seg)

Definition at line 815 of file dsm.c.

References NULL, ResourceOwnerForgetDSM(), and dsm_segment::resowner.

Referenced by dsa_pin_mapping(), get_segment_by_index(), and make_new_segment().

816 {
817  if (seg->resowner != NULL)
818  {
819  ResourceOwnerForgetDSM(seg->resowner, seg);
820  seg->resowner = NULL;
821  }
822 }
ResourceOwner resowner
Definition: dsm.c:70
#define NULL
Definition: c.h:229
void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1254
void dsm_pin_segment ( dsm_segment seg)

Definition at line 855 of file dsm.c.

References dsm_segment::control_slot, dsm_impl_pin_segment(), elog, ERROR, dsm_segment::handle, dsm_segment::impl_private, dsm_control_item::impl_private_pm_handle, dsm_control_header::item, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), dsm_control_item::pinned, and dsm_control_item::refcnt.

Referenced by dsa_create(), and make_new_segment().

856 {
857  void *handle;
858 
859  /*
860  * Bump reference count for this segment in shared memory. This will
861  * ensure that even if there is no session which is attached to this
862  * segment, it will remain until postmaster shutdown or an explicit call
863  * to unpin.
864  */
865  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
866  if (dsm_control->item[seg->control_slot].pinned)
867  elog(ERROR, "cannot pin a segment that is already pinned");
868  dsm_impl_pin_segment(seg->handle, seg->impl_private, &handle);
869  dsm_control->item[seg->control_slot].pinned = true;
872  LWLockRelease(DynamicSharedMemoryControlLock);
873 }
bool pinned
Definition: dsm.c:85
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ERROR
Definition: elog.h:43
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
dsm_handle handle
Definition: dsm.c:71
static dsm_control_header * dsm_control
Definition: dsm.c:134
void * impl_private
Definition: dsm.c:73
uint32 control_slot
Definition: dsm.c:72
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
uint32 refcnt
Definition: dsm.c:83
void dsm_impl_pin_segment(dsm_handle handle, void *impl_private, void **impl_private_pm_handle)
Definition: dsm_impl.c:1009
void * impl_private_pm_handle
Definition: dsm.c:84
#define elog
Definition: elog.h:219
static void dsm_postmaster_shutdown ( int  code,
Datum  arg 
)
static

Definition at line 343 of file dsm.c.

References DatumGetPointer, DEBUG2, PGShmemHeader::dsm_control, dsm_control, dsm_control_handle, dsm_control_impl_private, dsm_control_mapped_size, dsm_control_segment_sane(), dsm_impl_op(), DSM_OP_DESTROY, elog, ereport, errmsg(), dsm_control_item::handle, i, dsm_control_header::item, LOG, dsm_control_header::nitems, NULL, and dsm_control_item::refcnt.

Referenced by dsm_postmaster_startup().

344 {
345  uint32 nitems;
346  uint32 i;
347  void *dsm_control_address;
348  void *junk_mapped_address = NULL;
349  void *junk_impl_private = NULL;
350  Size junk_mapped_size = 0;
352 
353  /*
354  * If some other backend exited uncleanly, it might have corrupted the
355  * control segment while it was dying. In that case, we warn and ignore
356  * the contents of the control segment. This may end up leaving behind
357  * stray shared memory segments, but there's not much we can do about that
358  * if the metadata is gone.
359  */
360  nitems = dsm_control->nitems;
362  {
363  ereport(LOG,
364  (errmsg("dynamic shared memory control segment is corrupt")));
365  return;
366  }
367 
368  /* Remove any remaining segments. */
369  for (i = 0; i < nitems; ++i)
370  {
371  dsm_handle handle;
372 
373  /* If the reference count is 0, the slot is actually unused. */
374  if (dsm_control->item[i].refcnt == 0)
375  continue;
376 
377  /* Log debugging information. */
378  handle = dsm_control->item[i].handle;
379  elog(DEBUG2, "cleaning up orphaned dynamic shared memory with ID %u",
380  handle);
381 
382  /* Destroy the segment. */
383  dsm_impl_op(DSM_OP_DESTROY, handle, 0, &junk_impl_private,
384  &junk_mapped_address, &junk_mapped_size, LOG);
385  }
386 
387  /* Remove the control segment itself. */
388  elog(DEBUG2,
389  "cleaning up dynamic shared memory control segment with ID %u",
391  dsm_control_address = dsm_control;
393  &dsm_control_impl_private, &dsm_control_address,
395  dsm_control = dsm_control_address;
396  shim->dsm_control = 0;
397 }
static void * dsm_control_impl_private
Definition: dsm.c:136
uint32 dsm_handle
Definition: dsm_impl.h:55
dsm_handle dsm_control
Definition: pg_shmem.h:36
dsm_handle handle
Definition: dsm.c:82
static dsm_handle dsm_control_handle
Definition: dsm.c:133
#define LOG
Definition: elog.h:26
uint32 nitems
Definition: dsm.c:92
#define DEBUG2
Definition: elog.h:24
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
unsigned int uint32
Definition: c.h:268
#define ereport(elevel, rest)
Definition: elog.h:122
static bool dsm_control_segment_sane(dsm_control_header *control, Size mapped_size)
Definition: dsm.c:1128
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define NULL
Definition: c.h:229
size_t Size
Definition: c.h:356
#define DatumGetPointer(X)
Definition: postgres.h:555
uint32 refcnt
Definition: dsm.c:83
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Size dsm_control_mapped_size
Definition: dsm.c:135
int i
void * arg
#define elog
Definition: elog.h:219
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
void dsm_postmaster_startup ( PGShmemHeader shim)

Definition at line 145 of file dsm.c.

References Assert, DEBUG2, dsm_cleanup_for_mmap(), PGShmemHeader::dsm_control, dsm_control_bytes_needed(), dsm_control_handle, dsm_control_impl_private, dsm_control_mapped_size, DSM_HANDLE_INVALID, DSM_IMPL_MMAP, DSM_IMPL_NONE, dsm_impl_op(), DSM_OP_CREATE, dsm_postmaster_shutdown(), dynamic_shared_memory_type, elog, ERROR, IsUnderPostmaster, dsm_control_header::magic, MaxBackends, dsm_control_header::maxitems, dsm_control_header::nitems, NULL, on_shmem_exit(), PG_DYNSHMEM_CONTROL_MAGIC, PG_DYNSHMEM_FIXED_SLOTS, PG_DYNSHMEM_SLOTS_PER_BACKEND, PointerGetDatum, and random().

Referenced by CreateSharedMemoryAndSemaphores().

146 {
147  void *dsm_control_address = NULL;
148  uint32 maxitems;
149  Size segsize;
150 
152 
153  /* If dynamic shared memory is disabled, there's nothing to do. */
155  return;
156 
157  /*
158  * If we're using the mmap implementations, clean up any leftovers.
159  * Cleanup isn't needed on Windows, and happens earlier in startup for
160  * POSIX and System V shared memory, via a direct call to
161  * dsm_cleanup_using_control_segment.
162  */
165 
166  /* Determine size for new control segment. */
167  maxitems = PG_DYNSHMEM_FIXED_SLOTS
169  elog(DEBUG2, "dynamic shared memory system will support %u segments",
170  maxitems);
171  segsize = dsm_control_bytes_needed(maxitems);
172 
173  /*
174  * Loop until we find an unused identifier for the new control segment. We
175  * sometimes use 0 as a sentinel value indicating that no control segment
176  * is known to exist, so avoid using that value for a real control
177  * segment.
178  */
179  for (;;)
180  {
181  Assert(dsm_control_address == NULL);
185  continue;
187  &dsm_control_impl_private, &dsm_control_address,
189  break;
190  }
191  dsm_control = dsm_control_address;
193  elog(DEBUG2,
194  "created dynamic shared memory control segment %u (%zu bytes)",
195  dsm_control_handle, segsize);
197 
198  /* Initialize control segment. */
200  dsm_control->nitems = 0;
201  dsm_control->maxitems = maxitems;
202 }
static void * dsm_control_impl_private
Definition: dsm.c:136
#define DSM_IMPL_MMAP
Definition: dsm_impl.h:21
uint32 maxitems
Definition: dsm.c:93
#define PG_DYNSHMEM_SLOTS_PER_BACKEND
Definition: dsm.c:54
#define PG_DYNSHMEM_FIXED_SLOTS
Definition: dsm.c:53
dsm_handle dsm_control
Definition: pg_shmem.h:36
#define PointerGetDatum(X)
Definition: postgres.h:562
long random(void)
Definition: random.c:22
static dsm_handle dsm_control_handle
Definition: dsm.c:133
static uint64 dsm_control_bytes_needed(uint32 nitems)
Definition: dsm.c:1146
uint32 nitems
Definition: dsm.c:92
#define DSM_HANDLE_INVALID
Definition: dsm.h:23
#define ERROR
Definition: elog.h:43
uint32 magic
Definition: dsm.c:91
int MaxBackends
Definition: globals.c:126
#define DEBUG2
Definition: elog.h:24
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:348
bool IsUnderPostmaster
Definition: globals.c:100
static void dsm_postmaster_shutdown(int code, Datum arg)
Definition: dsm.c:343
int dynamic_shared_memory_type
Definition: dsm_impl.c:112
unsigned int uint32
Definition: c.h:268
static void dsm_cleanup_for_mmap(void)
Definition: dsm.c:292
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define DSM_IMPL_NONE
Definition: dsm_impl.h:17
size_t Size
Definition: c.h:356
static Size dsm_control_mapped_size
Definition: dsm.c:135
#define elog
Definition: elog.h:219
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
#define PG_DYNSHMEM_CONTROL_MAGIC
Definition: dsm.c:46
void* dsm_remap ( dsm_segment seg)

Definition at line 696 of file dsm.c.

References dsm_impl_op(), DSM_OP_ATTACH, ERROR, dsm_segment::handle, dsm_segment::impl_private, dsm_segment::mapped_address, and dsm_segment::mapped_size.

697 {
699  &seg->mapped_address, &seg->mapped_size, ERROR);
700 
701  return seg->mapped_address;
702 }
Size mapped_size
Definition: dsm.c:75
#define ERROR
Definition: elog.h:43
void * mapped_address
Definition: dsm.c:74
dsm_handle handle
Definition: dsm.c:71
void * impl_private
Definition: dsm.c:73
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
void* dsm_resize ( dsm_segment seg,
Size  size 
)

Definition at line 679 of file dsm.c.

References Assert, dsm_segment::control_slot, dsm_impl_op(), DSM_OP_RESIZE, ERROR, dsm_segment::handle, dsm_segment::impl_private, INVALID_CONTROL_SLOT, dsm_segment::mapped_address, and dsm_segment::mapped_size.

680 {
682  dsm_impl_op(DSM_OP_RESIZE, seg->handle, size, &seg->impl_private,
683  &seg->mapped_address, &seg->mapped_size, ERROR);
684  return seg->mapped_address;
685 }
Size mapped_size
Definition: dsm.c:75
#define ERROR
Definition: elog.h:43
void * mapped_address
Definition: dsm.c:74
dsm_handle handle
Definition: dsm.c:71
#define Assert(condition)
Definition: c.h:675
void * impl_private
Definition: dsm.c:73
uint32 control_slot
Definition: dsm.c:72
#define INVALID_CONTROL_SLOT
Definition: dsm.c:56
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
void* dsm_segment_address ( dsm_segment seg)

Definition at line 988 of file dsm.c.

References Assert, dsm_segment::mapped_address, and NULL.

Referenced by dsa_attach(), dsa_create(), get_segment_by_index(), InitializeParallelDSM(), make_new_segment(), ParallelWorkerMain(), setup_dynamic_shared_memory(), and test_shm_mq_main().

989 {
990  Assert(seg->mapped_address != NULL);
991  return seg->mapped_address;
992 }
void * mapped_address
Definition: dsm.c:74
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
dsm_handle dsm_segment_handle ( dsm_segment seg)

Definition at line 1016 of file dsm.c.

References dsm_segment::handle.

Referenced by destroy_superblock(), dsa_create(), LaunchParallelWorkers(), make_new_segment(), PrintDSMLeakWarning(), ResourceOwnerForgetDSM(), and setup_background_workers().

1017 {
1018  return seg->handle;
1019 }
dsm_handle handle
Definition: dsm.c:71
Size dsm_segment_map_length ( dsm_segment seg)

Definition at line 998 of file dsm.c.

References Assert, dsm_segment::mapped_address, dsm_segment::mapped_size, and NULL.

999 {
1000  Assert(seg->mapped_address != NULL);
1001  return seg->mapped_size;
1002 }
Size mapped_size
Definition: dsm.c:75
void * mapped_address
Definition: dsm.c:74
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void dsm_unpin_mapping ( dsm_segment seg)

Definition at line 834 of file dsm.c.

References Assert, CurrentResourceOwner, NULL, ResourceOwnerEnlargeDSMs(), ResourceOwnerRememberDSM(), and dsm_segment::resowner.

835 {
836  Assert(seg->resowner == NULL);
840 }
void ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1245
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ResourceOwnerEnlargeDSMs(ResourceOwner owner)
Definition: resowner.c:1234
ResourceOwner resowner
Definition: dsm.c:70
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void dsm_unpin_segment ( dsm_handle  handle)

Definition at line 887 of file dsm.c.

References Assert, dsm_impl_op(), dsm_impl_unpin_segment(), DSM_OP_DESTROY, elog, ERROR, dsm_control_item::handle, i, dsm_control_item::impl_private_pm_handle, INVALID_CONTROL_SLOT, dsm_control_header::item, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), dsm_control_header::nitems, NULL, dsm_control_item::pinned, dsm_control_item::refcnt, and WARNING.

Referenced by destroy_superblock(), and dsa_release_in_place().

888 {
889  uint32 control_slot = INVALID_CONTROL_SLOT;
890  bool destroy = false;
891  uint32 i;
892 
893  /* Find the control slot for the given handle. */
894  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
895  for (i = 0; i < dsm_control->nitems; ++i)
896  {
897  /* Skip unused slots. */
898  if (dsm_control->item[i].refcnt == 0)
899  continue;
900 
901  /* If we've found our handle, we can stop searching. */
902  if (dsm_control->item[i].handle == handle)
903  {
904  control_slot = i;
905  break;
906  }
907  }
908 
909  /*
910  * We should definitely have found the slot, and it should not already be
911  * in the process of going away, because this function should only be
912  * called on a segment which is pinned.
913  */
914  if (control_slot == INVALID_CONTROL_SLOT)
915  elog(ERROR, "cannot unpin unknown segment handle");
916  if (!dsm_control->item[control_slot].pinned)
917  elog(ERROR, "cannot unpin a segment that is not pinned");
918  Assert(dsm_control->item[control_slot].refcnt > 1);
919 
920  /*
921  * Allow implementation-specific code to run. We have to do this before
922  * releasing the lock, because impl_private_pm_handle may get modified by
923  * dsm_impl_unpin_segment.
924  */
925  dsm_impl_unpin_segment(handle,
926  &dsm_control->item[control_slot].impl_private_pm_handle);
927 
928  /* Note that 1 means no references (0 means unused slot). */
929  if (--dsm_control->item[control_slot].refcnt == 1)
930  destroy = true;
931  dsm_control->item[control_slot].pinned = false;
932 
933  /* Now we can release the lock. */
934  LWLockRelease(DynamicSharedMemoryControlLock);
935 
936  /* Clean up resources if that was the last reference. */
937  if (destroy)
938  {
939  void *junk_impl_private = NULL;
940  void *junk_mapped_address = NULL;
941  Size junk_mapped_size = 0;
942 
943  /*
944  * For an explanation of how error handling works in this case, see
945  * comments in dsm_detach. Note that if we reach this point, the
946  * current process certainly does not have the segment mapped, because
947  * if it did, the reference count would have still been greater than 1
948  * even after releasing the reference count held by the pin. The fact
949  * that there can't be a dsm_segment for this handle makes it OK to
950  * pass the mapped size, mapped address, and private data as NULL
951  * here.
952  */
953  if (dsm_impl_op(DSM_OP_DESTROY, handle, 0, &junk_impl_private,
954  &junk_mapped_address, &junk_mapped_size, WARNING))
955  {
956  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
957  Assert(dsm_control->item[control_slot].handle == handle);
958  Assert(dsm_control->item[control_slot].refcnt == 1);
959  dsm_control->item[control_slot].refcnt = 0;
960  LWLockRelease(DynamicSharedMemoryControlLock);
961  }
962  }
963 }
void dsm_impl_unpin_segment(dsm_handle handle, void **impl_private)
Definition: dsm_impl.c:1059
dsm_handle handle
Definition: dsm.c:82
uint32 nitems
Definition: dsm.c:92
bool pinned
Definition: dsm.c:85
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ERROR
Definition: elog.h:43
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
unsigned int uint32
Definition: c.h:268
#define WARNING
Definition: elog.h:40
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
size_t Size
Definition: c.h:356
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
uint32 refcnt
Definition: dsm.c:83
int i
void * impl_private_pm_handle
Definition: dsm.c:84
#define INVALID_CONTROL_SLOT
Definition: dsm.c:56
#define elog
Definition: elog.h:219
bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, void **impl_private, void **mapped_address, Size *mapped_size, int elevel)
Definition: dsm_impl.c:162
void on_dsm_detach ( dsm_segment seg,
on_dsm_detach_callback  function,
Datum  arg 
)

Definition at line 1025 of file dsm.c.

References arg, dsm_segment_detach_callback::arg, dsm_segment_detach_callback::function, MemoryContextAlloc(), dsm_segment_detach_callback::node, dsm_segment::on_detach, slist_push_head(), and TopMemoryContext.

Referenced by dsa_attach(), dsa_attach_in_place(), dsa_create(), dsa_create_in_place(), pq_redirect_to_shm_mq(), setup_background_workers(), and shm_mq_attach().

1026 {
1028 
1030  sizeof(dsm_segment_detach_callback));
1031  cb->function = function;
1032  cb->arg = arg;
1033  slist_push_head(&seg->on_detach, &cb->node);
1034 }
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:574
on_dsm_detach_callback function
Definition: dsm.c:61
MemoryContext TopMemoryContext
Definition: mcxt.c:43
slist_head on_detach
Definition: dsm.c:76
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
void * arg
void reset_on_dsm_detach ( void  )

Definition at line 1063 of file dsm.c.

References dsm_segment::control_slot, dlist_iter::cur, dlist_container, dlist_foreach, INVALID_CONTROL_SLOT, dsm_segment::on_detach, pfree(), slist_container, slist_is_empty(), and slist_pop_head_node().

Referenced by on_exit_reset().

1064 {
1065  dlist_iter iter;
1066 
1068  {
1069  dsm_segment *seg = dlist_container(dsm_segment, node, iter.cur);
1070 
1071  /* Throw away explicit on-detach actions one by one. */
1072  while (!slist_is_empty(&seg->on_detach))
1073  {
1074  slist_node *node;
1076 
1077  node = slist_pop_head_node(&seg->on_detach);
1078  cb = slist_container(dsm_segment_detach_callback, node, node);
1079  pfree(cb);
1080  }
1081 
1082  /*
1083  * Decrementing the reference count is a sort of implicit on-detach
1084  * action; make sure we don't do that, either.
1085  */
1087  }
1088 }
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
static dlist_head dsm_segment_list
Definition: dsm.c:124
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
void pfree(void *pointer)
Definition: mcxt.c:950
static slist_node * slist_pop_head_node(slist_head *head)
Definition: ilist.h:596
slist_head on_detach
Definition: dsm.c:76
static bool slist_is_empty(slist_head *head)
Definition: ilist.h:563
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
dlist_node * cur
Definition: ilist.h:161
uint32 control_slot
Definition: dsm.c:72
#define INVALID_CONTROL_SLOT
Definition: dsm.c:56

Variable Documentation

dsm_control_header* dsm_control
static

Definition at line 134 of file dsm.c.

Referenced by dsm_detach_all(), and dsm_postmaster_shutdown().

dsm_handle dsm_control_handle
static
void* dsm_control_impl_private = NULL
static
Size dsm_control_mapped_size = 0
static
bool dsm_init_done = false
static

Definition at line 105 of file dsm.c.

Referenced by dsm_attach(), dsm_backend_startup(), and dsm_create().

dlist_head dsm_segment_list = DLIST_STATIC_INIT(dsm_segment_list)
static

Definition at line 124 of file dsm.c.