PostgreSQL Source Code  git master
pg_shmem.h File Reference
#include "storage/dsm_impl.h"
Include dependency graph for pg_shmem.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PGShmemHeader
 

Macros

#define PGShmemMagic   679834894
 

Typedefs

typedef struct PGShmemHeader PGShmemHeader
 

Enumerations

enum  HugePagesType { HUGE_PAGES_OFF, HUGE_PAGES_ON, HUGE_PAGES_TRY }
 

Functions

PGShmemHeaderPGSharedMemoryCreate (Size size, bool makePrivate, int port, PGShmemHeader **shim)
 
bool PGSharedMemoryIsInUse (unsigned long id1, unsigned long id2)
 
void PGSharedMemoryDetach (void)
 

Variables

int huge_pages
 
unsigned long UsedShmemSegID
 
void * UsedShmemSegAddr
 

Macro Definition Documentation

◆ PGShmemMagic

#define PGShmemMagic   679834894

Typedef Documentation

◆ PGShmemHeader

Enumeration Type Documentation

◆ HugePagesType

Enumerator
HUGE_PAGES_OFF 
HUGE_PAGES_ON 
HUGE_PAGES_TRY 

Definition at line 48 of file pg_shmem.h.

Function Documentation

◆ PGSharedMemoryCreate()

PGShmemHeader* PGSharedMemoryCreate ( Size  size,
bool  makePrivate,
int  port,
PGShmemHeader **  shim 
)

Definition at line 558 of file sysv_shmem.c.

References AnonymousShmem, AnonymousShmemDetach(), AnonymousShmemSize, Assert, CreateAnonymousSegment(), PGShmemHeader::creatorPID, DataDir, DEBUG3, PGShmemHeader::device, dsm_cleanup_using_control_segment(), PGShmemHeader::dsm_control, dsm_control, elog, ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), ERROR, FATAL, free, PGShmemHeader::freeoffset, GetSharedMemName(), huge_pages, HUGE_PAGES_ON, i, PGShmemHeader::inode, InternalIpcMemoryCreate(), IPC_RMID, IsUnderPostmaster, kill, LOG, PGShmemHeader::magic, MAXALIGN, on_shmem_exit(), PGSharedMemoryAttach(), PGSharedMemoryDetach(), PGSharedMemoryNoReAttach(), PGSharedMemoryReAttach(), PGShmemMagic, pgwin32_SharedMemoryDelete(), PointerGetDatum, stat, PGShmemHeader::totalsize, TRUE, UsedShmemSegAddr, UsedShmemSegID, and UsedShmemSegSize.

Referenced by CreateSharedMemoryAndSemaphores().

560 {
561  IpcMemoryKey NextShmemSegID;
562  void *memAddress;
563  PGShmemHeader *hdr;
564  IpcMemoryId shmid;
565  struct stat statbuf;
566  Size sysvsize;
567 
568  /* Complain if hugepages demanded but we can't possibly support them */
569 #if !defined(USE_ANONYMOUS_SHMEM) || !defined(MAP_HUGETLB)
570  if (huge_pages == HUGE_PAGES_ON)
571  ereport(ERROR,
572  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
573  errmsg("huge pages not supported on this platform")));
574 #endif
575 
576  /* Room for a header? */
577  Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
578 
579 #ifdef USE_ANONYMOUS_SHMEM
581  AnonymousShmemSize = size;
582 
583  /* Register on-exit routine to unmap the anonymous segment */
585 
586  /* Now we need only allocate a minimal-sized SysV shmem block. */
587  sysvsize = sizeof(PGShmemHeader);
588 #else
589  sysvsize = size;
590 #endif
591 
592  /* Make sure PGSharedMemoryAttach doesn't fail without need */
593  UsedShmemSegAddr = NULL;
594 
595  /* Loop till we find a free IPC key */
596  NextShmemSegID = port * 1000;
597 
598  for (NextShmemSegID++;; NextShmemSegID++)
599  {
600  /* Try to create new segment */
601  memAddress = InternalIpcMemoryCreate(NextShmemSegID, sysvsize);
602  if (memAddress)
603  break; /* successful create and attach */
604 
605  /* Check shared memory and possibly remove and recreate */
606 
607  if (makePrivate) /* a standalone backend shouldn't do this */
608  continue;
609 
610  if ((memAddress = PGSharedMemoryAttach(NextShmemSegID, &shmid)) == NULL)
611  continue; /* can't attach, not one of mine */
612 
613  /*
614  * If I am not the creator and it belongs to an extant process,
615  * continue.
616  */
617  hdr = (PGShmemHeader *) memAddress;
618  if (hdr->creatorPID != getpid())
619  {
620  if (kill(hdr->creatorPID, 0) == 0 || errno != ESRCH)
621  {
622  shmdt(memAddress);
623  continue; /* segment belongs to a live process */
624  }
625  }
626 
627  /*
628  * The segment appears to be from a dead Postgres process, or from a
629  * previous cycle of life in this same process. Zap it, if possible,
630  * and any associated dynamic shared memory segments, as well. This
631  * probably shouldn't fail, but if it does, assume the segment belongs
632  * to someone else after all, and continue quietly.
633  */
634  if (hdr->dsm_control != 0)
636  shmdt(memAddress);
637  if (shmctl(shmid, IPC_RMID, NULL) < 0)
638  continue;
639 
640  /*
641  * Now try again to create the segment.
642  */
643  memAddress = InternalIpcMemoryCreate(NextShmemSegID, sysvsize);
644  if (memAddress)
645  break; /* successful create and attach */
646 
647  /*
648  * Can only get here if some other process managed to create the same
649  * shmem key before we did. Let him have that one, loop around to try
650  * next key.
651  */
652  }
653 
654  /*
655  * OK, we created a new segment. Mark it as created by this process. The
656  * order of assignments here is critical so that another Postgres process
657  * can't see the header as valid but belonging to an invalid PID!
658  */
659  hdr = (PGShmemHeader *) memAddress;
660  hdr->creatorPID = getpid();
661  hdr->magic = PGShmemMagic;
662  hdr->dsm_control = 0;
663 
664  /* Fill in the data directory ID info, too */
665  if (stat(DataDir, &statbuf) < 0)
666  ereport(FATAL,
668  errmsg("could not stat data directory \"%s\": %m",
669  DataDir)));
670  hdr->device = statbuf.st_dev;
671  hdr->inode = statbuf.st_ino;
672 
673  /*
674  * Initialize space allocation status for segment.
675  */
676  hdr->totalsize = size;
677  hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
678  *shim = hdr;
679 
680  /* Save info for possible future use */
681  UsedShmemSegAddr = memAddress;
682  UsedShmemSegID = (unsigned long) NextShmemSegID;
683 
684  /*
685  * If AnonymousShmem is NULL here, then we're not using anonymous shared
686  * memory, and should return a pointer to the System V shared memory
687  * block. Otherwise, the System V shared memory block is only a shim, and
688  * we must return a pointer to the real block.
689  */
690 #ifdef USE_ANONYMOUS_SHMEM
691  if (AnonymousShmem == NULL)
692  return hdr;
693  memcpy(AnonymousShmem, hdr, sizeof(PGShmemHeader));
694  return (PGShmemHeader *) AnonymousShmem;
695 #else
696  return hdr;
697 #endif
698 }
pid_t creatorPID
Definition: pg_shmem.h:33
void dsm_cleanup_using_control_segment(dsm_handle old_control_handle)
Definition: dsm.c:210
static PGShmemHeader * PGSharedMemoryAttach(IpcMemoryKey key, IpcMemoryId *shmid)
Definition: sysv_shmem.c:822
dsm_handle dsm_control
Definition: pg_shmem.h:36
struct PGShmemHeader PGShmemHeader
static Size AnonymousShmemSize
Definition: sysv_shmem.c:79
int errcode(int sqlerrcode)
Definition: elog.c:575
#define kill(pid, sig)
Definition: win32_port.h:437
static void * InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
Definition: sysv_shmem.c:103
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:348
key_t IpcMemoryKey
Definition: sysv_shmem.c:71
int errcode_for_file_access(void)
Definition: elog.c:598
void * UsedShmemSegAddr
Definition: sysv_shmem.c:76
static void AnonymousShmemDetach(int status, Datum arg)
Definition: sysv_shmem.c:525
#define ereport(elevel, rest)
Definition: elog.h:122
static int port
Definition: pg_regress.c:90
int32 magic
Definition: pg_shmem.h:31
static void * CreateAnonymousSegment(Size *size)
Definition: sysv_shmem.c:457
#define stat(a, b)
Definition: win32_port.h:266
Size totalsize
Definition: pg_shmem.h:34
uintptr_t Datum
Definition: postgres.h:372
unsigned long UsedShmemSegID
Definition: sysv_shmem.c:75
#define IPC_RMID
Definition: win32_port.h:81
static void * AnonymousShmem
Definition: sysv_shmem.c:80
ino_t inode
Definition: pg_shmem.h:40
dev_t device
Definition: pg_shmem.h:39
#define Assert(condition)
Definition: c.h:670
#define PGShmemMagic
Definition: pg_shmem.h:32
Size freeoffset
Definition: pg_shmem.h:35
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623
int IpcMemoryId
Definition: sysv_shmem.c:72
int huge_pages
Definition: guc.c:488
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * DataDir
Definition: globals.c:60

◆ PGSharedMemoryDetach()

void PGSharedMemoryDetach ( void  )

Definition at line 790 of file sysv_shmem.c.

References AnonymousShmem, AnonymousShmemSize, elog, LOG, UsedShmemSegAddr, and UsedShmemSegID.

Referenced by pgarch_start(), PGSharedMemoryCreate(), PGSharedMemoryNoReAttach(), pgstat_start(), pgwin32_SharedMemoryDelete(), StartBackgroundWorker(), and SysLogger_Start().

791 {
792  if (UsedShmemSegAddr != NULL)
793  {
794  if ((shmdt(UsedShmemSegAddr) < 0)
795 #if defined(EXEC_BACKEND) && defined(__CYGWIN__)
796  /* Work-around for cygipc exec bug */
797  && shmdt(NULL) < 0
798 #endif
799  )
800  elog(LOG, "shmdt(%p) failed: %m", UsedShmemSegAddr);
801  UsedShmemSegAddr = NULL;
802  }
803 
804 #ifdef USE_ANONYMOUS_SHMEM
805  if (AnonymousShmem != NULL)
806  {
807  if (munmap(AnonymousShmem, AnonymousShmemSize) < 0)
808  elog(LOG, "munmap(%p, %zu) failed: %m",
810  AnonymousShmem = NULL;
811  }
812 #endif
813 }
static Size AnonymousShmemSize
Definition: sysv_shmem.c:79
#define LOG
Definition: elog.h:26
void * UsedShmemSegAddr
Definition: sysv_shmem.c:76
static void * AnonymousShmem
Definition: sysv_shmem.c:80
#define elog
Definition: elog.h:219

◆ PGSharedMemoryIsInUse()

bool PGSharedMemoryIsInUse ( unsigned long  id1,
unsigned long  id2 
)

Definition at line 289 of file sysv_shmem.c.

References AllocateFile(), buf, DataDir, EIDRM, FALSE, free, FreeFile(), GetSharedMemName(), IPC_STAT, PG_SHMAT_FLAGS, PGShmemMagic, and stat.

Referenced by CreateLockFile().

290 {
291  IpcMemoryId shmId = (IpcMemoryId) id2;
292  struct shmid_ds shmStat;
293  struct stat statbuf;
294  PGShmemHeader *hdr;
295 
296  /*
297  * We detect whether a shared memory segment is in use by seeing whether
298  * it (a) exists and (b) has any processes attached to it.
299  */
300  if (shmctl(shmId, IPC_STAT, &shmStat) < 0)
301  {
302  /*
303  * EINVAL actually has multiple possible causes documented in the
304  * shmctl man page, but we assume it must mean the segment no longer
305  * exists.
306  */
307  if (errno == EINVAL)
308  return false;
309 
310  /*
311  * EACCES implies that the segment belongs to some other userid, which
312  * means it is not a Postgres shmem segment (or at least, not one that
313  * is relevant to our data directory).
314  */
315  if (errno == EACCES)
316  return false;
317 
318  /*
319  * Some Linux kernel versions (in fact, all of them as of July 2007)
320  * sometimes return EIDRM when EINVAL is correct. The Linux kernel
321  * actually does not have any internal state that would justify
322  * returning EIDRM, so we can get away with assuming that EIDRM is
323  * equivalent to EINVAL on that platform.
324  */
325 #ifdef HAVE_LINUX_EIDRM_BUG
326  if (errno == EIDRM)
327  return false;
328 #endif
329 
330  /*
331  * Otherwise, we had better assume that the segment is in use. The
332  * only likely case is EIDRM, which implies that the segment has been
333  * IPC_RMID'd but there are still processes attached to it.
334  */
335  return true;
336  }
337 
338  /* If it has no attached processes, it's not in use */
339  if (shmStat.shm_nattch == 0)
340  return false;
341 
342  /*
343  * Try to attach to the segment and see if it matches our data directory.
344  * This avoids shmid-conflict problems on machines that are running
345  * several postmasters under the same userid.
346  */
347  if (stat(DataDir, &statbuf) < 0)
348  return true; /* if can't stat, be conservative */
349 
350  hdr = (PGShmemHeader *) shmat(shmId, NULL, PG_SHMAT_FLAGS);
351 
352  if (hdr == (PGShmemHeader *) -1)
353  return true; /* if can't attach, be conservative */
354 
355  if (hdr->magic != PGShmemMagic ||
356  hdr->device != statbuf.st_dev ||
357  hdr->inode != statbuf.st_ino)
358  {
359  /*
360  * It's either not a Postgres segment, or not one for my data
361  * directory. In either case it poses no threat.
362  */
363  shmdt((void *) hdr);
364  return false;
365  }
366 
367  /* Trouble --- looks a lot like there's still live backends */
368  shmdt((void *) hdr);
369 
370  return true;
371 }
#define PG_SHMAT_FLAGS
Definition: mem.h:20
#define EIDRM
Definition: win32_port.h:90
#define stat(a, b)
Definition: win32_port.h:266
#define PGShmemMagic
Definition: pg_shmem.h:32
int IpcMemoryId
Definition: sysv_shmem.c:72
char * DataDir
Definition: globals.c:60
#define IPC_STAT
Definition: win32_port.h:86

Variable Documentation

◆ huge_pages

int huge_pages

Definition at line 488 of file guc.c.

Referenced by CreateAnonymousSegment(), and PGSharedMemoryCreate().

◆ UsedShmemSegAddr

◆ UsedShmemSegID