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 "common/pg_prng.h"
#include "lib/ilist.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
#include "storage/lwlock.h"
#include "storage/pg_shmem.h"
#include "utils/freepage.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   5
 
#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)
 
static dsm_handle make_main_region_dsm_handle (int slot)
 
static bool is_main_region_dsm_handle (dsm_handle handle)
 
void dsm_postmaster_startup (PGShmemHeader *shim)
 
void dsm_cleanup_using_control_segment (dsm_handle old_control_handle)
 
static void dsm_backend_startup (void)
 
size_t dsm_estimate_size (void)
 
void dsm_shmem_init (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 handle)
 
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 void * dsm_main_space_begin = NULL
 
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)

Definition at line 54 of file dsm.c.

◆ PG_DYNSHMEM_CONTROL_MAGIC

#define PG_DYNSHMEM_CONTROL_MAGIC   0x9a503d32

Definition at line 49 of file dsm.c.

◆ PG_DYNSHMEM_FIXED_SLOTS

#define PG_DYNSHMEM_FIXED_SLOTS   64

Definition at line 51 of file dsm.c.

◆ PG_DYNSHMEM_SLOTS_PER_BACKEND

#define PG_DYNSHMEM_SLOTS_PER_BACKEND   5

Definition at line 52 of file dsm.c.

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 1118 of file dsm.c.

1120 {
1121  slist_mutable_iter iter;
1122 
1123  slist_foreach_modify(iter, &seg->on_detach)
1124  {
1126 
1128  if (cb->function == function && cb->arg == arg)
1129  {
1130  slist_delete_current(&iter);
1131  pfree(cb);
1132  break;
1133  }
1134  }
1135 }
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:1084
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:1148
#define slist_container(type, membername, ptr)
Definition: ilist.h:1106
void pfree(void *pointer)
Definition: mcxt.c:1456
void * arg
on_dsm_detach_callback function
Definition: dsm.c:59
slist_head on_detach
Definition: dsm.c:74
slist_node * cur
Definition: ilist.h:274

References dsm_segment_detach_callback::arg, 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 shm_mq_detach(), and test_shm_mq_setup().

◆ dsm_attach()

dsm_segment* dsm_attach ( dsm_handle  h)

Definition at line 638 of file dsm.c.

639 {
640  dsm_segment *seg;
641  dlist_iter iter;
642  uint32 i;
643  uint32 nitems;
644 
645  /* Unsafe in postmaster (and pointless in a stand-alone backend). */
647 
648  if (!dsm_init_done)
650 
651  /*
652  * Since this is just a debugging cross-check, we could leave it out
653  * altogether, or include it only in assert-enabled builds. But since the
654  * list of attached segments should normally be very short, let's include
655  * it always for right now.
656  *
657  * If you're hitting this error, you probably want to attempt to find an
658  * existing mapping via dsm_find_mapping() before calling dsm_attach() to
659  * create a new one.
660  */
662  {
663  seg = dlist_container(dsm_segment, node, iter.cur);
664  if (seg->handle == h)
665  elog(ERROR, "can't attach the same segment more than once");
666  }
667 
668  /* Create a new segment descriptor. */
669  seg = dsm_create_descriptor();
670  seg->handle = h;
671 
672  /* Bump reference count for this segment in shared memory. */
673  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
675  for (i = 0; i < nitems; ++i)
676  {
677  /*
678  * If the reference count is 0, the slot is actually unused. If the
679  * reference count is 1, the slot is still in use, but the segment is
680  * in the process of going away; even if the handle matches, another
681  * slot may already have started using the same handle value by
682  * coincidence so we have to keep searching.
683  */
684  if (dsm_control->item[i].refcnt <= 1)
685  continue;
686 
687  /* If the handle doesn't match, it's not the slot we want. */
688  if (dsm_control->item[i].handle != seg->handle)
689  continue;
690 
691  /* Otherwise we've found a match. */
692  dsm_control->item[i].refcnt++;
693  seg->control_slot = i;
695  {
696  seg->mapped_address = (char *) dsm_main_space_begin +
699  }
700  break;
701  }
702  LWLockRelease(DynamicSharedMemoryControlLock);
703 
704  /*
705  * If we didn't find the handle we're looking for in the control segment,
706  * it probably means that everyone else who had it mapped, including the
707  * original creator, died before we got to this point. It's up to the
708  * caller to decide what to do about that.
709  */
711  {
712  dsm_detach(seg);
713  return NULL;
714  }
715 
716  /* Here's where we actually try to map the segment. */
719  &seg->mapped_address, &seg->mapped_size, ERROR);
720 
721  return seg;
722 }
unsigned int uint32
Definition: c.h:495
static void dsm_backend_startup(void)
Definition: dsm.c:396
static void * dsm_main_space_begin
Definition: dsm.c:110
void dsm_detach(dsm_segment *seg)
Definition: dsm.c:776
static dlist_head dsm_segment_list
Definition: dsm.c:129
static bool dsm_init_done
Definition: dsm.c:107
static dsm_control_header * dsm_control
Definition: dsm.c:139
static dsm_segment * dsm_create_descriptor(void)
Definition: dsm.c:1172
#define INVALID_CONTROL_SLOT
Definition: dsm.c:54
static bool is_main_region_dsm_handle(dsm_handle handle)
Definition: dsm.c:1252
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:159
@ DSM_OP_ATTACH
Definition: dsm_impl.h:64
#define ERROR
Definition: elog.h:39
#define FPM_PAGE_SIZE
Definition: freepage.h:30
bool IsUnderPostmaster
Definition: globals.c:113
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
#define nitems(x)
Definition: indent.h:31
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808
@ LW_EXCLUSIVE
Definition: lwlock.h:116
dlist_node * cur
Definition: ilist.h:179
uint32 nitems
Definition: dsm.c:92
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:94
size_t npages
Definition: dsm.c:83
dsm_handle handle
Definition: dsm.c:80
size_t first_page
Definition: dsm.c:82
uint32 refcnt
Definition: dsm.c:81
uint32 control_slot
Definition: dsm.c:70
dsm_handle handle
Definition: dsm.c:69
Size mapped_size
Definition: dsm.c:73
void * impl_private
Definition: dsm.c:71
void * mapped_address
Definition: dsm.c:72

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

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

◆ dsm_backend_shutdown()

void dsm_backend_shutdown ( void  )

Definition at line 730 of file dsm.c.

731 {
733  {
734  dsm_segment *seg;
735 
737  dsm_detach(seg);
738  }
739 }
#define dlist_head_element(type, membername, lhead)
Definition: ilist.h:603
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336

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

Referenced by shmem_exit().

◆ dsm_backend_startup()

static void dsm_backend_startup ( void  )
static

Definition at line 396 of file dsm.c.

397 {
398 #ifdef EXEC_BACKEND
399  if (IsUnderPostmaster)
400  {
401  void *control_address = NULL;
402 
403  /* Attach control segment. */
406  &dsm_control_impl_private, &control_address,
408  dsm_control = control_address;
409  /* If control segment doesn't look sane, something is badly wrong. */
411  {
413  &dsm_control_impl_private, &control_address,
415  ereport(FATAL,
416  (errcode(ERRCODE_INTERNAL_ERROR),
417  errmsg("dynamic shared memory control segment is not valid")));
418  }
419  }
420 #endif
421 
422  dsm_init_done = true;
423 }
static dsm_handle dsm_control_handle
Definition: dsm.c:138
static Size dsm_control_mapped_size
Definition: dsm.c:140
static bool dsm_control_segment_sane(dsm_control_header *control, Size mapped_size)
Definition: dsm.c:1208
static void * dsm_control_impl_private
Definition: dsm.c:141
@ DSM_OP_DETACH
Definition: dsm_impl.h:65
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define FATAL
Definition: elog.h:41
#define WARNING
Definition: elog.h:36
#define ereport(elevel,...)
Definition: elog.h:149

References Assert(), dsm_control, 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, IsUnderPostmaster, and WARNING.

Referenced by dsm_attach(), and dsm_create().

◆ dsm_cleanup_for_mmap()

static void dsm_cleanup_for_mmap ( void  )
static

Definition at line 293 of file dsm.c.

294 {
295  DIR *dir;
296  struct dirent *dent;
297 
298  /* Scan the directory for something with a name of the correct format. */
300 
301  while ((dent = ReadDir(dir, PG_DYNSHMEM_DIR)) != NULL)
302  {
303  if (strncmp(dent->d_name, PG_DYNSHMEM_MMAP_FILE_PREFIX,
304  strlen(PG_DYNSHMEM_MMAP_FILE_PREFIX)) == 0)
305  {
306  char buf[MAXPGPATH + sizeof(PG_DYNSHMEM_DIR)];
307 
308  snprintf(buf, sizeof(buf), PG_DYNSHMEM_DIR "/%s", dent->d_name);
309 
310  elog(DEBUG2, "removing file \"%s\"", buf);
311 
312  /* We found a matching file; so remove it. */
313  if (unlink(buf) != 0)
314  ereport(ERROR,
316  errmsg("could not remove file \"%s\": %m", buf)));
317  }
318  }
319 
320  /* Cleanup complete. */
321  FreeDir(dir);
322 }
#define PG_DYNSHMEM_MMAP_FILE_PREFIX
Definition: dsm_impl.h:52
#define PG_DYNSHMEM_DIR
Definition: dsm_impl.h:51
int errcode_for_file_access(void)
Definition: elog.c:881
#define DEBUG2
Definition: elog.h:29
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2854
int FreeDir(DIR *dir)
Definition: fd.c:2906
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2788
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:67
#define snprintf
Definition: port.h:238
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

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().

◆ dsm_cleanup_using_control_segment()

void dsm_cleanup_using_control_segment ( dsm_handle  old_control_handle)

Definition at line 211 of file dsm.c.

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

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, is_main_region_dsm_handle(), dsm_control_header::item, LOG, dsm_control_header::nitems, nitems, and dsm_control_item::refcnt.

Referenced by PGSharedMemoryCreate().

◆ dsm_control_bytes_needed()

static uint64 dsm_control_bytes_needed ( uint32  nitems)
static

Definition at line 1226 of file dsm.c.

1227 {
1228  return offsetof(dsm_control_header, item)
1229  + sizeof(dsm_control_item) * (uint64) nitems;
1230 }
struct dsm_control_item dsm_control_item

References nitems.

Referenced by dsm_control_segment_sane(), and dsm_postmaster_startup().

◆ dsm_control_segment_sane()

static bool dsm_control_segment_sane ( dsm_control_header control,
Size  mapped_size 
)
static

Definition at line 1208 of file dsm.c.

1209 {
1210  if (mapped_size < offsetof(dsm_control_header, item))
1211  return false; /* Mapped size too short to read header. */
1212  if (control->magic != PG_DYNSHMEM_CONTROL_MAGIC)
1213  return false; /* Magic number doesn't match. */
1214  if (dsm_control_bytes_needed(control->maxitems) > mapped_size)
1215  return false; /* Max item count won't fit in map. */
1216  if (control->nitems > control->maxitems)
1217  return false; /* Overfull. */
1218  return true;
1219 }
#define PG_DYNSHMEM_CONTROL_MAGIC
Definition: dsm.c:49
static uint64 dsm_control_bytes_needed(uint32 nitems)
Definition: dsm.c:1226
uint32 maxitems
Definition: dsm.c:93
uint32 magic
Definition: dsm.c:91

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

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

◆ dsm_create()

dsm_segment* dsm_create ( Size  size,
int  flags 
)

Definition at line 489 of file dsm.c.

490 {
491  dsm_segment *seg;
492  uint32 i;
493  uint32 nitems;
494  size_t npages = 0;
495  size_t first_page = 0;
496  FreePageManager *dsm_main_space_fpm = dsm_main_space_begin;
497  bool using_main_dsm_region = false;
498 
499  /*
500  * Unsafe in postmaster. It might seem pointless to allow use of dsm in
501  * single user mode, but otherwise some subsystems will need dedicated
502  * single user mode code paths.
503  */
505 
506  if (!dsm_init_done)
508 
509  /* Create a new segment descriptor. */
510  seg = dsm_create_descriptor();
511 
512  /*
513  * Lock the control segment while we try to allocate from the main shared
514  * memory area, if configured.
515  */
516  if (dsm_main_space_fpm)
517  {
518  npages = size / FPM_PAGE_SIZE;
519  if (size % FPM_PAGE_SIZE > 0)
520  ++npages;
521 
522  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
523  if (FreePageManagerGet(dsm_main_space_fpm, npages, &first_page))
524  {
525  /* We can carve out a piece of the main shared memory segment. */
526  seg->mapped_address = (char *) dsm_main_space_begin +
527  first_page * FPM_PAGE_SIZE;
528  seg->mapped_size = npages * FPM_PAGE_SIZE;
529  using_main_dsm_region = true;
530  /* We'll choose a handle below. */
531  }
532  }
533 
534  if (!using_main_dsm_region)
535  {
536  /*
537  * We need to create a new memory segment. Loop until we find an
538  * unused segment identifier.
539  */
540  if (dsm_main_space_fpm)
541  LWLockRelease(DynamicSharedMemoryControlLock);
542  for (;;)
543  {
544  Assert(seg->mapped_address == NULL && seg->mapped_size == 0);
545  /* Use even numbers only */
547  if (seg->handle == DSM_HANDLE_INVALID) /* Reserve sentinel */
548  continue;
549  if (dsm_impl_op(DSM_OP_CREATE, seg->handle, size, &seg->impl_private,
550  &seg->mapped_address, &seg->mapped_size, ERROR))
551  break;
552  }
553  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
554  }
555 
556  /* Search the control segment for an unused slot. */
558  for (i = 0; i < nitems; ++i)
559  {
560  if (dsm_control->item[i].refcnt == 0)
561  {
562  if (using_main_dsm_region)
563  {
565  dsm_control->item[i].first_page = first_page;
566  dsm_control->item[i].npages = npages;
567  }
568  else
570  dsm_control->item[i].handle = seg->handle;
571  /* refcnt of 1 triggers destruction, so start at 2 */
572  dsm_control->item[i].refcnt = 2;
574  dsm_control->item[i].pinned = false;
575  seg->control_slot = i;
576  LWLockRelease(DynamicSharedMemoryControlLock);
577  return seg;
578  }
579  }
580 
581  /* Verify that we can support an additional mapping. */
582  if (nitems >= dsm_control->maxitems)
583  {
584  if (using_main_dsm_region)
585  FreePageManagerPut(dsm_main_space_fpm, first_page, npages);
586  LWLockRelease(DynamicSharedMemoryControlLock);
587  if (!using_main_dsm_region)
589  &seg->mapped_address, &seg->mapped_size, WARNING);
590  if (seg->resowner != NULL)
591  ResourceOwnerForgetDSM(seg->resowner, seg);
592  dlist_delete(&seg->node);
593  pfree(seg);
594 
595  if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0)
596  return NULL;
597  ereport(ERROR,
598  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
599  errmsg("too many dynamic shared memory segments")));
600  }
601 
602  /* Enter the handle into a new array slot. */
603  if (using_main_dsm_region)
604  {
606  dsm_control->item[i].first_page = first_page;
607  dsm_control->item[i].npages = npages;
608  }
610  /* refcnt of 1 triggers destruction, so start at 2 */
613  dsm_control->item[nitems].pinned = false;
614  seg->control_slot = nitems;
615  dsm_control->nitems++;
616  LWLockRelease(DynamicSharedMemoryControlLock);
617 
618  return seg;
619 }
static dsm_handle make_main_region_dsm_handle(int slot)
Definition: dsm.c:1233
#define DSM_CREATE_NULL_IF_MAXSEGMENTS
Definition: dsm.h:20
@ DSM_OP_CREATE
Definition: dsm_impl.h:63
#define DSM_HANDLE_INVALID
Definition: dsm_impl.h:58
bool FreePageManagerGet(FreePageManager *fpm, Size npages, Size *first_page)
Definition: freepage.c:210
void FreePageManagerPut(FreePageManager *fpm, Size first_page, Size npages)
Definition: freepage.c:379
bool IsPostmasterEnvironment
Definition: globals.c:112
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
uint32 pg_prng_uint32(pg_prng_state *state)
Definition: pg_prng.c:191
pg_prng_state pg_global_prng_state
Definition: pg_prng.c:34
void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1415
bool pinned
Definition: dsm.c:85
void * impl_private_pm_handle
Definition: dsm.c:84
dlist_node node
Definition: dsm.c:67
ResourceOwner resowner
Definition: dsm.c:68

References Assert(), dsm_segment::control_slot, dlist_delete(), dsm_backend_startup(), dsm_control, dsm_create_descriptor(), DSM_CREATE_NULL_IF_MAXSEGMENTS, DSM_HANDLE_INVALID, dsm_impl_op(), dsm_init_done, dsm_main_space_begin, DSM_OP_CREATE, DSM_OP_DESTROY, ereport, errcode(), errmsg(), ERROR, dsm_control_item::first_page, FPM_PAGE_SIZE, FreePageManagerGet(), FreePageManagerPut(), dsm_segment::handle, dsm_control_item::handle, i, dsm_segment::impl_private, dsm_control_item::impl_private_pm_handle, is_main_region_dsm_handle(), IsPostmasterEnvironment, IsUnderPostmaster, dsm_control_header::item, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), make_main_region_dsm_handle(), dsm_segment::mapped_address, dsm_segment::mapped_size, dsm_control_header::maxitems, dsm_control_header::nitems, nitems, dsm_segment::node, dsm_control_item::npages, pfree(), pg_global_prng_state, pg_prng_uint32(), dsm_control_item::pinned, dsm_control_item::refcnt, ResourceOwnerForgetDSM(), dsm_segment::resowner, and WARNING.

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

◆ dsm_create_descriptor()

static dsm_segment * dsm_create_descriptor ( void  )
static

Definition at line 1172 of file dsm.c.

1173 {
1174  dsm_segment *seg;
1175 
1178 
1181 
1182  /* seg->handle must be initialized by the caller */
1184  seg->impl_private = NULL;
1185  seg->mapped_address = NULL;
1186  seg->mapped_size = 0;
1187 
1191 
1192  slist_init(&seg->on_detach);
1193 
1194  return seg;
1195 }
static void slist_init(slist_head *head)
Definition: ilist.h:986
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
MemoryContext TopMemoryContext
Definition: mcxt.c:141
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147
void ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
Definition: resowner.c:1406
void ResourceOwnerEnlargeDSMs(ResourceOwner owner)
Definition: resowner.c:1395

References dsm_segment::control_slot, CurrentResourceOwner, dlist_push_head(), dsm_segment_list, 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().

◆ dsm_detach()

void dsm_detach ( dsm_segment seg)

Definition at line 776 of file dsm.c.

777 {
778  /*
779  * Invoke registered callbacks. Just in case one of those callbacks
780  * throws a further error that brings us back here, pop the callback
781  * before invoking it, to avoid infinite error recursion. Don't allow
782  * interrupts while running the individual callbacks in non-error code
783  * paths, to avoid leaving cleanup work unfinished if we're interrupted by
784  * a statement timeout or similar.
785  */
786  HOLD_INTERRUPTS();
787  while (!slist_is_empty(&seg->on_detach))
788  {
789  slist_node *node;
791  on_dsm_detach_callback function;
792  Datum arg;
793 
794  node = slist_pop_head_node(&seg->on_detach);
796  function = cb->function;
797  arg = cb->arg;
798  pfree(cb);
799 
800  function(seg, arg);
801  }
803 
804  /*
805  * Try to remove the mapping, if one exists. Normally, there will be, but
806  * maybe not, if we failed partway through a create or attach operation.
807  * We remove the mapping before decrementing the reference count so that
808  * the process that sees a zero reference count can be certain that no
809  * remaining mappings exist. Even if this fails, we pretend that it
810  * works, because retrying is likely to fail in the same way.
811  */
812  if (seg->mapped_address != NULL)
813  {
816  &seg->mapped_address, &seg->mapped_size, WARNING);
817  seg->impl_private = NULL;
818  seg->mapped_address = NULL;
819  seg->mapped_size = 0;
820  }
821 
822  /* Reduce reference count, if we previously increased it. */
824  {
825  uint32 refcnt;
826  uint32 control_slot = seg->control_slot;
827 
828  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
829  Assert(dsm_control->item[control_slot].handle == seg->handle);
830  Assert(dsm_control->item[control_slot].refcnt > 1);
831  refcnt = --dsm_control->item[control_slot].refcnt;
833  LWLockRelease(DynamicSharedMemoryControlLock);
834 
835  /* If new reference count is 1, try to destroy the segment. */
836  if (refcnt == 1)
837  {
838  /* A pinned segment should never reach 1. */
839  Assert(!dsm_control->item[control_slot].pinned);
840 
841  /*
842  * If we fail to destroy the segment here, or are killed before we
843  * finish doing so, the reference count will remain at 1, which
844  * will mean that nobody else can attach to the segment. At
845  * postmaster shutdown time, or when a new postmaster is started
846  * after a hard kill, another attempt will be made to remove the
847  * segment.
848  *
849  * The main case we're worried about here is being killed by a
850  * signal before we can finish removing the segment. In that
851  * case, it's important to be sure that the segment still gets
852  * removed. If we actually fail to remove the segment for some
853  * other reason, the postmaster may not have any better luck than
854  * we did. There's not much we can do about that, though.
855  */
856  if (is_main_region_dsm_handle(seg->handle) ||
858  &seg->mapped_address, &seg->mapped_size, WARNING))
859  {
860  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
863  dsm_control->item[control_slot].first_page,
864  dsm_control->item[control_slot].npages);
865  Assert(dsm_control->item[control_slot].handle == seg->handle);
866  Assert(dsm_control->item[control_slot].refcnt == 1);
867  dsm_control->item[control_slot].refcnt = 0;
868  LWLockRelease(DynamicSharedMemoryControlLock);
869  }
870  }
871  }
872 
873  /* Clean up our remaining backend-private data structures. */
874  if (seg->resowner != NULL)
875  ResourceOwnerForgetDSM(seg->resowner, seg);
876  dlist_delete(&seg->node);
877  pfree(seg);
878 }
void(* on_dsm_detach_callback)(dsm_segment *, Datum arg)
Definition: dsm.h:54
static bool slist_is_empty(const slist_head *head)
Definition: ilist.h:995
static slist_node * slist_pop_head_node(slist_head *head)
Definition: ilist.h:1028
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:134
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:132
uintptr_t Datum
Definition: postgres.h:64

References dsm_segment_detach_callback::arg, arg, Assert(), dsm_segment::control_slot, dlist_delete(), dsm_control, dsm_impl_op(), dsm_main_space_begin, DSM_OP_DESTROY, DSM_OP_DETACH, dsm_control_item::first_page, FreePageManagerPut(), dsm_segment_detach_callback::function, dsm_segment::handle, dsm_control_item::handle, HOLD_INTERRUPTS, dsm_segment::impl_private, INVALID_CONTROL_SLOT, is_main_region_dsm_handle(), dsm_control_header::item, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), dsm_segment::mapped_address, dsm_segment::mapped_size, dsm_segment::node, dsm_control_item::npages, dsm_segment::on_detach, pfree(), dsm_control_item::pinned, dsm_control_item::refcnt, ResourceOwnerForgetDSM(), dsm_segment::resowner, RESUME_INTERRUPTS, 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(), pa_free_worker_info(), pa_shutdown(), ParallelWorkerShutdown(), ResourceOwnerReleaseInternal(), test_shm_mq(), test_shm_mq_main(), and test_shm_mq_pipelined().

◆ dsm_detach_all()

void dsm_detach_all ( void  )

Definition at line 748 of file dsm.c.

749 {
750  void *control_address = dsm_control;
751 
753  {
754  dsm_segment *seg;
755 
757  dsm_detach(seg);
758  }
759 
760  if (control_address != NULL)
762  &dsm_control_impl_private, &control_address,
764 }

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, dsm_segment_list, and ERROR.

Referenced by SysLogger_Start().

◆ dsm_estimate_size()

size_t dsm_estimate_size ( void  )

Definition at line 443 of file dsm.c.

444 {
445  return 1024 * 1024 * (size_t) min_dynamic_shared_memory;
446 }
int min_dynamic_shared_memory
Definition: dsm_impl.c:115

References min_dynamic_shared_memory.

Referenced by CalculateShmemSize(), and dsm_shmem_init().

◆ dsm_find_mapping()

dsm_segment* dsm_find_mapping ( dsm_handle  handle)

Definition at line 1047 of file dsm.c.

1048 {
1049  dlist_iter iter;
1050  dsm_segment *seg;
1051 
1053  {
1054  seg = dlist_container(dsm_segment, node, iter.cur);
1055  if (seg->handle == handle)
1056  return seg;
1057  }
1058 
1059  return NULL;
1060 }

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

◆ dsm_pin_mapping()

void dsm_pin_mapping ( dsm_segment seg)

Definition at line 888 of file dsm.c.

889 {
890  if (seg->resowner != NULL)
891  {
892  ResourceOwnerForgetDSM(seg->resowner, seg);
893  seg->resowner = NULL;
894  }
895 }

References ResourceOwnerForgetDSM(), and dsm_segment::resowner.

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

◆ dsm_pin_segment()

void dsm_pin_segment ( dsm_segment seg)

Definition at line 928 of file dsm.c.

929 {
930  void *handle;
931 
932  /*
933  * Bump reference count for this segment in shared memory. This will
934  * ensure that even if there is no session which is attached to this
935  * segment, it will remain until postmaster shutdown or an explicit call
936  * to unpin.
937  */
938  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
939  if (dsm_control->item[seg->control_slot].pinned)
940  elog(ERROR, "cannot pin a segment that is already pinned");
941  dsm_impl_pin_segment(seg->handle, seg->impl_private, &handle);
942  dsm_control->item[seg->control_slot].pinned = true;
945  LWLockRelease(DynamicSharedMemoryControlLock);
946 }
void dsm_impl_pin_segment(dsm_handle handle, void *impl_private, void **impl_private_pm_handle)
Definition: dsm_impl.c:963

References dsm_segment::control_slot, dsm_control, 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().

◆ dsm_postmaster_shutdown()

static void dsm_postmaster_shutdown ( int  code,
Datum  arg 
)
static

Definition at line 331 of file dsm.c.

332 {
333  uint32 nitems;
334  uint32 i;
335  void *dsm_control_address;
336  void *junk_mapped_address = NULL;
337  void *junk_impl_private = NULL;
338  Size junk_mapped_size = 0;
340 
341  /*
342  * If some other backend exited uncleanly, it might have corrupted the
343  * control segment while it was dying. In that case, we warn and ignore
344  * the contents of the control segment. This may end up leaving behind
345  * stray shared memory segments, but there's not much we can do about that
346  * if the metadata is gone.
347  */
350  {
351  ereport(LOG,
352  (errmsg("dynamic shared memory control segment is corrupt")));
353  return;
354  }
355 
356  /* Remove any remaining segments. */
357  for (i = 0; i < nitems; ++i)
358  {
359  dsm_handle handle;
360 
361  /* If the reference count is 0, the slot is actually unused. */
362  if (dsm_control->item[i].refcnt == 0)
363  continue;
364 
365  handle = dsm_control->item[i].handle;
366  if (is_main_region_dsm_handle(handle))
367  continue;
368 
369  /* Log debugging information. */
370  elog(DEBUG2, "cleaning up orphaned dynamic shared memory with ID %u",
371  handle);
372 
373  /* Destroy the segment. */
374  dsm_impl_op(DSM_OP_DESTROY, handle, 0, &junk_impl_private,
375  &junk_mapped_address, &junk_mapped_size, LOG);
376  }
377 
378  /* Remove the control segment itself. */
379  elog(DEBUG2,
380  "cleaning up dynamic shared memory control segment with ID %u",
382  dsm_control_address = dsm_control;
384  &dsm_control_impl_private, &dsm_control_address,
386  dsm_control = dsm_control_address;
387  shim->dsm_control = 0;
388 }
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
dsm_handle dsm_control
Definition: pg_shmem.h:36

References arg, DatumGetPointer(), DEBUG2, dsm_control, PGShmemHeader::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, is_main_region_dsm_handle(), dsm_control_header::item, LOG, dsm_control_header::nitems, nitems, and dsm_control_item::refcnt.

Referenced by dsm_postmaster_startup().

◆ dsm_postmaster_startup()

void dsm_postmaster_startup ( PGShmemHeader shim)

Definition at line 150 of file dsm.c.

151 {
152  void *dsm_control_address = NULL;
153  uint32 maxitems;
154  Size segsize;
155 
157 
158  /*
159  * If we're using the mmap implementations, clean up any leftovers.
160  * Cleanup isn't needed on Windows, and happens earlier in startup for
161  * POSIX and System V shared memory, via a direct call to
162  * dsm_cleanup_using_control_segment.
163  */
166 
167  /* Determine size for new control segment. */
168  maxitems = PG_DYNSHMEM_FIXED_SLOTS
170  elog(DEBUG2, "dynamic shared memory system will support %u segments",
171  maxitems);
172  segsize = dsm_control_bytes_needed(maxitems);
173 
174  /*
175  * Loop until we find an unused identifier for the new control segment. We
176  * sometimes use DSM_HANDLE_INVALID as a sentinel value indicating "no
177  * control segment", so avoid generating that value for a real handle.
178  */
179  for (;;)
180  {
181  Assert(dsm_control_address == NULL);
183  /* Use even numbers only */
186  continue;
188  &dsm_control_impl_private, &dsm_control_address,
190  break;
191  }
192  dsm_control = dsm_control_address;
194  elog(DEBUG2,
195  "created dynamic shared memory control segment %u (%zu bytes)",
196  dsm_control_handle, segsize);
198 
199  /* Initialize control segment. */
201  dsm_control->nitems = 0;
202  dsm_control->maxitems = maxitems;
203 }
static void dsm_postmaster_shutdown(int code, Datum arg)
Definition: dsm.c:331
#define PG_DYNSHMEM_SLOTS_PER_BACKEND
Definition: dsm.c:52
#define PG_DYNSHMEM_FIXED_SLOTS
Definition: dsm.c:51
static void dsm_cleanup_for_mmap(void)
Definition: dsm.c:293
int dynamic_shared_memory_type
Definition: dsm_impl.c:112
#define DSM_IMPL_MMAP
Definition: dsm_impl.h:20
int MaxBackends
Definition: globals.c:140
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322

References Assert(), DEBUG2, dsm_cleanup_for_mmap(), dsm_control, 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, pg_global_prng_state, pg_prng_uint32(), and PointerGetDatum().

Referenced by CreateSharedMemoryAndSemaphores().

◆ dsm_segment_address()

◆ dsm_segment_handle()

◆ dsm_segment_map_length()

Size dsm_segment_map_length ( dsm_segment seg)

Definition at line 1076 of file dsm.c.

1077 {
1078  Assert(seg->mapped_address != NULL);
1079  return seg->mapped_size;
1080 }

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

◆ dsm_shmem_init()

void dsm_shmem_init ( void  )

Definition at line 452 of file dsm.c.

453 {
454  size_t size = dsm_estimate_size();
455  bool found;
456 
457  if (size == 0)
458  return;
459 
460  dsm_main_space_begin = ShmemInitStruct("Preallocated DSM", size, &found);
461  if (!found)
462  {
464  size_t first_page = 0;
465  size_t pages;
466 
467  /* Reserve space for the FreePageManager. */
468  while (first_page * FPM_PAGE_SIZE < sizeof(FreePageManager))
469  ++first_page;
470 
471  /* Initialize it and give it all the rest of the space. */
473  pages = (size / FPM_PAGE_SIZE) - first_page;
474  FreePageManagerPut(fpm, first_page, pages);
475  }
476 }
size_t dsm_estimate_size(void)
Definition: dsm.c:443
void FreePageManagerInitialize(FreePageManager *fpm, char *base)
Definition: freepage.c:183
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396

References dsm_estimate_size(), dsm_main_space_begin, FPM_PAGE_SIZE, FreePageManagerInitialize(), FreePageManagerPut(), and ShmemInitStruct().

Referenced by CreateSharedMemoryAndSemaphores().

◆ dsm_unpin_mapping()

void dsm_unpin_mapping ( dsm_segment seg)

◆ dsm_unpin_segment()

void dsm_unpin_segment ( dsm_handle  handle)

Definition at line 960 of file dsm.c.

961 {
962  uint32 control_slot = INVALID_CONTROL_SLOT;
963  bool destroy = false;
964  uint32 i;
965 
966  /* Find the control slot for the given handle. */
967  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
968  for (i = 0; i < dsm_control->nitems; ++i)
969  {
970  /* Skip unused slots and segments that are concurrently going away. */
971  if (dsm_control->item[i].refcnt <= 1)
972  continue;
973 
974  /* If we've found our handle, we can stop searching. */
975  if (dsm_control->item[i].handle == handle)
976  {
977  control_slot = i;
978  break;
979  }
980  }
981 
982  /*
983  * We should definitely have found the slot, and it should not already be
984  * in the process of going away, because this function should only be
985  * called on a segment which is pinned.
986  */
987  if (control_slot == INVALID_CONTROL_SLOT)
988  elog(ERROR, "cannot unpin unknown segment handle");
989  if (!dsm_control->item[control_slot].pinned)
990  elog(ERROR, "cannot unpin a segment that is not pinned");
991  Assert(dsm_control->item[control_slot].refcnt > 1);
992 
993  /*
994  * Allow implementation-specific code to run. We have to do this before
995  * releasing the lock, because impl_private_pm_handle may get modified by
996  * dsm_impl_unpin_segment.
997  */
998  dsm_impl_unpin_segment(handle,
999  &dsm_control->item[control_slot].impl_private_pm_handle);
1000 
1001  /* Note that 1 means no references (0 means unused slot). */
1002  if (--dsm_control->item[control_slot].refcnt == 1)
1003  destroy = true;
1004  dsm_control->item[control_slot].pinned = false;
1005 
1006  /* Now we can release the lock. */
1007  LWLockRelease(DynamicSharedMemoryControlLock);
1008 
1009  /* Clean up resources if that was the last reference. */
1010  if (destroy)
1011  {
1012  void *junk_impl_private = NULL;
1013  void *junk_mapped_address = NULL;
1014  Size junk_mapped_size = 0;
1015 
1016  /*
1017  * For an explanation of how error handling works in this case, see
1018  * comments in dsm_detach. Note that if we reach this point, the
1019  * current process certainly does not have the segment mapped, because
1020  * if it did, the reference count would have still been greater than 1
1021  * even after releasing the reference count held by the pin. The fact
1022  * that there can't be a dsm_segment for this handle makes it OK to
1023  * pass the mapped size, mapped address, and private data as NULL
1024  * here.
1025  */
1026  if (is_main_region_dsm_handle(handle) ||
1027  dsm_impl_op(DSM_OP_DESTROY, handle, 0, &junk_impl_private,
1028  &junk_mapped_address, &junk_mapped_size, WARNING))
1029  {
1030  LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
1031  if (is_main_region_dsm_handle(handle))
1033  dsm_control->item[control_slot].first_page,
1034  dsm_control->item[control_slot].npages);
1035  Assert(dsm_control->item[control_slot].handle == handle);
1036  Assert(dsm_control->item[control_slot].refcnt == 1);
1037  dsm_control->item[control_slot].refcnt = 0;
1038  LWLockRelease(DynamicSharedMemoryControlLock);
1039  }
1040  }
1041 }
void dsm_impl_unpin_segment(dsm_handle handle, void **impl_private)
Definition: dsm_impl.c:1014

References Assert(), dsm_control, dsm_impl_op(), dsm_impl_unpin_segment(), dsm_main_space_begin, DSM_OP_DESTROY, elog(), ERROR, dsm_control_item::first_page, FreePageManagerPut(), dsm_control_item::handle, i, dsm_control_item::impl_private_pm_handle, INVALID_CONTROL_SLOT, is_main_region_dsm_handle(), dsm_control_header::item, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), dsm_control_header::nitems, dsm_control_item::npages, dsm_control_item::pinned, dsm_control_item::refcnt, and WARNING.

Referenced by destroy_superblock(), and dsa_release_in_place().

◆ is_main_region_dsm_handle()

static bool is_main_region_dsm_handle ( dsm_handle  handle)
inlinestatic

Definition at line 1252 of file dsm.c.

1253 {
1254  return handle & 1;
1255 }

Referenced by dsm_attach(), dsm_cleanup_using_control_segment(), dsm_create(), dsm_detach(), dsm_postmaster_shutdown(), and dsm_unpin_segment().

◆ make_main_region_dsm_handle()

static dsm_handle make_main_region_dsm_handle ( int  slot)
inlinestatic

Definition at line 1233 of file dsm.c.

1234 {
1235  dsm_handle handle;
1236 
1237  /*
1238  * We need to create a handle that doesn't collide with any existing extra
1239  * segment created by dsm_impl_op(), so we'll make it odd. It also
1240  * mustn't collide with any other main area pseudo-segment, so we'll
1241  * include the slot number in some of the bits. We also want to make an
1242  * effort to avoid newly created and recently destroyed handles from being
1243  * confused, so we'll make the rest of the bits random.
1244  */
1245  handle = 1;
1246  handle |= slot << 1;
1248  return handle;
1249 }
static int pg_leftmost_one_pos32(uint32 word)
Definition: pg_bitutils.h:41

References dsm_control, dsm_control_header::maxitems, pg_global_prng_state, pg_leftmost_one_pos32(), and pg_prng_uint32().

Referenced by dsm_create().

◆ on_dsm_detach()

◆ reset_on_dsm_detach()

void reset_on_dsm_detach ( void  )

Definition at line 1141 of file dsm.c.

1142 {
1143  dlist_iter iter;
1144 
1146  {
1147  dsm_segment *seg = dlist_container(dsm_segment, node, iter.cur);
1148 
1149  /* Throw away explicit on-detach actions one by one. */
1150  while (!slist_is_empty(&seg->on_detach))
1151  {
1152  slist_node *node;
1154 
1155  node = slist_pop_head_node(&seg->on_detach);
1156  cb = slist_container(dsm_segment_detach_callback, node, node);
1157  pfree(cb);
1158  }
1159 
1160  /*
1161  * Decrementing the reference count is a sort of implicit on-detach
1162  * action; make sure we don't do that, either.
1163  */
1165  }
1166 }

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

Referenced by on_exit_reset().

Variable Documentation

◆ dsm_control

◆ 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 107 of file dsm.c.

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

◆ dsm_main_space_begin

void* dsm_main_space_begin = NULL
static

Definition at line 110 of file dsm.c.

Referenced by dsm_attach(), dsm_create(), dsm_detach(), dsm_shmem_init(), and dsm_unpin_segment().

◆ dsm_segment_list

dlist_head dsm_segment_list = DLIST_STATIC_INIT(dsm_segment_list)
static