PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 "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 ResOwnerReleaseDSM (Datum res)
 
static char * ResOwnerPrintDSM (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)
 
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
 
static const ResourceOwnerDesc dsm_resowner_desc
 

Macro Definition Documentation

◆ INVALID_CONTROL_SLOT

#define INVALID_CONTROL_SLOT   ((uint32) -1)

Definition at line 55 of file dsm.c.

◆ PG_DYNSHMEM_CONTROL_MAGIC

#define PG_DYNSHMEM_CONTROL_MAGIC   0x9a503d32

Definition at line 50 of file dsm.c.

◆ PG_DYNSHMEM_FIXED_SLOTS

#define PG_DYNSHMEM_FIXED_SLOTS   64

Definition at line 52 of file dsm.c.

◆ PG_DYNSHMEM_SLOTS_PER_BACKEND

#define PG_DYNSHMEM_SLOTS_PER_BACKEND   5

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

1149{
1150 slist_mutable_iter iter;
1151
1152 slist_foreach_modify(iter, &seg->on_detach)
1153 {
1155
1157 if (cb->function == function && cb->arg == arg)
1158 {
1159 slist_delete_current(&iter);
1160 pfree(cb);
1161 break;
1162 }
1163 }
1164}
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:2150
on_exit_nicely_callback function
void * arg
on_dsm_detach_callback function
Definition: dsm.c:60
slist_head on_detach
Definition: dsm.c:75
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 665 of file dsm.c.

666{
667 dsm_segment *seg;
668 dlist_iter iter;
669 uint32 i;
671
672 /* Unsafe in postmaster (and pointless in a stand-alone backend). */
674
675 if (!dsm_init_done)
677
678 /*
679 * Since this is just a debugging cross-check, we could leave it out
680 * altogether, or include it only in assert-enabled builds. But since the
681 * list of attached segments should normally be very short, let's include
682 * it always for right now.
683 *
684 * If you're hitting this error, you probably want to attempt to find an
685 * existing mapping via dsm_find_mapping() before calling dsm_attach() to
686 * create a new one.
687 */
689 {
690 seg = dlist_container(dsm_segment, node, iter.cur);
691 if (seg->handle == h)
692 elog(ERROR, "can't attach the same segment more than once");
693 }
694
695 /* Create a new segment descriptor. */
696 seg = dsm_create_descriptor();
697 seg->handle = h;
698
699 /* Bump reference count for this segment in shared memory. */
700 LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
702 for (i = 0; i < nitems; ++i)
703 {
704 /*
705 * If the reference count is 0, the slot is actually unused. If the
706 * reference count is 1, the slot is still in use, but the segment is
707 * in the process of going away; even if the handle matches, another
708 * slot may already have started using the same handle value by
709 * coincidence so we have to keep searching.
710 */
711 if (dsm_control->item[i].refcnt <= 1)
712 continue;
713
714 /* If the handle doesn't match, it's not the slot we want. */
715 if (dsm_control->item[i].handle != seg->handle)
716 continue;
717
718 /* Otherwise we've found a match. */
720 seg->control_slot = i;
722 {
723 seg->mapped_address = (char *) dsm_main_space_begin +
726 }
727 break;
728 }
729 LWLockRelease(DynamicSharedMemoryControlLock);
730
731 /*
732 * If we didn't find the handle we're looking for in the control segment,
733 * it probably means that everyone else who had it mapped, including the
734 * original creator, died before we got to this point. It's up to the
735 * caller to decide what to do about that.
736 */
738 {
739 dsm_detach(seg);
740 return NULL;
741 }
742
743 /* Here's where we actually try to map the segment. */
746 &seg->mapped_address, &seg->mapped_size, ERROR);
747
748 return seg;
749}
uint32_t uint32
Definition: c.h:502
static void dsm_backend_startup(void)
Definition: dsm.c:423
static void * dsm_main_space_begin
Definition: dsm.c:111
void dsm_detach(dsm_segment *seg)
Definition: dsm.c:803
static dlist_head dsm_segment_list
Definition: dsm.c:130
static bool dsm_init_done
Definition: dsm.c:108
static dsm_control_header * dsm_control
Definition: dsm.c:140
static dsm_segment * dsm_create_descriptor(void)
Definition: dsm.c:1201
#define INVALID_CONTROL_SLOT
Definition: dsm.c:55
static bool is_main_region_dsm_handle(dsm_handle handle)
Definition: dsm.c:1281
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 elog(elevel,...)
Definition: elog.h:225
#define FPM_PAGE_SIZE
Definition: freepage.h:30
bool IsUnderPostmaster
Definition: globals.c:121
Assert(PointerIsAligned(start, uint64))
#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:1182
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1902
@ LW_EXCLUSIVE
Definition: lwlock.h:114
dlist_node * cur
Definition: ilist.h:179
uint32 nitems
Definition: dsm.c:93
dsm_control_item item[FLEXIBLE_ARRAY_MEMBER]
Definition: dsm.c:95
size_t npages
Definition: dsm.c:84
dsm_handle handle
Definition: dsm.c:81
size_t first_page
Definition: dsm.c:83
uint32 refcnt
Definition: dsm.c:82
uint32 control_slot
Definition: dsm.c:71
dsm_handle handle
Definition: dsm.c:70
Size mapped_size
Definition: dsm.c:74
void * impl_private
Definition: dsm.c:72
void * mapped_address
Definition: dsm.c:73

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

◆ dsm_backend_shutdown()

void dsm_backend_shutdown ( void  )

Definition at line 757 of file dsm.c.

758{
760 {
761 dsm_segment *seg;
762
764 dsm_detach(seg);
765 }
766}
#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 423 of file dsm.c.

424{
425#ifdef EXEC_BACKEND
427 {
428 void *control_address = NULL;
429
430 /* Attach control segment. */
433 &dsm_control_impl_private, &control_address,
435 dsm_control = control_address;
436 /* If control segment doesn't look sane, something is badly wrong. */
438 {
440 &dsm_control_impl_private, &control_address,
443 (errcode(ERRCODE_INTERNAL_ERROR),
444 errmsg("dynamic shared memory control segment is not valid")));
445 }
446 }
447#endif
448
449 dsm_init_done = true;
450}
static dsm_handle dsm_control_handle
Definition: dsm.c:139
static Size dsm_control_mapped_size
Definition: dsm.c:141
static bool dsm_control_segment_sane(dsm_control_header *control, Size mapped_size)
Definition: dsm.c:1237
static void * dsm_control_impl_private
Definition: dsm.c:142
@ DSM_OP_DETACH
Definition: dsm_impl.h:65
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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 320 of file dsm.c.

321{
322 DIR *dir;
323 struct dirent *dent;
324
325 /* Scan the directory for something with a name of the correct format. */
327
328 while ((dent = ReadDir(dir, PG_DYNSHMEM_DIR)) != NULL)
329 {
330 if (strncmp(dent->d_name, PG_DYNSHMEM_MMAP_FILE_PREFIX,
331 strlen(PG_DYNSHMEM_MMAP_FILE_PREFIX)) == 0)
332 {
333 char buf[MAXPGPATH + sizeof(PG_DYNSHMEM_DIR)];
334
335 snprintf(buf, sizeof(buf), PG_DYNSHMEM_DIR "/%s", dent->d_name);
336
337 elog(DEBUG2, "removing file \"%s\"", buf);
338
339 /* We found a matching file; so remove it. */
340 if (unlink(buf) != 0)
343 errmsg("could not remove file \"%s\": %m", buf)));
344 }
345 }
346
347 /* Cleanup complete. */
348 FreeDir(dir);
349}
#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:877
#define DEBUG2
Definition: elog.h:29
int FreeDir(DIR *dir)
Definition: fd.c:3025
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2907
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2973
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:239
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 238 of file dsm.c.

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

1256{
1257 return offsetof(dsm_control_header, item)
1258 + sizeof(dsm_control_item) * (uint64) nitems;
1259}
uint64_t uint64
Definition: c.h:503
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 1237 of file dsm.c.

1238{
1239 if (mapped_size < offsetof(dsm_control_header, item))
1240 return false; /* Mapped size too short to read header. */
1241 if (control->magic != PG_DYNSHMEM_CONTROL_MAGIC)
1242 return false; /* Magic number doesn't match. */
1243 if (dsm_control_bytes_needed(control->maxitems) > mapped_size)
1244 return false; /* Max item count won't fit in map. */
1245 if (control->nitems > control->maxitems)
1246 return false; /* Overfull. */
1247 return true;
1248}
#define PG_DYNSHMEM_CONTROL_MAGIC
Definition: dsm.c:50
static uint64 dsm_control_bytes_needed(uint32 nitems)
Definition: dsm.c:1255
uint32 maxitems
Definition: dsm.c:94
uint32 magic
Definition: dsm.c:92

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

517{
518 dsm_segment *seg;
519 uint32 i;
521 size_t npages = 0;
522 size_t first_page = 0;
523 FreePageManager *dsm_main_space_fpm = dsm_main_space_begin;
524 bool using_main_dsm_region = false;
525
526 /*
527 * Unsafe in postmaster. It might seem pointless to allow use of dsm in
528 * single user mode, but otherwise some subsystems will need dedicated
529 * single user mode code paths.
530 */
532
533 if (!dsm_init_done)
535
536 /* Create a new segment descriptor. */
537 seg = dsm_create_descriptor();
538
539 /*
540 * Lock the control segment while we try to allocate from the main shared
541 * memory area, if configured.
542 */
543 if (dsm_main_space_fpm)
544 {
545 npages = size / FPM_PAGE_SIZE;
546 if (size % FPM_PAGE_SIZE > 0)
547 ++npages;
548
549 LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
550 if (FreePageManagerGet(dsm_main_space_fpm, npages, &first_page))
551 {
552 /* We can carve out a piece of the main shared memory segment. */
553 seg->mapped_address = (char *) dsm_main_space_begin +
554 first_page * FPM_PAGE_SIZE;
555 seg->mapped_size = npages * FPM_PAGE_SIZE;
556 using_main_dsm_region = true;
557 /* We'll choose a handle below. */
558 }
559 }
560
561 if (!using_main_dsm_region)
562 {
563 /*
564 * We need to create a new memory segment. Loop until we find an
565 * unused segment identifier.
566 */
567 if (dsm_main_space_fpm)
568 LWLockRelease(DynamicSharedMemoryControlLock);
569 for (;;)
570 {
571 Assert(seg->mapped_address == NULL && seg->mapped_size == 0);
572 /* Use even numbers only */
574 if (seg->handle == DSM_HANDLE_INVALID) /* Reserve sentinel */
575 continue;
576 if (dsm_impl_op(DSM_OP_CREATE, seg->handle, size, &seg->impl_private,
577 &seg->mapped_address, &seg->mapped_size, ERROR))
578 break;
579 }
580 LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
581 }
582
583 /* Search the control segment for an unused slot. */
585 for (i = 0; i < nitems; ++i)
586 {
587 if (dsm_control->item[i].refcnt == 0)
588 {
589 if (using_main_dsm_region)
590 {
592 dsm_control->item[i].first_page = first_page;
593 dsm_control->item[i].npages = npages;
594 }
595 else
597 dsm_control->item[i].handle = seg->handle;
598 /* refcnt of 1 triggers destruction, so start at 2 */
599 dsm_control->item[i].refcnt = 2;
601 dsm_control->item[i].pinned = false;
602 seg->control_slot = i;
603 LWLockRelease(DynamicSharedMemoryControlLock);
604 return seg;
605 }
606 }
607
608 /* Verify that we can support an additional mapping. */
610 {
611 if (using_main_dsm_region)
612 FreePageManagerPut(dsm_main_space_fpm, first_page, npages);
613 LWLockRelease(DynamicSharedMemoryControlLock);
614 if (!using_main_dsm_region)
616 &seg->mapped_address, &seg->mapped_size, WARNING);
617 if (seg->resowner != NULL)
619 dlist_delete(&seg->node);
620 pfree(seg);
621
622 if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0)
623 return NULL;
625 (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
626 errmsg("too many dynamic shared memory segments")));
627 }
628
629 /* Enter the handle into a new array slot. */
630 if (using_main_dsm_region)
631 {
633 dsm_control->item[i].first_page = first_page;
634 dsm_control->item[i].npages = npages;
635 }
637 /* refcnt of 1 triggers destruction, so start at 2 */
640 dsm_control->item[nitems].pinned = false;
641 seg->control_slot = nitems;
643 LWLockRelease(DynamicSharedMemoryControlLock);
644
645 return seg;
646}
static void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg)
Definition: dsm.c:165
static dsm_handle make_main_region_dsm_handle(int slot)
Definition: dsm.c:1262
#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:120
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:86
void * impl_private_pm_handle
Definition: dsm.c:85
dlist_node node
Definition: dsm.c:68
ResourceOwner resowner
Definition: dsm.c:69

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_ext(), GetNamedDSMSegment(), 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 1201 of file dsm.c.

1202{
1203 dsm_segment *seg;
1204
1207
1210
1211 /* seg->handle must be initialized by the caller */
1213 seg->impl_private = NULL;
1214 seg->mapped_address = NULL;
1215 seg->mapped_size = 0;
1216
1220
1221 slist_init(&seg->on_detach);
1222
1223 return seg;
1224}
static void ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg)
Definition: dsm.c:160
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:1260
MemoryContext TopMemoryContext
Definition: mcxt.c:165
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:452

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

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

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, 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(), ResOwnerReleaseDSM(), test_shm_mq(), test_shm_mq_main(), and test_shm_mq_pipelined().

◆ dsm_detach_all()

void dsm_detach_all ( void  )

Definition at line 775 of file dsm.c.

776{
777 void *control_address = dsm_control;
778
780 {
781 dsm_segment *seg;
782
784 dsm_detach(seg);
785 }
786
787 if (control_address != NULL)
789 &dsm_control_impl_private, &control_address,
791}

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

◆ dsm_estimate_size()

size_t dsm_estimate_size ( void  )

Definition at line 470 of file dsm.c.

471{
472 return 1024 * 1024 * (size_t) min_dynamic_shared_memory;
473}
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 1076 of file dsm.c.

1077{
1078 dlist_iter iter;
1079 dsm_segment *seg;
1080
1082 {
1083 seg = dlist_container(dsm_segment, node, iter.cur);
1084 if (seg->handle == handle)
1085 return seg;
1086 }
1087
1088 return NULL;
1089}

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

Referenced by GetNamedDSMSegment().

◆ dsm_pin_mapping()

void dsm_pin_mapping ( dsm_segment seg)

Definition at line 915 of file dsm.c.

916{
917 if (seg->resowner != NULL)
918 {
920 seg->resowner = NULL;
921 }
922}

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

956{
957 void *handle = NULL;
958
959 /*
960 * Bump reference count for this segment in shared memory. This will
961 * ensure that even if there is no session which is attached to this
962 * segment, it will remain until postmaster shutdown or an explicit call
963 * to unpin.
964 */
965 LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE);
967 elog(ERROR, "cannot pin a segment that is already pinned");
969 dsm_impl_pin_segment(seg->handle, seg->impl_private, &handle);
970 dsm_control->item[seg->control_slot].pinned = true;
973 LWLockRelease(DynamicSharedMemoryControlLock);
974}
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, 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 358 of file dsm.c.

359{
361 uint32 i;
362 void *dsm_control_address;
363 void *junk_mapped_address = NULL;
364 void *junk_impl_private = NULL;
365 Size junk_mapped_size = 0;
367
368 /*
369 * If some other backend exited uncleanly, it might have corrupted the
370 * control segment while it was dying. In that case, we warn and ignore
371 * the contents of the control segment. This may end up leaving behind
372 * stray shared memory segments, but there's not much we can do about that
373 * if the metadata is gone.
374 */
377 {
378 ereport(LOG,
379 (errmsg("dynamic shared memory control segment is corrupt")));
380 return;
381 }
382
383 /* Remove any remaining segments. */
384 for (i = 0; i < nitems; ++i)
385 {
386 dsm_handle handle;
387
388 /* If the reference count is 0, the slot is actually unused. */
389 if (dsm_control->item[i].refcnt == 0)
390 continue;
391
392 handle = dsm_control->item[i].handle;
393 if (is_main_region_dsm_handle(handle))
394 continue;
395
396 /* Log debugging information. */
397 elog(DEBUG2, "cleaning up orphaned dynamic shared memory with ID %u",
398 handle);
399
400 /* Destroy the segment. */
401 dsm_impl_op(DSM_OP_DESTROY, handle, 0, &junk_impl_private,
402 &junk_mapped_address, &junk_mapped_size, LOG);
403 }
404
405 /* Remove the control segment itself. */
406 elog(DEBUG2,
407 "cleaning up dynamic shared memory control segment with ID %u",
409 dsm_control_address = dsm_control;
411 &dsm_control_impl_private, &dsm_control_address,
413 dsm_control = dsm_control_address;
414 shim->dsm_control = 0;
415}
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
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 177 of file dsm.c.

178{
179 void *dsm_control_address = NULL;
180 uint32 maxitems;
181 Size segsize;
182
184
185 /*
186 * If we're using the mmap implementations, clean up any leftovers.
187 * Cleanup isn't needed on Windows, and happens earlier in startup for
188 * POSIX and System V shared memory, via a direct call to
189 * dsm_cleanup_using_control_segment.
190 */
193
194 /* Determine size for new control segment. */
195 maxitems = PG_DYNSHMEM_FIXED_SLOTS
197 elog(DEBUG2, "dynamic shared memory system will support %u segments",
198 maxitems);
199 segsize = dsm_control_bytes_needed(maxitems);
200
201 /*
202 * Loop until we find an unused identifier for the new control segment. We
203 * sometimes use DSM_HANDLE_INVALID as a sentinel value indicating "no
204 * control segment", so avoid generating that value for a real handle.
205 */
206 for (;;)
207 {
208 Assert(dsm_control_address == NULL);
210 /* Use even numbers only */
213 continue;
215 &dsm_control_impl_private, &dsm_control_address,
217 break;
218 }
219 dsm_control = dsm_control_address;
221 elog(DEBUG2,
222 "created dynamic shared memory control segment %u (%zu bytes)",
223 dsm_control_handle, segsize);
225
226 /* Initialize control segment. */
228 dsm_control->nitems = 0;
229 dsm_control->maxitems = maxitems;
230}
static void dsm_postmaster_shutdown(int code, Datum arg)
Definition: dsm.c:358
#define PG_DYNSHMEM_SLOTS_PER_BACKEND
Definition: dsm.c:53
#define PG_DYNSHMEM_FIXED_SLOTS
Definition: dsm.c:52
static void dsm_cleanup_for_mmap(void)
Definition: dsm.c:320
int dynamic_shared_memory_type
Definition: dsm_impl.c:112
#define DSM_IMPL_MMAP
Definition: dsm_impl.h:20
int MaxBackends
Definition: globals.c:147
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:365
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327

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

1106{
1107 Assert(seg->mapped_address != NULL);
1108 return seg->mapped_size;
1109}

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

◆ dsm_shmem_init()

void dsm_shmem_init ( void  )

Definition at line 479 of file dsm.c.

480{
481 size_t size = dsm_estimate_size();
482 bool found;
483
484 if (size == 0)
485 return;
486
487 dsm_main_space_begin = ShmemInitStruct("Preallocated DSM", size, &found);
488 if (!found)
489 {
491 size_t first_page = 0;
492 size_t pages;
493
494 /* Reserve space for the FreePageManager. */
495 while (first_page * FPM_PAGE_SIZE < sizeof(FreePageManager))
496 ++first_page;
497
498 /* Initialize it and give it all the rest of the space. */
500 pages = (size / FPM_PAGE_SIZE) - first_page;
501 FreePageManagerPut(fpm, first_page, pages);
502 }
503}
size_t dsm_estimate_size(void)
Definition: dsm.c:470
void FreePageManagerInitialize(FreePageManager *fpm, char *base)
Definition: freepage.c:183
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387

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

Referenced by CreateOrAttachShmemStructs().

◆ dsm_unpin_mapping()

void dsm_unpin_mapping ( dsm_segment seg)

◆ dsm_unpin_segment()

void dsm_unpin_segment ( dsm_handle  handle)

Definition at line 988 of file dsm.c.

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

1282{
1283 return handle & 1;
1284}

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

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

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

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

166{
168}
static const ResourceOwnerDesc dsm_resowner_desc
Definition: dsm.c:149
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:564

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

161{
163}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:524

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

1298{
1299 dsm_segment *seg = (dsm_segment *) DatumGetPointer(res);
1300
1301 return psprintf("dynamic shared memory segment %u",
1302 dsm_segment_handle(seg));
1303}
dsm_handle dsm_segment_handle(dsm_segment *seg)
Definition: dsm.c:1123
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 1289 of file dsm.c.

1290{
1291 dsm_segment *seg = (dsm_segment *) DatumGetPointer(res);
1292
1293 seg->resowner = NULL;
1294 dsm_detach(seg);
1295}

References DatumGetPointer(), dsm_detach(), 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 108 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 111 of file dsm.c.

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

◆ 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:1297
static void ResOwnerReleaseDSM(Datum res)
Definition: dsm.c:1289
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition: resowner.h:54
#define RELEASE_PRIO_DSMS
Definition: resowner.h:65

Definition at line 149 of file dsm.c.

Referenced by ResourceOwnerForgetDSM(), and ResourceOwnerRememberDSM().

◆ dsm_segment_list

dlist_head dsm_segment_list = DLIST_STATIC_INIT(dsm_segment_list)
static