PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
win32_shmem.c File Reference
#include "postgres.h"
#include "miscadmin.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
Include dependency graph for win32_shmem.c:

Go to the source code of this file.

Functions

static void pgwin32_SharedMemoryDelete (int status, Datum shmId)
 
static char * GetSharedMemName (void)
 
bool PGSharedMemoryIsInUse (unsigned long id1, unsigned long id2)
 
PGShmemHeaderPGSharedMemoryCreate (Size size, bool makePrivate, int port, PGShmemHeader **shim)
 
void PGSharedMemoryReAttach (void)
 
void PGSharedMemoryNoReAttach (void)
 
void PGSharedMemoryDetach (void)
 
int pgwin32_ReserveSharedMemoryRegion (HANDLE hChild)
 

Variables

HANDLE UsedShmemSegID = INVALID_HANDLE_VALUE
 
void * UsedShmemSegAddr = NULL
 
static Size UsedShmemSegSize = 0
 

Function Documentation

static char* GetSharedMemName ( void  )
static

Definition at line 40 of file win32_shmem.c.

References DataDir, elog, FATAL, malloc, and NULL.

Referenced by PGSharedMemoryCreate(), and PGSharedMemoryIsInUse().

41 {
42  char *retptr;
43  DWORD bufsize;
44  DWORD r;
45  char *cp;
46 
47  bufsize = GetFullPathName(DataDir, 0, NULL, NULL);
48  if (bufsize == 0)
49  elog(FATAL, "could not get size for full pathname of datadir %s: error code %lu",
50  DataDir, GetLastError());
51 
52  retptr = malloc(bufsize + 18); /* 18 for Global\PostgreSQL: */
53  if (retptr == NULL)
54  elog(FATAL, "could not allocate memory for shared memory name");
55 
56  strcpy(retptr, "Global\\PostgreSQL:");
57  r = GetFullPathName(DataDir, bufsize, retptr + 18, NULL);
58  if (r == 0 || r > bufsize)
59  elog(FATAL, "could not generate full pathname for datadir %s: error code %lu",
60  DataDir, GetLastError());
61 
62  /*
63  * XXX: Intentionally overwriting the Global\ part here. This was not the
64  * original approach, but putting it in the actual Global\ namespace
65  * causes permission errors in a lot of cases, so we leave it in the
66  * default namespace for now.
67  */
68  for (cp = retptr; *cp; cp++)
69  if (*cp == '\\')
70  *cp = '/';
71 
72  return retptr;
73 }
#define malloc(a)
Definition: header.h:50
#define FATAL
Definition: elog.h:52
#define NULL
Definition: c.h:229
char * DataDir
Definition: globals.c:60
#define elog
Definition: elog.h:219
PGShmemHeader* PGSharedMemoryCreate ( Size  size,
bool  makePrivate,
int  port,
PGShmemHeader **  shim 
)

Definition at line 119 of file win32_shmem.c.

References AnonymousShmem, AnonymousShmemDetach(), AnonymousShmemSize, Assert, CreateAnonymousSegment(), PGShmemHeader::creatorPID, DataDir, PGShmemHeader::device, dsm_cleanup_using_control_segment(), PGShmemHeader::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, LOG, PGShmemHeader::magic, MAXALIGN, NULL, on_shmem_exit(), PGSharedMemoryAttach(), PGShmemMagic, pgwin32_SharedMemoryDelete(), PointerGetDatum, PGShmemHeader::totalsize, TRUE, UsedShmemSegAddr, UsedShmemSegID, and UsedShmemSegSize.

121 {
122  void *memAddress;
123  PGShmemHeader *hdr;
124  HANDLE hmap,
125  hmap2;
126  char *szShareMem;
127  int i;
128  DWORD size_high;
129  DWORD size_low;
130 
131  if (huge_pages == HUGE_PAGES_ON)
132  ereport(ERROR,
133  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
134  errmsg("huge pages not supported on this platform")));
135 
136  /* Room for a header? */
137  Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
138 
139  szShareMem = GetSharedMemName();
140 
142 
143 #ifdef _WIN64
144  size_high = size >> 32;
145 #else
146  size_high = 0;
147 #endif
148  size_low = (DWORD) size;
149 
150  /*
151  * When recycling a shared memory segment, it may take a short while
152  * before it gets dropped from the global namespace. So re-try after
153  * sleeping for a second, and continue retrying 10 times. (both the 1
154  * second time and the 10 retries are completely arbitrary)
155  */
156  for (i = 0; i < 10; i++)
157  {
158  /*
159  * In case CreateFileMapping() doesn't set the error code to 0 on
160  * success
161  */
162  SetLastError(0);
163 
164  hmap = CreateFileMapping(INVALID_HANDLE_VALUE, /* Use the pagefile */
165  NULL, /* Default security attrs */
166  PAGE_READWRITE, /* Memory is Read/Write */
167  size_high, /* Size Upper 32 Bits */
168  size_low, /* Size Lower 32 bits */
169  szShareMem);
170 
171  if (!hmap)
172  ereport(FATAL,
173  (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
174  errdetail("Failed system call was CreateFileMapping(size=%zu, name=%s).",
175  size, szShareMem)));
176 
177  /*
178  * If the segment already existed, CreateFileMapping() will return a
179  * handle to the existing one and set ERROR_ALREADY_EXISTS.
180  */
181  if (GetLastError() == ERROR_ALREADY_EXISTS)
182  {
183  CloseHandle(hmap); /* Close the handle, since we got a valid one
184  * to the previous segment. */
185  hmap = NULL;
186  Sleep(1000);
187  continue;
188  }
189  break;
190  }
191 
192  /*
193  * If the last call in the loop still returned ERROR_ALREADY_EXISTS, this
194  * shared memory segment exists and we assume it belongs to somebody else.
195  */
196  if (!hmap)
197  ereport(FATAL,
198  (errmsg("pre-existing shared memory block is still in use"),
199  errhint("Check if there are any old server processes still running, and terminate them.")));
200 
201  free(szShareMem);
202 
203  /*
204  * Make the handle inheritable
205  */
206  if (!DuplicateHandle(GetCurrentProcess(), hmap, GetCurrentProcess(), &hmap2, 0, TRUE, DUPLICATE_SAME_ACCESS))
207  ereport(FATAL,
208  (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
209  errdetail("Failed system call was DuplicateHandle.")));
210 
211  /*
212  * Close the old, non-inheritable handle. If this fails we don't really
213  * care.
214  */
215  if (!CloseHandle(hmap))
216  elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError());
217 
218 
219  /*
220  * Get a pointer to the new shared memory segment. Map the whole segment
221  * at once, and let the system decide on the initial address.
222  */
223  memAddress = MapViewOfFileEx(hmap2, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0, NULL);
224  if (!memAddress)
225  ereport(FATAL,
226  (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
227  errdetail("Failed system call was MapViewOfFileEx.")));
228 
229 
230 
231  /*
232  * OK, we created a new segment. Mark it as created by this process. The
233  * order of assignments here is critical so that another Postgres process
234  * can't see the header as valid but belonging to an invalid PID!
235  */
236  hdr = (PGShmemHeader *) memAddress;
237  hdr->creatorPID = getpid();
238  hdr->magic = PGShmemMagic;
239 
240  /*
241  * Initialize space allocation status for segment.
242  */
243  hdr->totalsize = size;
244  hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
245  hdr->dsm_control = 0;
246 
247  /* Save info for possible future use */
248  UsedShmemSegAddr = memAddress;
249  UsedShmemSegSize = size;
250  UsedShmemSegID = hmap2;
251 
252  /* Register on-exit routine to delete the new segment */
254 
255  *shim = hdr;
256  return hdr;
257 }
pid_t creatorPID
Definition: pg_shmem.h:33
int errhint(const char *fmt,...)
Definition: elog.c:987
dsm_handle dsm_control
Definition: pg_shmem.h:36
#define PointerGetDatum(X)
Definition: postgres.h:562
int errcode(int sqlerrcode)
Definition: elog.c:575
#define LOG
Definition: elog.h:26
#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
HANDLE UsedShmemSegID
Definition: win32_shmem.c:20
int errdetail(const char *fmt,...)
Definition: elog.c:873
static void pgwin32_SharedMemoryDelete(int status, Datum shmId)
Definition: win32_shmem.c:378
#define ereport(elevel, rest)
Definition: elog.h:122
int32 magic
Definition: pg_shmem.h:31
static Size UsedShmemSegSize
Definition: win32_shmem.c:22
Size totalsize
Definition: pg_shmem.h:34
static char * GetSharedMemName(void)
Definition: win32_shmem.c:40
#define free(a)
Definition: header.h:65
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define PGShmemMagic
Definition: pg_shmem.h:32
Size freeoffset
Definition: pg_shmem.h:35
#define MAXALIGN(LEN)
Definition: c.h:588
int huge_pages
Definition: guc.c:487
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define TRUE
Definition: c.h:217
#define elog
Definition: elog.h:219
void * UsedShmemSegAddr
Definition: win32_shmem.c:21
void PGSharedMemoryDetach ( void  )

Definition at line 347 of file win32_shmem.c.

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

Referenced by PGSharedMemoryNoReAttach(), and pgwin32_SharedMemoryDelete().

348 {
349  /* Unmap the view, if it's mapped */
350  if (UsedShmemSegAddr != NULL)
351  {
352  if (!UnmapViewOfFile(UsedShmemSegAddr))
353  elog(LOG, "could not unmap view of shared memory: error code %lu",
354  GetLastError());
355 
357  }
358 
359  /* And close the shmem handle, if we have one */
360  if (UsedShmemSegID != INVALID_HANDLE_VALUE)
361  {
362  if (!CloseHandle(UsedShmemSegID))
363  elog(LOG, "could not close handle to shared memory: error code %lu",
364  GetLastError());
365 
366  UsedShmemSegID = INVALID_HANDLE_VALUE;
367  }
368 }
#define LOG
Definition: elog.h:26
HANDLE UsedShmemSegID
Definition: win32_shmem.c:20
#define NULL
Definition: c.h:229
#define elog
Definition: elog.h:219
void * UsedShmemSegAddr
Definition: win32_shmem.c:21
bool PGSharedMemoryIsInUse ( unsigned long  id1,
unsigned long  id2 
)

Definition at line 88 of file win32_shmem.c.

References DataDir, EIDRM, FALSE, free, GetSharedMemName(), IPC_STAT, NULL, PG_SHMAT_FLAGS, and PGShmemMagic.

89 {
90  char *szShareMem;
91  HANDLE hmap;
92 
93  szShareMem = GetSharedMemName();
94 
95  hmap = OpenFileMapping(FILE_MAP_READ, FALSE, szShareMem);
96 
97  free(szShareMem);
98 
99  if (hmap == NULL)
100  return false;
101 
102  CloseHandle(hmap);
103  return true;
104 }
#define FALSE
Definition: c.h:221
static char * GetSharedMemName(void)
Definition: win32_shmem.c:40
#define free(a)
Definition: header.h:65
#define NULL
Definition: c.h:229
void PGSharedMemoryNoReAttach ( void  )

Definition at line 315 of file win32_shmem.c.

References Assert, IsUnderPostmaster, NULL, PGSharedMemoryDetach(), and UsedShmemSegAddr.

316 {
319 
320  /*
321  * Under Windows we will not have mapped the segment, so we don't need to
322  * un-map it. Just reset UsedShmemSegAddr to show we're not attached.
323  */
325 
326  /*
327  * We *must* close the inherited shmem segment handle, else Windows will
328  * consider the existence of this process to mean it can't release the
329  * shmem segment yet. We can now use PGSharedMemoryDetach to do that.
330  */
332 }
void PGSharedMemoryDetach(void)
Definition: win32_shmem.c:347
bool IsUnderPostmaster
Definition: globals.c:101
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void * UsedShmemSegAddr
Definition: win32_shmem.c:21
void PGSharedMemoryReAttach ( void  )

Definition at line 271 of file win32_shmem.c.

References Assert, PGShmemHeader::dsm_control, elog, FATAL, IsUnderPostmaster, PGShmemHeader::magic, NULL, PGShmemMagic, UsedShmemSegAddr, and UsedShmemSegID.

272 {
273  PGShmemHeader *hdr;
274  void *origUsedShmemSegAddr = UsedShmemSegAddr;
275 
278 
279  /*
280  * Release memory region reservation that was made by the postmaster
281  */
282  if (VirtualFree(UsedShmemSegAddr, 0, MEM_RELEASE) == 0)
283  elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
284  UsedShmemSegAddr, GetLastError());
285 
286  hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
287  if (!hdr)
288  elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
289  UsedShmemSegID, UsedShmemSegAddr, GetLastError());
290  if (hdr != origUsedShmemSegAddr)
291  elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
292  hdr, origUsedShmemSegAddr);
293  if (hdr->magic != PGShmemMagic)
294  elog(FATAL, "reattaching to shared memory returned non-PostgreSQL memory");
295  dsm_set_control_handle(hdr->dsm_control);
296 
297  UsedShmemSegAddr = hdr; /* probably redundant */
298 }
dsm_handle dsm_control
Definition: pg_shmem.h:36
#define FATAL
Definition: elog.h:52
bool IsUnderPostmaster
Definition: globals.c:101
HANDLE UsedShmemSegID
Definition: win32_shmem.c:20
int32 magic
Definition: pg_shmem.h:31
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define PGShmemMagic
Definition: pg_shmem.h:32
#define elog
Definition: elog.h:219
void * UsedShmemSegAddr
Definition: win32_shmem.c:21
int pgwin32_ReserveSharedMemoryRegion ( HANDLE  hChild)

Definition at line 402 of file win32_shmem.c.

References Assert, elog, LOG, NULL, UsedShmemSegAddr, and UsedShmemSegSize.

403 {
404  void *address;
405 
407  Assert(UsedShmemSegSize != 0);
408 
409  address = VirtualAllocEx(hChild, UsedShmemSegAddr, UsedShmemSegSize,
410  MEM_RESERVE, PAGE_READWRITE);
411  if (address == NULL)
412  {
413  /* Don't use FATAL since we're running in the postmaster */
414  elog(LOG, "could not reserve shared memory region (addr=%p) for child %p: error code %lu",
415  UsedShmemSegAddr, hChild, GetLastError());
416  return false;
417  }
418  if (address != UsedShmemSegAddr)
419  {
420  /*
421  * Should never happen - in theory if allocation granularity causes
422  * strange effects it could, so check just in case.
423  *
424  * Don't use FATAL since we're running in the postmaster.
425  */
426  elog(LOG, "reserved shared memory region got incorrect address %p, expected %p",
427  address, UsedShmemSegAddr);
428  VirtualFreeEx(hChild, address, 0, MEM_RELEASE);
429  return false;
430  }
431 
432  return true;
433 }
#define LOG
Definition: elog.h:26
static Size UsedShmemSegSize
Definition: win32_shmem.c:22
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define elog
Definition: elog.h:219
void * UsedShmemSegAddr
Definition: win32_shmem.c:21
static void pgwin32_SharedMemoryDelete ( int  status,
Datum  shmId 
)
static

Definition at line 378 of file win32_shmem.c.

References Assert, DatumGetPointer, PGSharedMemoryDetach(), and UsedShmemSegID.

Referenced by PGSharedMemoryCreate().

379 {
382 }
void PGSharedMemoryDetach(void)
Definition: win32_shmem.c:347
HANDLE UsedShmemSegID
Definition: win32_shmem.c:20
#define Assert(condition)
Definition: c.h:675
#define DatumGetPointer(X)
Definition: postgres.h:555

Variable Documentation

HANDLE UsedShmemSegID = INVALID_HANDLE_VALUE
Size UsedShmemSegSize = 0
static

Definition at line 22 of file win32_shmem.c.

Referenced by PGSharedMemoryCreate(), and pgwin32_ReserveSharedMemoryRegion().