PostgreSQL Source Code  git master
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_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

◆ INVALID_CONTROL_SLOT

#define INVALID_CONTROL_SLOT   ((uint32) -1)

◆ PG_DYNSHMEM_CONTROL_MAGIC

#define PG_DYNSHMEM_CONTROL_MAGIC   0x9a503d32

Definition at line 46 of file dsm.c.

Referenced by dsm_control_segment_sane(), and dsm_postmaster_startup().

◆ PG_DYNSHMEM_FIXED_SLOTS

#define PG_DYNSHMEM_FIXED_SLOTS   64

Definition at line 53 of file dsm.c.

Referenced by dsm_postmaster_startup().

◆ PG_DYNSHMEM_SLOTS_PER_BACKEND

#define PG_DYNSHMEM_SLOTS_PER_BACKEND   2

Definition at line 54 of file dsm.c.

Referenced by dsm_postmaster_startup().

Typedef Documentation

◆ dsm_control_header

◆ dsm_control_item

◆ dsm_segment_detach_callback

Function Documentation

◆ cancel_on_dsm_detach()

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

Definition at line 990 of file dsm.c.

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

Referenced by shm_mq_detach(), and test_shm_mq_setup().

992 {
993  slist_mutable_iter iter;
994 
995  slist_foreach_modify(iter, &seg->on_detach)
996  {
998 
1000  if (cb->function == function && cb->arg == arg)
1001  {
1002  slist_delete_current(&iter);
1003  pfree(cb);
1004  break;
1005  }
1006  }
1007 }
slist_node * cur
Definition: ilist.h:241
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:716
void pfree(void *pointer)
Definition: mcxt.c:1056
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_attach()

dsm_segment* dsm_attach ( dsm_handle  h)

Definition at line 533 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, dsm_segment_detach_callback::node, and dsm_control_item::refcnt.

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

534 {
535  dsm_segment *seg;
536  dlist_iter iter;
537  uint32 i;
538  uint32 nitems;
539 
540  /* Unsafe in postmaster (and pointless in a stand-alone backend). */
542 
543  if (!dsm_init_done)
545 
546  /*
547  * Since this is just a debugging cross-check, we could leave it out
548  * altogether, or include it only in assert-enabled builds. But since the
549  * list of attached segments should normally be very short, let's include
550  * it always for right now.
551  *
552  * If you're hitting this error, you probably want to attempt to find an
553  * existing mapping via dsm_find_mapping() before calling dsm_attach() to
554  * create a new one.
555  */
557  {
558  seg = dlist_container(dsm_segment, node, iter.cur);
559  if (seg->handle == h)
560  elog(ERROR, "can't attach the same segment more than once");
561  }
562 
563  /* Create a new segment descriptor. */
564  seg = dsm_create_descriptor();
565  seg->handle = h;
566 
567  /* Bump reference count for this segment in shared memory. */
568  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
569  nitems = dsm_control->nitems;
570  for (i = 0; i < nitems; ++i)
571  {
572  /*
573  * If the reference count is 0, the slot is actually unused. If the
574  * reference count is 1, the slot is still in use, but the segment is
575  * in the process of going away; even if the handle matches, another
576  * slot may already have started using the same handle value by
577  * coincidence so we have to keep searching.
578  */
579  if (dsm_control->item[i].refcnt <= 1)
580  continue;
581 
582  /* If the handle doesn't match, it's not the slot we want. */
583  if (dsm_control->item[i].handle != seg->handle)
584  continue;
585 
586  /* Otherwise we've found a match. */
587  dsm_control->item[i].refcnt++;
588  seg->control_slot = i;
589  break;
590  }
591  LWLockRelease(DynamicSharedMemoryControlLock);
592 
593  /*
594  * If we didn't find the handle we're looking for in the control segment,
595  * it probably means that everyone else who had it mapped, including the
596  * original creator, died before we got to this point. It's up to the
597  * caller to decide what to do about that.
598  */
600  {
601  dsm_detach(seg);
602  return NULL;
603  }
604 
605  /* Here's where we actually try to map the segment. */
607  &seg->mapped_address, &seg->mapped_size, ERROR);
608 
609  return seg;
610 }
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:384
static dlist_head dsm_segment_list
Definition: dsm.c:124
uint32 nitems
Definition: dsm.c:92
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define ERROR
Definition: elog.h:43
bool IsUnderPostmaster
Definition: globals.c:109
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
unsigned int uint32
Definition: c.h:359
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 Assert(condition)
Definition: c.h:739
void * impl_private
Definition: dsm.c:73
uint32 control_slot
Definition: dsm.c:72
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static dsm_segment * dsm_create_descriptor(void)
Definition: dsm.c:1044
uint32 refcnt
Definition: dsm.c:83
static bool dsm_init_done
Definition: dsm.c:105
void dsm_detach(dsm_segment *seg)
Definition: dsm.c:664
#define elog(elevel,...)
Definition: elog.h:228
int i
#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:158

◆ dsm_backend_shutdown()

void dsm_backend_shutdown ( void  )

Definition at line 618 of file dsm.c.

References dlist_head_element, dlist_is_empty(), dsm_detach(), and dsm_segment_detach_callback::node.

Referenced by shmem_exit().

619 {
621  {
622  dsm_segment *seg;
623 
625  dsm_detach(seg);
626  }
627 }
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:664

◆ dsm_backend_startup()

static void dsm_backend_startup ( void  )
static

Definition at line 384 of file dsm.c.

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

Referenced by dsm_attach(), and dsm_create().

385 {
386 #ifdef EXEC_BACKEND
387  {
388  void *control_address = NULL;
389 
390  /* Attach control segment. */
393  &dsm_control_impl_private, &control_address,
395  dsm_control = control_address;
396  /* If control segment doesn't look sane, something is badly wrong. */
398  {
400  &dsm_control_impl_private, &control_address,
402  ereport(FATAL,
403  (errcode(ERRCODE_INTERNAL_ERROR),
404  errmsg("dynamic shared memory control segment is not valid")));
405  }
406  }
407 #endif
408 
409  dsm_init_done = true;
410 }
static void * dsm_control_impl_private
Definition: dsm.c:136
static dsm_handle dsm_control_handle
Definition: dsm.c:133
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
#define ereport(elevel, rest)
Definition: elog.h:141
static bool dsm_control_segment_sane(dsm_control_header *control, Size mapped_size)
Definition: dsm.c:1080
#define WARNING
Definition: elog.h:40
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define Assert(condition)
Definition: c.h:739
static bool dsm_init_done
Definition: dsm.c:105
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:158

◆ dsm_cleanup_for_mmap()

static void dsm_cleanup_for_mmap ( void  )
static

Definition at line 284 of file dsm.c.

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

Referenced by dsm_postmaster_startup().

285 {
286  DIR *dir;
287  struct dirent *dent;
288 
289  /* Scan the directory for something with a name of the correct format. */
291 
292  while ((dent = ReadDir(dir, PG_DYNSHMEM_DIR)) != NULL)
293  {
294  if (strncmp(dent->d_name, PG_DYNSHMEM_MMAP_FILE_PREFIX,
295  strlen(PG_DYNSHMEM_MMAP_FILE_PREFIX)) == 0)
296  {
297  char buf[MAXPGPATH + sizeof(PG_DYNSHMEM_DIR)];
298 
299  snprintf(buf, sizeof(buf), PG_DYNSHMEM_DIR "/%s", dent->d_name);
300 
301  elog(DEBUG2, "removing file \"%s\"", buf);
302 
303  /* We found a matching file; so remove it. */
304  if (unlink(buf) != 0)
305  ereport(ERROR,
307  errmsg("could not remove file \"%s\": %m", buf)));
308  }
309  }
310 
311  /* Cleanup complete. */
312  FreeDir(dir);
313 }
#define PG_DYNSHMEM_DIR
Definition: dsm_impl.h:50
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:67
int errcode_for_file_access(void)
Definition: elog.c:631
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2503
#define ereport(elevel, rest)
Definition: elog.h:141
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2569
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
#define PG_DYNSHMEM_MMAP_FILE_PREFIX
Definition: dsm_impl.h:51
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2621

◆ dsm_cleanup_using_control_segment()

void dsm_cleanup_using_control_segment ( dsm_handle  old_control_handle)

Definition at line 206 of file dsm.c.

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

Referenced by PGSharedMemoryCreate().

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

◆ dsm_control_bytes_needed()

static uint64 dsm_control_bytes_needed ( uint32  nitems)
static

Definition at line 1098 of file dsm.c.

References offsetof.

Referenced by dsm_control_segment_sane(), and dsm_postmaster_startup().

1099 {
1100  return offsetof(dsm_control_header, item)
1101  + sizeof(dsm_control_item) * (uint64) nitems;
1102 }
struct dsm_control_item dsm_control_item
#define offsetof(type, field)
Definition: c.h:662

◆ dsm_control_segment_sane()

static bool dsm_control_segment_sane ( dsm_control_header control,
Size  mapped_size 
)
static

Definition at line 1080 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().

1081 {
1082  if (mapped_size < offsetof(dsm_control_header, item))
1083  return false; /* Mapped size too short to read header. */
1084  if (control->magic != PG_DYNSHMEM_CONTROL_MAGIC)
1085  return false; /* Magic number doesn't match. */
1086  if (dsm_control_bytes_needed(control->maxitems) > mapped_size)
1087  return false; /* Max item count won't fit in map. */
1088  if (control->nitems > control->maxitems)
1089  return false; /* Overfull. */
1090  return true;
1091 }
uint32 maxitems
Definition: dsm.c:93
static uint64 dsm_control_bytes_needed(uint32 nitems)
Definition: dsm.c:1098
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:662

◆ dsm_create()

dsm_segment* dsm_create ( Size  size,
int  flags 
)

Definition at line 437 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, pfree(), dsm_control_item::pinned, random(), dsm_control_item::refcnt, ResourceOwnerForgetDSM(), dsm_segment::resowner, and WARNING.

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

438 {
439  dsm_segment *seg;
440  uint32 i;
441  uint32 nitems;
442 
443  /* Unsafe in postmaster (and pointless in a stand-alone backend). */
445 
446  if (!dsm_init_done)
448 
449  /* Create a new segment descriptor. */
450  seg = dsm_create_descriptor();
451 
452  /* Loop until we find an unused segment identifier. */
453  for (;;)
454  {
455  Assert(seg->mapped_address == NULL && seg->mapped_size == 0);
456  seg->handle = random();
457  if (seg->handle == DSM_HANDLE_INVALID) /* Reserve sentinel */
458  continue;
459  if (dsm_impl_op(DSM_OP_CREATE, seg->handle, size, &seg->impl_private,
460  &seg->mapped_address, &seg->mapped_size, ERROR))
461  break;
462  }
463 
464  /* Lock the control segment so we can register the new segment. */
465  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
466 
467  /* Search the control segment for an unused slot. */
468  nitems = dsm_control->nitems;
469  for (i = 0; i < nitems; ++i)
470  {
471  if (dsm_control->item[i].refcnt == 0)
472  {
473  dsm_control->item[i].handle = seg->handle;
474  /* refcnt of 1 triggers destruction, so start at 2 */
475  dsm_control->item[i].refcnt = 2;
477  dsm_control->item[i].pinned = false;
478  seg->control_slot = i;
479  LWLockRelease(DynamicSharedMemoryControlLock);
480  return seg;
481  }
482  }
483 
484  /* Verify that we can support an additional mapping. */
485  if (nitems >= dsm_control->maxitems)
486  {
487  if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0)
488  {
489  LWLockRelease(DynamicSharedMemoryControlLock);
491  &seg->mapped_address, &seg->mapped_size, WARNING);
492  if (seg->resowner != NULL)
493  ResourceOwnerForgetDSM(seg->resowner, seg);
494  dlist_delete(&seg->node);
495  pfree(seg);
496  return NULL;
497  }
498  ereport(ERROR,
499  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
500  errmsg("too many dynamic shared memory segments")));
501  }
502 
503  /* Enter the handle into a new array slot. */
504  dsm_control->item[nitems].handle = seg->handle;
505  /* refcnt of 1 triggers destruction, so start at 2 */
506  dsm_control->item[nitems].refcnt = 2;
507  dsm_control->item[nitems].impl_private_pm_handle = NULL;
508  dsm_control->item[nitems].pinned = false;
509  seg->control_slot = nitems;
510  dsm_control->nitems++;
511  LWLockRelease(DynamicSharedMemoryControlLock);
512 
513  return seg;
514 }
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:608
static void dsm_backend_startup(void)
Definition: dsm.c:384
uint32 nitems
Definition: dsm.c:92
bool pinned
Definition: dsm.c:85
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define DSM_HANDLE_INVALID
Definition: dsm.h:23
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define DSM_CREATE_NULL_IF_MAXSEGMENTS
Definition: dsm.h:20
bool IsUnderPostmaster
Definition: globals.c:109
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
unsigned int uint32
Definition: c.h:359
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:141
#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 Assert(condition)
Definition: c.h:739
void * impl_private
Definition: dsm.c:73
void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1298
uint32 control_slot
Definition: dsm.c:72
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static dsm_segment * dsm_create_descriptor(void)
Definition: dsm.c:1044
uint32 refcnt
Definition: dsm.c:83
static bool dsm_init_done
Definition: dsm.c:105
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:158

◆ dsm_create_descriptor()

static dsm_segment * dsm_create_descriptor ( void  )
static

Definition at line 1044 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, dsm_segment::on_detach, ResourceOwnerEnlargeDSMs(), ResourceOwnerRememberDSM(), dsm_segment::resowner, slist_init(), and TopMemoryContext.

Referenced by dsm_attach(), and dsm_create().

1045 {
1046  dsm_segment *seg;
1047 
1050 
1053 
1054  /* seg->handle must be initialized by the caller */
1056  seg->impl_private = NULL;
1057  seg->mapped_address = NULL;
1058  seg->mapped_size = 0;
1059 
1063 
1064  slist_init(&seg->on_detach);
1065 
1066  return seg;
1067 }
dlist_node node
Definition: dsm.c:69
void ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1289
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:142
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:1278
void * mapped_address
Definition: dsm.c:74
MemoryContext TopMemoryContext
Definition: mcxt.c:44
slist_head on_detach
Definition: dsm.c:76
ResourceOwner resowner
Definition: dsm.c:70
void * impl_private
Definition: dsm.c:73
uint32 control_slot
Definition: dsm.c:72
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define INVALID_CONTROL_SLOT
Definition: dsm.c:56

◆ dsm_detach()

void dsm_detach ( dsm_segment seg)

Definition at line 664 of file dsm.c.

References 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_detach_callback::node, dsm_segment::node, 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 apw_load_buffers(), autoprewarm_database_main(), check_for_freed_segments_locked(), destroy_superblock(), DestroyParallelContext(), DetachSession(), dsa_detach(), dsm_attach(), dsm_backend_shutdown(), dsm_detach_all(), ResourceOwnerReleaseInternal(), test_shm_mq(), test_shm_mq_main(), and test_shm_mq_pipelined().

665 {
666  /*
667  * Invoke registered callbacks. Just in case one of those callbacks
668  * throws a further error that brings us back here, pop the callback
669  * before invoking it, to avoid infinite error recursion.
670  */
671  while (!slist_is_empty(&seg->on_detach))
672  {
673  slist_node *node;
675  on_dsm_detach_callback function;
676  Datum arg;
677 
678  node = slist_pop_head_node(&seg->on_detach);
680  function = cb->function;
681  arg = cb->arg;
682  pfree(cb);
683 
684  function(seg, arg);
685  }
686 
687  /*
688  * Try to remove the mapping, if one exists. Normally, there will be, but
689  * maybe not, if we failed partway through a create or attach operation.
690  * We remove the mapping before decrementing the reference count so that
691  * the process that sees a zero reference count can be certain that no
692  * remaining mappings exist. Even if this fails, we pretend that it
693  * works, because retrying is likely to fail in the same way.
694  */
695  if (seg->mapped_address != NULL)
696  {
698  &seg->mapped_address, &seg->mapped_size, WARNING);
699  seg->impl_private = NULL;
700  seg->mapped_address = NULL;
701  seg->mapped_size = 0;
702  }
703 
704  /* Reduce reference count, if we previously increased it. */
706  {
707  uint32 refcnt;
708  uint32 control_slot = seg->control_slot;
709 
710  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
711  Assert(dsm_control->item[control_slot].handle == seg->handle);
712  Assert(dsm_control->item[control_slot].refcnt > 1);
713  refcnt = --dsm_control->item[control_slot].refcnt;
715  LWLockRelease(DynamicSharedMemoryControlLock);
716 
717  /* If new reference count is 1, try to destroy the segment. */
718  if (refcnt == 1)
719  {
720  /* A pinned segment should never reach 1. */
721  Assert(!dsm_control->item[control_slot].pinned);
722 
723  /*
724  * If we fail to destroy the segment here, or are killed before we
725  * finish doing so, the reference count will remain at 1, which
726  * will mean that nobody else can attach to the segment. At
727  * postmaster shutdown time, or when a new postmaster is started
728  * after a hard kill, another attempt will be made to remove the
729  * segment.
730  *
731  * The main case we're worried about here is being killed by a
732  * signal before we can finish removing the segment. In that
733  * case, it's important to be sure that the segment still gets
734  * removed. If we actually fail to remove the segment for some
735  * other reason, the postmaster may not have any better luck than
736  * we did. There's not much we can do about that, though.
737  */
738  if (dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
739  &seg->mapped_address, &seg->mapped_size, WARNING))
740  {
741  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
742  Assert(dsm_control->item[control_slot].handle == seg->handle);
743  Assert(dsm_control->item[control_slot].refcnt == 1);
744  dsm_control->item[control_slot].refcnt = 0;
745  LWLockRelease(DynamicSharedMemoryControlLock);
746  }
747  }
748  }
749 
750  /* Clean up our remaining backend-private data structures. */
751  if (seg->resowner != NULL)
752  ResourceOwnerForgetDSM(seg->resowner, seg);
753  dlist_delete(&seg->node);
754  pfree(seg);
755 }
dlist_node node
Definition: dsm.c:69
Size mapped_size
Definition: dsm.c:75
dsm_handle handle
Definition: dsm.c:82
bool pinned
Definition: dsm.c:85
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
void pfree(void *pointer)
Definition: mcxt.c:1056
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:359
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:367
static dsm_control_header * dsm_control
Definition: dsm.c:134
ResourceOwner resowner
Definition: dsm.c:70
#define Assert(condition)
Definition: c.h:739
void * impl_private
Definition: dsm.c:73
void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1298
uint32 control_slot
Definition: dsm.c:72
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
uint32 refcnt
Definition: dsm.c:83
void * arg
#define INVALID_CONTROL_SLOT
Definition: dsm.c:56
void(* on_dsm_detach_callback)(dsm_segment *, Datum arg)
Definition: dsm.h:54
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:158

◆ dsm_detach_all()

void dsm_detach_all ( void  )

Definition at line 636 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 dsm_segment_detach_callback::node.

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

637 {
638  void *control_address = dsm_control;
639 
641  {
642  dsm_segment *seg;
643 
645  dsm_detach(seg);
646  }
647 
648  if (control_address != NULL)
650  &dsm_control_impl_private, &control_address,
652 }
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
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
void dsm_detach(dsm_segment *seg)
Definition: dsm.c:664
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:158

◆ dsm_find_mapping()

dsm_segment* dsm_find_mapping ( dsm_handle  h)

Definition at line 919 of file dsm.c.

References dlist_iter::cur, dlist_container, dlist_foreach, dsm_segment::handle, and dsm_segment_detach_callback::node.

920 {
921  dlist_iter iter;
922  dsm_segment *seg;
923 
925  {
926  seg = dlist_container(dsm_segment, node, iter.cur);
927  if (seg->handle == h)
928  return seg;
929  }
930 
931  return NULL;
932 }
#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

◆ dsm_pin_mapping()

void dsm_pin_mapping ( dsm_segment seg)

Definition at line 765 of file dsm.c.

References ResourceOwnerForgetDSM(), and dsm_segment::resowner.

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

766 {
767  if (seg->resowner != NULL)
768  {
769  ResourceOwnerForgetDSM(seg->resowner, seg);
770  seg->resowner = NULL;
771  }
772 }
ResourceOwner resowner
Definition: dsm.c:70
void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1298

◆ dsm_pin_segment()

void dsm_pin_segment ( dsm_segment seg)

Definition at line 805 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().

806 {
807  void *handle;
808 
809  /*
810  * Bump reference count for this segment in shared memory. This will
811  * ensure that even if there is no session which is attached to this
812  * segment, it will remain until postmaster shutdown or an explicit call
813  * to unpin.
814  */
815  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
816  if (dsm_control->item[seg->control_slot].pinned)
817  elog(ERROR, "cannot pin a segment that is already pinned");
818  dsm_impl_pin_segment(seg->handle, seg->impl_private, &handle);
819  dsm_control->item[seg->control_slot].pinned = true;
822  LWLockRelease(DynamicSharedMemoryControlLock);
823 }
bool pinned
Definition: dsm.c:85
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#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:1122
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:943
#define elog(elevel,...)
Definition: elog.h:228
void * impl_private_pm_handle
Definition: dsm.c:84

◆ dsm_postmaster_shutdown()

static void dsm_postmaster_shutdown ( int  code,
Datum  arg 
)
static

Definition at line 322 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, and dsm_control_item::refcnt.

Referenced by dsm_postmaster_startup().

323 {
324  uint32 nitems;
325  uint32 i;
326  void *dsm_control_address;
327  void *junk_mapped_address = NULL;
328  void *junk_impl_private = NULL;
329  Size junk_mapped_size = 0;
331 
332  /*
333  * If some other backend exited uncleanly, it might have corrupted the
334  * control segment while it was dying. In that case, we warn and ignore
335  * the contents of the control segment. This may end up leaving behind
336  * stray shared memory segments, but there's not much we can do about that
337  * if the metadata is gone.
338  */
339  nitems = dsm_control->nitems;
341  {
342  ereport(LOG,
343  (errmsg("dynamic shared memory control segment is corrupt")));
344  return;
345  }
346 
347  /* Remove any remaining segments. */
348  for (i = 0; i < nitems; ++i)
349  {
350  dsm_handle handle;
351 
352  /* If the reference count is 0, the slot is actually unused. */
353  if (dsm_control->item[i].refcnt == 0)
354  continue;
355 
356  /* Log debugging information. */
357  handle = dsm_control->item[i].handle;
358  elog(DEBUG2, "cleaning up orphaned dynamic shared memory with ID %u",
359  handle);
360 
361  /* Destroy the segment. */
362  dsm_impl_op(DSM_OP_DESTROY, handle, 0, &junk_impl_private,
363  &junk_mapped_address, &junk_mapped_size, LOG);
364  }
365 
366  /* Remove the control segment itself. */
367  elog(DEBUG2,
368  "cleaning up dynamic shared memory control segment with ID %u",
370  dsm_control_address = dsm_control;
372  &dsm_control_impl_private, &dsm_control_address,
374  dsm_control = dsm_control_address;
375  shim->dsm_control = 0;
376 }
static void * dsm_control_impl_private
Definition: dsm.c:136
uint32 dsm_handle
Definition: dsm_impl.h:54
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:359
#define ereport(elevel, rest)
Definition: elog.h:141
static bool dsm_control_segment_sane(dsm_control_header *control, Size mapped_size)
Definition: dsm.c:1080
static dsm_control_header * dsm_control
Definition: dsm.c:134
size_t Size
Definition: c.h:467
#define DatumGetPointer(X)
Definition: postgres.h:549
uint32 refcnt
Definition: dsm.c:83
int errmsg(const char *fmt,...)
Definition: elog.c:822
static Size dsm_control_mapped_size
Definition: dsm.c:135
#define elog(elevel,...)
Definition: elog.h:228
int i
void * arg
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:158

◆ dsm_postmaster_startup()

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_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, 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  /*
154  * If we're using the mmap implementations, clean up any leftovers.
155  * Cleanup isn't needed on Windows, and happens earlier in startup for
156  * POSIX and System V shared memory, via a direct call to
157  * dsm_cleanup_using_control_segment.
158  */
161 
162  /* Determine size for new control segment. */
163  maxitems = PG_DYNSHMEM_FIXED_SLOTS
165  elog(DEBUG2, "dynamic shared memory system will support %u segments",
166  maxitems);
167  segsize = dsm_control_bytes_needed(maxitems);
168 
169  /*
170  * Loop until we find an unused identifier for the new control segment. We
171  * sometimes use 0 as a sentinel value indicating that no control segment
172  * is known to exist, so avoid using that value for a real control
173  * segment.
174  */
175  for (;;)
176  {
177  Assert(dsm_control_address == NULL);
181  continue;
183  &dsm_control_impl_private, &dsm_control_address,
185  break;
186  }
187  dsm_control = dsm_control_address;
189  elog(DEBUG2,
190  "created dynamic shared memory control segment %u (%zu bytes)",
191  dsm_control_handle, segsize);
193 
194  /* Initialize control segment. */
196  dsm_control->nitems = 0;
197  dsm_control->maxitems = maxitems;
198 }
static void * dsm_control_impl_private
Definition: dsm.c:136
#define DSM_IMPL_MMAP
Definition: dsm_impl.h:20
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:556
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:1098
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:135
#define DEBUG2
Definition: elog.h:24
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
bool IsUnderPostmaster
Definition: globals.c:109
static void dsm_postmaster_shutdown(int code, Datum arg)
Definition: dsm.c:322
int dynamic_shared_memory_type
Definition: dsm_impl.c:114
unsigned int uint32
Definition: c.h:359
static void dsm_cleanup_for_mmap(void)
Definition: dsm.c:284
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
static Size dsm_control_mapped_size
Definition: dsm.c:135
#define elog(elevel,...)
Definition: elog.h:228
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:158
#define PG_DYNSHMEM_CONTROL_MAGIC
Definition: dsm.c:46

◆ dsm_segment_address()

void* dsm_segment_address ( dsm_segment seg)

◆ dsm_segment_handle()

◆ dsm_segment_map_length()

Size dsm_segment_map_length ( dsm_segment seg)

Definition at line 948 of file dsm.c.

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

949 {
950  Assert(seg->mapped_address != NULL);
951  return seg->mapped_size;
952 }
Size mapped_size
Definition: dsm.c:75
void * mapped_address
Definition: dsm.c:74
#define Assert(condition)
Definition: c.h:739

◆ dsm_unpin_mapping()

void dsm_unpin_mapping ( dsm_segment seg)

Definition at line 784 of file dsm.c.

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

785 {
786  Assert(seg->resowner == NULL);
790 }
void ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1289
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
void ResourceOwnerEnlargeDSMs(ResourceOwner owner)
Definition: resowner.c:1278
ResourceOwner resowner
Definition: dsm.c:70
#define Assert(condition)
Definition: c.h:739

◆ dsm_unpin_segment()

void dsm_unpin_segment ( dsm_handle  handle)

Definition at line 837 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, dsm_control_item::pinned, dsm_control_item::refcnt, and WARNING.

Referenced by destroy_superblock(), and dsa_release_in_place().

838 {
839  uint32 control_slot = INVALID_CONTROL_SLOT;
840  bool destroy = false;
841  uint32 i;
842 
843  /* Find the control slot for the given handle. */
844  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
845  for (i = 0; i < dsm_control->nitems; ++i)
846  {
847  /* Skip unused slots and segments that are concurrently going away. */
848  if (dsm_control->item[i].refcnt <= 1)
849  continue;
850 
851  /* If we've found our handle, we can stop searching. */
852  if (dsm_control->item[i].handle == handle)
853  {
854  control_slot = i;
855  break;
856  }
857  }
858 
859  /*
860  * We should definitely have found the slot, and it should not already be
861  * in the process of going away, because this function should only be
862  * called on a segment which is pinned.
863  */
864  if (control_slot == INVALID_CONTROL_SLOT)
865  elog(ERROR, "cannot unpin unknown segment handle");
866  if (!dsm_control->item[control_slot].pinned)
867  elog(ERROR, "cannot unpin a segment that is not pinned");
868  Assert(dsm_control->item[control_slot].refcnt > 1);
869 
870  /*
871  * Allow implementation-specific code to run. We have to do this before
872  * releasing the lock, because impl_private_pm_handle may get modified by
873  * dsm_impl_unpin_segment.
874  */
875  dsm_impl_unpin_segment(handle,
876  &dsm_control->item[control_slot].impl_private_pm_handle);
877 
878  /* Note that 1 means no references (0 means unused slot). */
879  if (--dsm_control->item[control_slot].refcnt == 1)
880  destroy = true;
881  dsm_control->item[control_slot].pinned = false;
882 
883  /* Now we can release the lock. */
884  LWLockRelease(DynamicSharedMemoryControlLock);
885 
886  /* Clean up resources if that was the last reference. */
887  if (destroy)
888  {
889  void *junk_impl_private = NULL;
890  void *junk_mapped_address = NULL;
891  Size junk_mapped_size = 0;
892 
893  /*
894  * For an explanation of how error handling works in this case, see
895  * comments in dsm_detach. Note that if we reach this point, the
896  * current process certainly does not have the segment mapped, because
897  * if it did, the reference count would have still been greater than 1
898  * even after releasing the reference count held by the pin. The fact
899  * that there can't be a dsm_segment for this handle makes it OK to
900  * pass the mapped size, mapped address, and private data as NULL
901  * here.
902  */
903  if (dsm_impl_op(DSM_OP_DESTROY, handle, 0, &junk_impl_private,
904  &junk_mapped_address, &junk_mapped_size, WARNING))
905  {
906  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
907  Assert(dsm_control->item[control_slot].handle == handle);
908  Assert(dsm_control->item[control_slot].refcnt == 1);
909  dsm_control->item[control_slot].refcnt = 0;
910  LWLockRelease(DynamicSharedMemoryControlLock);
911  }
912  }
913 }
void dsm_impl_unpin_segment(dsm_handle handle, void **impl_private)
Definition: dsm_impl.c:993
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:1726
#define ERROR
Definition: elog.h:43
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
unsigned int uint32
Definition: c.h:359
#define WARNING
Definition: elog.h:40
static dsm_control_header * dsm_control
Definition: dsm.c:134
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
uint32 refcnt
Definition: dsm.c:83
#define elog(elevel,...)
Definition: elog.h:228
int i
void * impl_private_pm_handle
Definition: dsm.c:84
#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:158

◆ on_dsm_detach()

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

Definition at line 975 of file dsm.c.

References 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(), SharedFileSetAttach(), SharedFileSetInit(), SharedRecordTypmodRegistryAttach(), SharedRecordTypmodRegistryInit(), and shm_mq_attach().

976 {
978 
981  cb->function = function;
982  cb->arg = arg;
983  slist_push_head(&seg->on_detach, &cb->node);
984 }
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:44
slist_head on_detach
Definition: dsm.c:76
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
void * arg

◆ reset_on_dsm_detach()

void reset_on_dsm_detach ( void  )

Definition at line 1013 of file dsm.c.

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

Referenced by on_exit_reset().

1014 {
1015  dlist_iter iter;
1016 
1018  {
1019  dsm_segment *seg = dlist_container(dsm_segment, node, iter.cur);
1020 
1021  /* Throw away explicit on-detach actions one by one. */
1022  while (!slist_is_empty(&seg->on_detach))
1023  {
1024  slist_node *node;
1026 
1027  node = slist_pop_head_node(&seg->on_detach);
1028  cb = slist_container(dsm_segment_detach_callback, node, node);
1029  pfree(cb);
1030  }
1031 
1032  /*
1033  * Decrementing the reference count is a sort of implicit on-detach
1034  * action; make sure we don't do that, either.
1035  */
1037  }
1038 }
#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:1056
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

dsm_control_header* dsm_control
static

Definition at line 134 of file dsm.c.

Referenced by dsm_detach_all(), and dsm_postmaster_shutdown().

◆ dsm_control_handle

dsm_handle dsm_control_handle
static

◆ dsm_control_impl_private

void* dsm_control_impl_private = NULL
static

◆ dsm_control_mapped_size

Size dsm_control_mapped_size = 0
static

◆ dsm_init_done

bool dsm_init_done = false
static

Definition at line 105 of file dsm.c.

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

◆ dsm_segment_list

dlist_head dsm_segment_list = DLIST_STATIC_INIT(dsm_segment_list)
static

Definition at line 124 of file dsm.c.