6
6
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7
7
*
8
8
* IDENTIFICATION
9
- * $PostgreSQL: pgsql/src/backend/port/win32_shmem.c,v 1.11 2009/06/11 14:49:00 momjian Exp $
9
+ * $PostgreSQL: pgsql/src/backend/port/win32_shmem.c,v 1.12 2009/07/24 20:12:42 mha Exp $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
18
18
19
19
unsigned long UsedShmemSegID = 0 ;
20
20
void * UsedShmemSegAddr = NULL ;
21
+ static Size UsedShmemSegSize = 0 ;
21
22
22
23
static void pgwin32_SharedMemoryDelete (int status , Datum shmId );
23
24
@@ -233,6 +234,7 @@ PGSharedMemoryCreate(Size size, bool makePrivate, int port)
233
234
234
235
/* Save info for possible future use */
235
236
UsedShmemSegAddr = memAddress ;
237
+ UsedShmemSegSize = size ;
236
238
UsedShmemSegID = (unsigned long ) hmap2 ;
237
239
238
240
return hdr ;
@@ -257,6 +259,13 @@ PGSharedMemoryReAttach(void)
257
259
Assert (UsedShmemSegAddr != NULL );
258
260
Assert (IsUnderPostmaster );
259
261
262
+ /*
263
+ * Release memory region reservation that was made by the postmaster
264
+ */
265
+ if (VirtualFree (UsedShmemSegAddr , 0 , MEM_RELEASE ) == 0 )
266
+ elog (FATAL , "failed to release reserved memory region (addr=%p): %lu" ,
267
+ UsedShmemSegAddr , GetLastError ());
268
+
260
269
hdr = (PGShmemHeader * ) MapViewOfFileEx ((HANDLE ) UsedShmemSegID , FILE_MAP_READ | FILE_MAP_WRITE , 0 , 0 , 0 , UsedShmemSegAddr );
261
270
if (!hdr )
262
271
elog (FATAL , "could not reattach to shared memory (key=%d, addr=%p): %lu" ,
@@ -302,3 +311,53 @@ pgwin32_SharedMemoryDelete(int status, Datum shmId)
302
311
if (!CloseHandle ((HANDLE ) DatumGetInt32 (shmId )))
303
312
elog (LOG , "could not close handle to shared memory: %lu" , GetLastError ());
304
313
}
314
+
315
+ /*
316
+ * pgwin32_ReserveSharedMemoryRegion(hChild)
317
+ *
318
+ * Reserve the memory region that will be used for shared memory in a child
319
+ * process. It is called before the child process starts, to make sure the
320
+ * memory is available.
321
+ *
322
+ * Once the child starts, DLLs loading in different order or threads getting
323
+ * scheduled differently may allocate memory which can conflict with the
324
+ * address space we need for our shared memory. By reserving the shared
325
+ * memory region before the child starts, and freeing it only just before we
326
+ * attempt to get access to the shared memory forces these allocations to
327
+ * be given different address ranges that don't conflict.
328
+ *
329
+ * NOTE! This function executes in the postmaster, and should for this
330
+ * reason not use elog(FATAL) since that would take down the postmaster.
331
+ */
332
+ int
333
+ pgwin32_ReserveSharedMemoryRegion (HANDLE hChild )
334
+ {
335
+ void * address ;
336
+
337
+ Assert (UsedShmemSegAddr != NULL );
338
+ Assert (UsedShmemSegSize != 0 );
339
+
340
+ address = VirtualAllocEx (hChild , UsedShmemSegAddr , UsedShmemSegSize ,
341
+ MEM_RESERVE , PAGE_READWRITE );
342
+ if (address == NULL ) {
343
+ /* Don't use FATAL since we're running in the postmaster */
344
+ elog (LOG , "could not reserve shared memory region (addr=%p) for child %lu: %lu" ,
345
+ UsedShmemSegAddr , hChild , GetLastError ());
346
+ return false;
347
+ }
348
+ if (address != UsedShmemSegAddr )
349
+ {
350
+ /*
351
+ * Should never happen - in theory if allocation granularity causes strange
352
+ * effects it could, so check just in case.
353
+ *
354
+ * Don't use FATAL since we're running in the postmaster.
355
+ */
356
+ elog (LOG , "reserved shared memory region got incorrect address %p, expected %p" ,
357
+ address , UsedShmemSegAddr );
358
+ VirtualFreeEx (hChild , address , 0 , MEM_RELEASE );
359
+ return false;
360
+ }
361
+
362
+ return true;
363
+ }
0 commit comments