PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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/fd.h"
#include "storage/ipc.h"
#include "storage/lwlock.h"
#include "storage/pg_shmem.h"
#include "storage/shmem.h"
#include "storage/subsystems.h"
#include "utils/freepage.h"
#include "utils/memutils.h"
#include "utils/resowner.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)
 
static void dsm_main_space_request (void *arg)
 
static void dsm_main_space_init (void *arg)
 
static void ResOwnerReleaseDSM (Datum res)
 
static charResOwnerPrintDSM (Datum res)
 
static void ResourceOwnerRememberDSM (ResourceOwner owner, dsm_segment *seg)
 
static void ResourceOwnerForgetDSM (ResourceOwner owner, dsm_segment *seg)
 
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 handle)
 
voiddsm_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 voiddsm_main_space_begin = NULL
 
static size_t dsm_main_space_size
 
const ShmemCallbacks dsm_shmem_callbacks
 
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 voiddsm_control_impl_private = NULL
 
static const ResourceOwnerDesc dsm_resowner_desc
 

Macro Definition Documentation

◆ INVALID_CONTROL_SLOT

#define INVALID_CONTROL_SLOT   ((uint32) -1)

Definition at line 56 of file dsm.c.

◆ PG_DYNSHMEM_CONTROL_MAGIC

#define PG_DYNSHMEM_CONTROL_MAGIC   0x9a503d32

Definition at line 51 of file dsm.c.

◆ PG_DYNSHMEM_FIXED_SLOTS

#define PG_DYNSHMEM_FIXED_SLOTS   64

Definition at line 53 of file dsm.c.

◆ PG_DYNSHMEM_SLOTS_PER_BACKEND

#define PG_DYNSHMEM_SLOTS_PER_BACKEND   5

Definition at line 54 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 1155 of file dsm.c.

1157{
1158 slist_mutable_iter iter;
1159
1160 slist_foreach_modify(iter, &seg->on_detach)
1161 {
1163
1165 if (cb->function == function && cb->arg == arg)
1166 {
1167 slist_delete_current(&iter);
1168 pfree(cb);
1169 break;
1170 }
1171 }
1172}
Datum arg
Definition elog.c:1323
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:1616
on_exit_nicely_callback function
on_dsm_detach_callback function
Definition dsm.c:61
slist_head on_detach
Definition dsm.c:76
slist_node * cur
Definition ilist.h:274

References dsm_segment_detach_callback::arg, arg, slist_mutable_iter::cur, dsm_segment_detach_callback::function, 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 673 of file dsm.c.

674{
675 dsm_segment *seg;
676 dlist_iter iter;
677 uint32 i;
679
680 /* Unsafe in postmaster (and pointless in a stand-alone backend). */
682
683 if (!dsm_init_done)
685
686 /*
687 * Since this is just a debugging cross-check, we could leave it out
688 * altogether, or include it only in assert-enabled builds. But since the
689 * list of attached segments should normally be very short, let's include
690 * it always for right now.
691 *
692 * If you're hitting this error, you probably want to attempt to find an
693 * existing mapping via dsm_find_mapping() before calling dsm_attach() to
694 * create a new one.
695 */
697 {
698 seg = dlist_container(dsm_segment, node, iter.cur);
699 if (seg->handle == h)
700 elog(ERROR, "can't attach the same segment more than once");
701 }
702
703 /* Create a new segment descriptor. */
704 seg = dsm_create_descriptor();
705 seg->handle = h;
706
707 /* Bump reference count for this segment in shared memory. */
710 for (i = 0; i < nitems; ++i)
711 {
712 /*
713 * If the reference count is 0, the slot is actually unused. If the
714 * reference count is 1, the slot is still in use, but the segment is
715 * in the process of going away; even if the handle matches, another
716 * slot may already have started using the same handle value by
717 * coincidence so we have to keep searching.
718 */
719 if (dsm_control->item[i].refcnt <= 1)
720 continue;
721
722 /* If the handle doesn't match, it's not the slot we want. */
723 if (dsm_control->item[i].handle != seg->handle)
724 continue;
725
726 /* Otherwise we've found a match. */
728 seg->control_slot = i;
730 {
731 seg->mapped_address = (char *) dsm_main_space_begin +
734 }
735 break;
736 }
738
739 /*
740 * If we didn't find the handle we're looking for in the control segment,
741 * it probably means that everyone else who had it mapped, including the
742 * original creator, died before we got to this point. It's up to the
743 * caller to decide what to do about that.
744 */
746 {
747 dsm_detach(seg);
748 return NULL;
749 }
750
751 /* Here's where we actually try to map the segment. */
754 &seg->mapped_address, &seg->mapped_size, ERROR);
755
756 return seg;
757}
#define Assert(condition)
Definition c.h:943
uint32_t uint32
Definition c.h:624
static void dsm_backend_startup(void)
Definition dsm.c:433
static void * dsm_main_space_begin
Definition dsm.c:112
void dsm_detach(dsm_segment *seg)
Definition dsm.c:811
static dlist_head dsm_segment_list
Definition dsm.c:140
static bool dsm_init_done
Definition dsm.c:109
static dsm_control_header * dsm_control
Definition dsm.c:150
static dsm_segment * dsm_create_descriptor(void)
Definition dsm.c:1209
#define INVALID_CONTROL_SLOT
Definition dsm.c:56
static bool is_main_region_dsm_handle(dsm_handle handle)
Definition dsm.c:1289
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:160
@ DSM_OP_ATTACH
Definition dsm_impl.h:64
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define FPM_PAGE_SIZE
Definition freepage.h:30
bool IsUnderPostmaster
Definition globals.c:122
#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:77
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_EXCLUSIVE
Definition lwlock.h:104
static int fb(int x)
dlist_node * cur
Definition ilist.h:179
uint32 nitems
Definition dsm.c:94
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition dsm.c:96
size_t npages
Definition dsm.c:85
dsm_handle handle
Definition dsm.c:82
size_t first_page
Definition dsm.c:84
uint32 refcnt
Definition dsm.c:83
uint32 control_slot
Definition dsm.c:72
dsm_handle handle
Definition dsm.c:71
Size mapped_size
Definition dsm.c:75
void * impl_private
Definition dsm.c:73
void * mapped_address
Definition dsm.c:74

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, fb(), 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(), dsa_get_total_size_from_handle(), get_segment_by_index(), GetNamedDSMSegment(), ParallelApplyWorkerMain(), ParallelWorkerMain(), RepackWorkerMain(), and test_shm_mq_main().

◆ dsm_backend_shutdown()

void dsm_backend_shutdown ( void  )

Definition at line 765 of file dsm.c.

766{
768 {
769 dsm_segment *seg;
770
772 dsm_detach(seg);
773 }
774}
#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 433 of file dsm.c.

434{
435#ifdef EXEC_BACKEND
437 {
438 void *control_address = NULL;
439
440 /* Attach control segment. */
446 /* If control segment doesn't look sane, something is badly wrong. */
448 {
454 errmsg("dynamic shared memory control segment is not valid")));
455 }
456 }
457#endif
458
459 dsm_init_done = true;
460}
static dsm_handle dsm_control_handle
Definition dsm.c:149
static Size dsm_control_mapped_size
Definition dsm.c:151
static bool dsm_control_segment_sane(dsm_control_header *control, Size mapped_size)
Definition dsm.c:1245
static void * dsm_control_impl_private
Definition dsm.c:152
@ DSM_OP_DETACH
Definition dsm_impl.h:65
int errcode(int sqlerrcode)
Definition elog.c:875
#define FATAL
Definition elog.h:42
#define WARNING
Definition elog.h:37
#define ereport(elevel,...)
Definition elog.h:152
static char * errmsg

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, fb(), 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 330 of file dsm.c.

331{
332 DIR *dir;
333 struct dirent *dent;
334
335 /* Scan the directory for something with a name of the correct format. */
337
338 while ((dent = ReadDir(dir, PG_DYNSHMEM_DIR)) != NULL)
339 {
342 {
343 char buf[MAXPGPATH + sizeof(PG_DYNSHMEM_DIR)];
344
345 snprintf(buf, sizeof(buf), PG_DYNSHMEM_DIR "/%s", dent->d_name);
346
347 elog(DEBUG2, "removing file \"%s\"", buf);
348
349 /* We found a matching file; so remove it. */
350 if (unlink(buf) != 0)
353 errmsg("could not remove file \"%s\": %m", buf)));
354 }
355 }
356
357 /* Cleanup complete. */
358 FreeDir(dir);
359}
#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:898
#define DEBUG2
Definition elog.h:30
int FreeDir(DIR *dir)
Definition fd.c:3009
DIR * AllocateDir(const char *dirname)
Definition fd.c:2891
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition fd.c:2957
#define MAXPGPATH
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:260
Definition dirent.c:26

References AllocateDir(), buf, DEBUG2, elog, ereport, errcode_for_file_access(), errmsg, ERROR, fb(), 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 248 of file dsm.c.

249{
250 void *mapped_address = NULL;
252 void *impl_private = NULL;
253 void *junk_impl_private = NULL;
254 Size mapped_size = 0;
257 uint32 i;
259
260 /*
261 * Try to attach the segment. If this fails, it probably just means that
262 * the operating system has been rebooted and the segment no longer
263 * exists, or an unrelated process has used the same shm ID. So just fall
264 * out quietly.
265 */
266 if (!dsm_impl_op(DSM_OP_ATTACH, old_control_handle, 0, &impl_private,
267 &mapped_address, &mapped_size, DEBUG1))
268 return;
269
270 /*
271 * We've managed to reattach it, but the contents might not be sane. If
272 * they aren't, we disregard the segment after all.
273 */
274 old_control = (dsm_control_header *) mapped_address;
275 if (!dsm_control_segment_sane(old_control, mapped_size))
276 {
278 &mapped_address, &mapped_size, LOG);
279 return;
280 }
281
282 /*
283 * OK, the control segment looks basically valid, so we can use it to get
284 * a list of segments that need to be removed.
285 */
286 nitems = old_control->nitems;
287 for (i = 0; i < nitems; ++i)
288 {
289 dsm_handle handle;
290 uint32 refcnt;
291
292 /* If the reference count is 0, the slot is actually unused. */
293 refcnt = old_control->item[i].refcnt;
294 if (refcnt == 0)
295 continue;
296
297 /* If it was using the main shmem area, there is nothing to do. */
298 handle = old_control->item[i].handle;
299 if (is_main_region_dsm_handle(handle))
300 continue;
301
302 /* Log debugging information. */
303 elog(DEBUG2, "cleaning up orphaned dynamic shared memory with ID %u (reference count %u)",
304 handle, refcnt);
305
306 /* Destroy the referenced segment. */
309 }
310
311 /* Destroy the old control segment, too. */
312 elog(DEBUG2,
313 "cleaning up dynamic shared memory control segment with ID %u",
316 &mapped_address, &mapped_size, LOG);
317}
size_t Size
Definition c.h:689
uint32 dsm_handle
Definition dsm_impl.h:55
@ DSM_OP_DESTROY
Definition dsm_impl.h:66
#define LOG
Definition elog.h:32
#define DEBUG1
Definition elog.h:31

References DEBUG1, DEBUG2, dsm_control_segment_sane(), dsm_impl_op(), DSM_OP_ATTACH, DSM_OP_DESTROY, DSM_OP_DETACH, elog, fb(), i, is_main_region_dsm_handle(), LOG, and nitems.

Referenced by PGSharedMemoryCreate().

◆ dsm_control_bytes_needed()

static uint64 dsm_control_bytes_needed ( uint32  nitems)
static

Definition at line 1263 of file dsm.c.

1264{
1265 return offsetof(dsm_control_header, item)
1266 + sizeof(dsm_control_item) * (uint64) nitems;
1267}
uint64_t uint64
Definition c.h:625

References fb(), and 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 1245 of file dsm.c.

1246{
1247 if (mapped_size < offsetof(dsm_control_header, item))
1248 return false; /* Mapped size too short to read header. */
1249 if (control->magic != PG_DYNSHMEM_CONTROL_MAGIC)
1250 return false; /* Magic number doesn't match. */
1251 if (dsm_control_bytes_needed(control->maxitems) > mapped_size)
1252 return false; /* Max item count won't fit in map. */
1253 if (control->nitems > control->maxitems)
1254 return false; /* Overfull. */
1255 return true;
1256}
#define PG_DYNSHMEM_CONTROL_MAGIC
Definition dsm.c:51
static uint64 dsm_control_bytes_needed(uint32 nitems)
Definition dsm.c:1263
uint32 maxitems
Definition dsm.c:95
uint32 magic
Definition dsm.c:93

References dsm_control_bytes_needed(), fb(), 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 524 of file dsm.c.

525{
526 dsm_segment *seg;
527 uint32 i;
529 size_t npages = 0;
530 size_t first_page = 0;
532 bool using_main_dsm_region = false;
533
534 /*
535 * Unsafe in postmaster. It might seem pointless to allow use of dsm in
536 * single user mode, but otherwise some subsystems will need dedicated
537 * single user mode code paths.
538 */
540
541 if (!dsm_init_done)
543
544 /* Create a new segment descriptor. */
545 seg = dsm_create_descriptor();
546
547 /*
548 * Lock the control segment while we try to allocate from the main shared
549 * memory area, if configured.
550 */
552 {
553 npages = size / FPM_PAGE_SIZE;
554 if (size % FPM_PAGE_SIZE > 0)
555 ++npages;
556
558 if (FreePageManagerGet(dsm_main_space_fpm, npages, &first_page))
559 {
560 /* We can carve out a piece of the main shared memory segment. */
561 seg->mapped_address = (char *) dsm_main_space_begin +
562 first_page * FPM_PAGE_SIZE;
563 seg->mapped_size = npages * FPM_PAGE_SIZE;
565 /* We'll choose a handle below. */
566 }
567 }
568
570 {
571 /*
572 * We need to create a new memory segment. Loop until we find an
573 * unused segment identifier.
574 */
577 for (;;)
578 {
579 Assert(seg->mapped_address == NULL && seg->mapped_size == 0);
580 /* Use even numbers only */
582 if (seg->handle == DSM_HANDLE_INVALID) /* Reserve sentinel */
583 continue;
584 if (dsm_impl_op(DSM_OP_CREATE, seg->handle, size, &seg->impl_private,
585 &seg->mapped_address, &seg->mapped_size, ERROR))
586 break;
587 }
589 }
590
591 /* Search the control segment for an unused slot. */
593 for (i = 0; i < nitems; ++i)
594 {
595 if (dsm_control->item[i].refcnt == 0)
596 {
598 {
600 dsm_control->item[i].first_page = first_page;
601 dsm_control->item[i].npages = npages;
602 }
603 else
605 dsm_control->item[i].handle = seg->handle;
606 /* refcnt of 1 triggers destruction, so start at 2 */
607 dsm_control->item[i].refcnt = 2;
609 dsm_control->item[i].pinned = false;
610 seg->control_slot = i;
612 return seg;
613 }
614 }
615
616 /* Verify that we can support an additional mapping. */
618 {
620 FreePageManagerPut(dsm_main_space_fpm, first_page, npages);
624 &seg->mapped_address, &seg->mapped_size, WARNING);
625 if (seg->resowner != NULL)
627 dlist_delete(&seg->node);
628 pfree(seg);
629
630 if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0)
631 return NULL;
634 errmsg("too many dynamic shared memory segments")));
635 }
636
637 /* Enter the handle into a new array slot. */
639 {
641 dsm_control->item[i].first_page = first_page;
642 dsm_control->item[i].npages = npages;
643 }
645 /* refcnt of 1 triggers destruction, so start at 2 */
648 dsm_control->item[nitems].pinned = false;
649 seg->control_slot = nitems;
652
653 return seg;
654}
static void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition dsm.c:175
static dsm_handle make_main_region_dsm_handle(int slot)
Definition dsm.c:1270
#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:121
static void dlist_delete(dlist_node *node)
Definition ilist.h:405
uint32 pg_prng_uint32(pg_prng_state *state)
Definition pg_prng.c:227
pg_prng_state pg_global_prng_state
Definition pg_prng.c:34
bool pinned
Definition dsm.c:87
void * impl_private_pm_handle
Definition dsm.c:86
dlist_node node
Definition dsm.c:69
ResourceOwner resowner
Definition dsm.c:70

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, fb(), 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_ext(), GetNamedDSMSegment(), GetSessionDsmHandle(), InitializeParallelDSM(), make_new_segment(), pa_setup_dsm(), setup_dynamic_shared_memory(), and start_repack_decoding_worker().

◆ dsm_create_descriptor()

static dsm_segment * dsm_create_descriptor ( void  )
static

Definition at line 1209 of file dsm.c.

1210{
1211 dsm_segment *seg;
1212
1215
1218
1219 /* seg->handle must be initialized by the caller */
1221 seg->impl_private = NULL;
1222 seg->mapped_address = NULL;
1223 seg->mapped_size = 0;
1224
1228
1229 slist_init(&seg->on_detach);
1230
1231 return seg;
1232}
static void ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
Definition dsm.c:170
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
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
MemoryContext TopMemoryContext
Definition mcxt.c:166
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition resowner.c:449

References dsm_segment::control_slot, CurrentResourceOwner, dlist_push_head(), dsm_segment_list, fb(), dsm_segment::impl_private, INVALID_CONTROL_SLOT, dsm_segment::mapped_address, dsm_segment::mapped_size, MemoryContextAlloc(), dsm_segment::node, dsm_segment::on_detach, ResourceOwnerEnlarge(), 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 811 of file dsm.c.

812{
813 /*
814 * Invoke registered callbacks. Just in case one of those callbacks
815 * throws a further error that brings us back here, pop the callback
816 * before invoking it, to avoid infinite error recursion. Don't allow
817 * interrupts while running the individual callbacks in non-error code
818 * paths, to avoid leaving cleanup work unfinished if we're interrupted by
819 * a statement timeout or similar.
820 */
822 while (!slist_is_empty(&seg->on_detach))
823 {
824 slist_node *node;
827 Datum arg;
828
829 node = slist_pop_head_node(&seg->on_detach);
831 function = cb->function;
832 arg = cb->arg;
833 pfree(cb);
834
835 function(seg, arg);
836 }
838
839 /*
840 * Try to remove the mapping, if one exists. Normally, there will be, but
841 * maybe not, if we failed partway through a create or attach operation.
842 * We remove the mapping before decrementing the reference count so that
843 * the process that sees a zero reference count can be certain that no
844 * remaining mappings exist. Even if this fails, we pretend that it
845 * works, because retrying is likely to fail in the same way.
846 */
847 if (seg->mapped_address != NULL)
848 {
851 &seg->mapped_address, &seg->mapped_size, WARNING);
852 seg->impl_private = NULL;
853 seg->mapped_address = NULL;
854 seg->mapped_size = 0;
855 }
856
857 /* Reduce reference count, if we previously increased it. */
859 {
860 uint32 refcnt;
861 uint32 control_slot = seg->control_slot;
862
864 Assert(dsm_control->item[control_slot].handle == seg->handle);
865 Assert(dsm_control->item[control_slot].refcnt > 1);
866 refcnt = --dsm_control->item[control_slot].refcnt;
869
870 /* If new reference count is 1, try to destroy the segment. */
871 if (refcnt == 1)
872 {
873 /* A pinned segment should never reach 1. */
874 Assert(!dsm_control->item[control_slot].pinned);
875
876 /*
877 * If we fail to destroy the segment here, or are killed before we
878 * finish doing so, the reference count will remain at 1, which
879 * will mean that nobody else can attach to the segment. At
880 * postmaster shutdown time, or when a new postmaster is started
881 * after a hard kill, another attempt will be made to remove the
882 * segment.
883 *
884 * The main case we're worried about here is being killed by a
885 * signal before we can finish removing the segment. In that
886 * case, it's important to be sure that the segment still gets
887 * removed. If we actually fail to remove the segment for some
888 * other reason, the postmaster may not have any better luck than
889 * we did. There's not much we can do about that, though.
890 */
893 &seg->mapped_address, &seg->mapped_size, WARNING))
894 {
898 dsm_control->item[control_slot].first_page,
899 dsm_control->item[control_slot].npages);
900 Assert(dsm_control->item[control_slot].handle == seg->handle);
901 Assert(dsm_control->item[control_slot].refcnt == 1);
902 dsm_control->item[control_slot].refcnt = 0;
904 }
905 }
906 }
907
908 /* Clean up our remaining backend-private data structures. */
909 if (seg->resowner != NULL)
911 dlist_delete(&seg->node);
912 pfree(seg);
913}
void(* on_dsm_detach_callback)(dsm_segment *, Datum arg)
Definition dsm.h:51
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:138
#define HOLD_INTERRUPTS()
Definition miscadmin.h:136
uint64_t Datum
Definition postgres.h:70

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, fb(), dsm_control_item::first_page, FreePageManagerPut(), dsm_segment_detach_callback::function, 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(), dsa_get_total_size_from_handle(), dsm_attach(), dsm_backend_shutdown(), dsm_detach_all(), pa_free_worker_info(), pa_shutdown(), ParallelWorkerShutdown(), RepackWorkerShutdown(), ResOwnerReleaseDSM(), stop_repack_decoding_worker(), test_shm_mq(), test_shm_mq_main(), and test_shm_mq_pipelined().

◆ dsm_detach_all()

◆ dsm_find_mapping()

dsm_segment * dsm_find_mapping ( dsm_handle  handle)

Definition at line 1084 of file dsm.c.

1085{
1086 dlist_iter iter;
1087 dsm_segment *seg;
1088
1090 {
1091 seg = dlist_container(dsm_segment, node, iter.cur);
1092 if (seg->handle == handle)
1093 return seg;
1094 }
1095
1096 return NULL;
1097}

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

Referenced by dsa_get_total_size_from_handle(), dsa_is_attached(), and GetNamedDSMSegment().

◆ dsm_main_space_init()

static void dsm_main_space_init ( void arg)
static

Definition at line 494 of file dsm.c.

495{
497 size_t first_page = 0;
498 size_t pages;
499
500 if (dsm_main_space_size == 0)
501 return;
502
503 /* Reserve space for the FreePageManager. */
504 while (first_page * FPM_PAGE_SIZE < sizeof(FreePageManager))
505 ++first_page;
506
507 /* Initialize it and give it all the rest of the space. */
509 pages = (dsm_main_space_size / FPM_PAGE_SIZE) - first_page;
510 FreePageManagerPut(fpm, first_page, pages);
511}
static size_t dsm_main_space_size
Definition dsm.c:113
void FreePageManagerInitialize(FreePageManager *fpm, char *base)
Definition freepage.c:183

References dsm_main_space_begin, dsm_main_space_size, FPM_PAGE_SIZE, FreePageManagerInitialize(), and FreePageManagerPut().

◆ dsm_main_space_request()

static void dsm_main_space_request ( void arg)
static

Definition at line 480 of file dsm.c.

481{
483
484 if (dsm_main_space_size == 0)
485 return;
486
487 ShmemRequestStruct(.name = "Preallocated DSM",
488 .size = dsm_main_space_size,
489 .ptr = &dsm_main_space_begin,
490 );
491}
int min_dynamic_shared_memory
Definition dsm_impl.c:116
#define ShmemRequestStruct(...)
Definition shmem.h:176
const char * name

References dsm_main_space_begin, dsm_main_space_size, fb(), min_dynamic_shared_memory, name, and ShmemRequestStruct.

◆ dsm_pin_mapping()

void dsm_pin_mapping ( dsm_segment seg)

Definition at line 923 of file dsm.c.

924{
925 if (seg->resowner != NULL)
926 {
928 seg->resowner = NULL;
929 }
930}

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

Referenced by AttachSession(), dsa_pin_mapping(), GetNamedDSMSegment(), and GetSessionDsmHandle().

◆ dsm_pin_segment()

void dsm_pin_segment ( dsm_segment seg)

Definition at line 963 of file dsm.c.

964{
965 void *handle = NULL;
966
967 /*
968 * Bump reference count for this segment in shared memory. This will
969 * ensure that even if there is no session which is attached to this
970 * segment, it will remain until postmaster shutdown or an explicit call
971 * to unpin.
972 */
975 elog(ERROR, "cannot pin a segment that is already pinned");
977 dsm_impl_pin_segment(seg->handle, seg->impl_private, &handle);
978 dsm_control->item[seg->control_slot].pinned = true;
982}
void dsm_impl_pin_segment(dsm_handle handle, void *impl_private, void **impl_private_pm_handle)
Definition dsm_impl.c:964

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

Referenced by dsa_create_ext(), GetNamedDSMSegment(), and make_new_segment().

◆ dsm_postmaster_shutdown()

static void dsm_postmaster_shutdown ( int  code,
Datum  arg 
)
static

Definition at line 368 of file dsm.c.

369{
371 uint32 i;
374 void *junk_impl_private = NULL;
377
378 /*
379 * If some other backend exited uncleanly, it might have corrupted the
380 * control segment while it was dying. In that case, we warn and ignore
381 * the contents of the control segment. This may end up leaving behind
382 * stray shared memory segments, but there's not much we can do about that
383 * if the metadata is gone.
384 */
387 {
388 ereport(LOG,
389 (errmsg("dynamic shared memory control segment is corrupt")));
390 return;
391 }
392
393 /* Remove any remaining segments. */
394 for (i = 0; i < nitems; ++i)
395 {
396 dsm_handle handle;
397
398 /* If the reference count is 0, the slot is actually unused. */
399 if (dsm_control->item[i].refcnt == 0)
400 continue;
401
402 handle = dsm_control->item[i].handle;
403 if (is_main_region_dsm_handle(handle))
404 continue;
405
406 /* Log debugging information. */
407 elog(DEBUG2, "cleaning up orphaned dynamic shared memory with ID %u",
408 handle);
409
410 /* Destroy the segment. */
413 }
414
415 /* Remove the control segment itself. */
416 elog(DEBUG2,
417 "cleaning up dynamic shared memory control segment with ID %u",
424 shim->dsm_control = 0;
425}
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332

References arg, DatumGetPointer(), DEBUG2, 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, fb(), 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 187 of file dsm.c.

188{
190 uint32 maxitems;
191 Size segsize;
192
194
195 /*
196 * If we're using the mmap implementations, clean up any leftovers.
197 * Cleanup isn't needed on Windows, and happens earlier in startup for
198 * POSIX and System V shared memory, via a direct call to
199 * dsm_cleanup_using_control_segment.
200 */
203
204 /* Determine size for new control segment. */
205 maxitems = PG_DYNSHMEM_FIXED_SLOTS
207 elog(DEBUG2, "dynamic shared memory system will support %u segments",
208 maxitems);
209 segsize = dsm_control_bytes_needed(maxitems);
210
211 /*
212 * Loop until we find an unused identifier for the new control segment. We
213 * sometimes use DSM_HANDLE_INVALID as a sentinel value indicating "no
214 * control segment", so avoid generating that value for a real handle.
215 */
216 for (;;)
217 {
220 /* Use even numbers only */
223 continue;
227 break;
228 }
231 elog(DEBUG2,
232 "created dynamic shared memory control segment %u (%zu bytes)",
233 dsm_control_handle, segsize);
234 shim->dsm_control = dsm_control_handle;
235
236 /* Initialize control segment. */
238 dsm_control->nitems = 0;
239 dsm_control->maxitems = maxitems;
240}
static void dsm_postmaster_shutdown(int code, Datum arg)
Definition dsm.c:368
#define PG_DYNSHMEM_SLOTS_PER_BACKEND
Definition dsm.c:54
#define PG_DYNSHMEM_FIXED_SLOTS
Definition dsm.c:53
static void dsm_cleanup_for_mmap(void)
Definition dsm.c:330
int dynamic_shared_memory_type
Definition dsm_impl.c:113
#define DSM_IMPL_MMAP
Definition dsm_impl.h:20
int MaxBackends
Definition globals.c:149
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
#define PointerGetDatum(X)
Definition postgres.h:354

References Assert, DEBUG2, dsm_cleanup_for_mmap(), 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, fb(), 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 1113 of file dsm.c.

1114{
1115 Assert(seg->mapped_address != NULL);
1116 return seg->mapped_size;
1117}

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

◆ dsm_unpin_mapping()

◆ dsm_unpin_segment()

void dsm_unpin_segment ( dsm_handle  handle)

Definition at line 996 of file dsm.c.

997{
998 uint32 control_slot = INVALID_CONTROL_SLOT;
999 bool destroy = false;
1000 uint32 i;
1001
1002 /* Find the control slot for the given handle. */
1004 for (i = 0; i < dsm_control->nitems; ++i)
1005 {
1006 /* Skip unused slots and segments that are concurrently going away. */
1007 if (dsm_control->item[i].refcnt <= 1)
1008 continue;
1009
1010 /* If we've found our handle, we can stop searching. */
1011 if (dsm_control->item[i].handle == handle)
1012 {
1013 control_slot = i;
1014 break;
1015 }
1016 }
1017
1018 /*
1019 * We should definitely have found the slot, and it should not already be
1020 * in the process of going away, because this function should only be
1021 * called on a segment which is pinned.
1022 */
1023 if (control_slot == INVALID_CONTROL_SLOT)
1024 elog(ERROR, "cannot unpin unknown segment handle");
1025 if (!dsm_control->item[control_slot].pinned)
1026 elog(ERROR, "cannot unpin a segment that is not pinned");
1027 Assert(dsm_control->item[control_slot].refcnt > 1);
1028
1029 /*
1030 * Allow implementation-specific code to run. We have to do this before
1031 * releasing the lock, because impl_private_pm_handle may get modified by
1032 * dsm_impl_unpin_segment.
1033 */
1034 if (!is_main_region_dsm_handle(handle))
1036 &dsm_control->item[control_slot].impl_private_pm_handle);
1037
1038 /* Note that 1 means no references (0 means unused slot). */
1039 if (--dsm_control->item[control_slot].refcnt == 1)
1040 destroy = true;
1041 dsm_control->item[control_slot].pinned = false;
1042
1043 /* Now we can release the lock. */
1045
1046 /* Clean up resources if that was the last reference. */
1047 if (destroy)
1048 {
1049 void *junk_impl_private = NULL;
1050 void *junk_mapped_address = NULL;
1052
1053 /*
1054 * For an explanation of how error handling works in this case, see
1055 * comments in dsm_detach. Note that if we reach this point, the
1056 * current process certainly does not have the segment mapped, because
1057 * if it did, the reference count would have still been greater than 1
1058 * even after releasing the reference count held by the pin. The fact
1059 * that there can't be a dsm_segment for this handle makes it OK to
1060 * pass the mapped size, mapped address, and private data as NULL
1061 * here.
1062 */
1063 if (is_main_region_dsm_handle(handle) ||
1066 {
1068 if (is_main_region_dsm_handle(handle))
1070 dsm_control->item[control_slot].first_page,
1071 dsm_control->item[control_slot].npages);
1072 Assert(dsm_control->item[control_slot].handle == handle);
1073 Assert(dsm_control->item[control_slot].refcnt == 1);
1074 dsm_control->item[control_slot].refcnt = 0;
1076 }
1077 }
1078}
void dsm_impl_unpin_segment(dsm_handle handle, void **impl_private)
Definition dsm_impl.c:1015

References Assert, dsm_control, dsm_impl_op(), dsm_impl_unpin_segment(), dsm_main_space_begin, DSM_OP_DESTROY, elog, ERROR, fb(), 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 1289 of file dsm.c.

1290{
1291 return handle & 1;
1292}

Referenced by dsm_attach(), dsm_cleanup_using_control_segment(), dsm_create(), dsm_detach(), dsm_pin_segment(), 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 1270 of file dsm.c.

1271{
1272 dsm_handle handle;
1273
1274 /*
1275 * We need to create a handle that doesn't collide with any existing extra
1276 * segment created by dsm_impl_op(), so we'll make it odd. It also
1277 * mustn't collide with any other main area pseudo-segment, so we'll
1278 * include the slot number in some of the bits. We also want to make an
1279 * effort to avoid newly created and recently destroyed handles from being
1280 * confused, so we'll make the rest of the bits random.
1281 */
1282 handle = 1;
1283 handle |= slot << 1;
1285 return handle;
1286}
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 1178 of file dsm.c.

1179{
1180 dlist_iter iter;
1181
1183 {
1184 dsm_segment *seg = dlist_container(dsm_segment, node, iter.cur);
1185
1186 /* Throw away explicit on-detach actions one by one. */
1187 while (!slist_is_empty(&seg->on_detach))
1188 {
1189 slist_node *node;
1191
1192 node = slist_pop_head_node(&seg->on_detach);
1194 pfree(cb);
1195 }
1196
1197 /*
1198 * Decrementing the reference count is a sort of implicit on-detach
1199 * action; make sure we don't do that, either.
1200 */
1202 }
1203}

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

◆ ResourceOwnerForgetDSM()

static void ResourceOwnerForgetDSM ( ResourceOwner  owner,
dsm_segment seg 
)
inlinestatic

Definition at line 175 of file dsm.c.

176{
178}
static const ResourceOwnerDesc dsm_resowner_desc
Definition dsm.c:159
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition resowner.c:561

References dsm_resowner_desc, PointerGetDatum, and ResourceOwnerForget().

Referenced by dsm_create(), dsm_detach(), and dsm_pin_mapping().

◆ ResourceOwnerRememberDSM()

static void ResourceOwnerRememberDSM ( ResourceOwner  owner,
dsm_segment seg 
)
inlinestatic

Definition at line 170 of file dsm.c.

171{
173}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition resowner.c:521

References dsm_resowner_desc, PointerGetDatum, and ResourceOwnerRemember().

Referenced by dsm_create_descriptor(), and dsm_unpin_mapping().

◆ ResOwnerPrintDSM()

static char * ResOwnerPrintDSM ( Datum  res)
static

Definition at line 1305 of file dsm.c.

1306{
1307 dsm_segment *seg = (dsm_segment *) DatumGetPointer(res);
1308
1309 return psprintf("dynamic shared memory segment %u",
1310 dsm_segment_handle(seg));
1311}
dsm_handle dsm_segment_handle(dsm_segment *seg)
Definition dsm.c:1131
char * psprintf(const char *fmt,...)
Definition psprintf.c:43

References DatumGetPointer(), dsm_segment_handle(), and psprintf().

◆ ResOwnerReleaseDSM()

static void ResOwnerReleaseDSM ( Datum  res)
static

Definition at line 1297 of file dsm.c.

1298{
1299 dsm_segment *seg = (dsm_segment *) DatumGetPointer(res);
1300
1301 seg->resowner = NULL;
1302 dsm_detach(seg);
1303}

References DatumGetPointer(), dsm_detach(), fb(), and dsm_segment::resowner.

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 109 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

◆ dsm_main_space_size

size_t dsm_main_space_size
static

Definition at line 113 of file dsm.c.

Referenced by dsm_main_space_init(), and dsm_main_space_request().

◆ dsm_resowner_desc

const ResourceOwnerDesc dsm_resowner_desc
static
Initial value:
=
{
.name = "dynamic shared memory segment",
.release_priority = RELEASE_PRIO_DSMS,
.ReleaseResource = ResOwnerReleaseDSM,
.DebugPrint = ResOwnerPrintDSM
}
static char * ResOwnerPrintDSM(Datum res)
Definition dsm.c:1305
static void ResOwnerReleaseDSM(Datum res)
Definition dsm.c:1297
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition resowner.h:54
#define RELEASE_PRIO_DSMS
Definition resowner.h:65

Definition at line 159 of file dsm.c.

160{
161 .name = "dynamic shared memory segment",
162 .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
163 .release_priority = RELEASE_PRIO_DSMS,
164 .ReleaseResource = ResOwnerReleaseDSM,
165 .DebugPrint = ResOwnerPrintDSM
166};

Referenced by ResourceOwnerForgetDSM(), and ResourceOwnerRememberDSM().

◆ dsm_segment_list

dlist_head dsm_segment_list = DLIST_STATIC_INIT(dsm_segment_list)
static

◆ dsm_shmem_callbacks

const ShmemCallbacks dsm_shmem_callbacks
Initial value:
= {
.request_fn = dsm_main_space_request,
.init_fn = dsm_main_space_init,
}
static void dsm_main_space_init(void *arg)
Definition dsm.c:494
static void dsm_main_space_request(void *arg)
Definition dsm.c:480

Definition at line 118 of file dsm.c.

118 {
119 .request_fn = dsm_main_space_request,
120 .init_fn = dsm_main_space_init,
121};