@@ -94,8 +94,19 @@ typedef enum
9494unsigned long  UsedShmemSegID  =  0 ;
9595void 	   * UsedShmemSegAddr  =  NULL ;
9696
97- static  Size  AnonymousShmemSize ;
98- static  void  * AnonymousShmem  =  NULL ;
97+ typedef  struct  AnonymousMapping 
98+ {
99+ 	int  shmem_segment ;
100+ 	Size  shmem_size ; 			/* Size of the mapping */ 
101+ 	Pointer  shmem ; 				/* Pointer to the start of the mapped memory */ 
102+ 	Pointer  seg_addr ; 			/* SysV shared memory for the header */ 
103+ 	unsigned long  seg_id ; 		/* IPC key */ 
104+ } AnonymousMapping ;
105+ 
106+ static  AnonymousMapping  Mappings [ANON_MAPPINGS ];
107+ 
108+ /* Keeps track of used mapping segments */ 
109+ static  int  next_free_segment  =  0 ;
99110
100111static  void  * InternalIpcMemoryCreate (IpcMemoryKey  memKey , Size  size );
101112static  void  IpcMemoryDetach (int  status , Datum  shmaddr );
@@ -104,6 +115,28 @@ static IpcMemoryState PGSharedMemoryAttach(IpcMemoryId shmId,
104115										   void  * attachAt ,
105116										   PGShmemHeader  * * addr );
106117
118+ static  const  char * 
119+ MappingName (int  shmem_segment )
120+ {
121+ 	switch  (shmem_segment )
122+ 	{
123+ 		case  MAIN_SHMEM_SEGMENT :
124+ 			return  "main" ;
125+ 		default :
126+ 			return  "unknown" ;
127+ 	}
128+ }
129+ 
130+ static  void 
131+ DebugMappings ()
132+ {
133+ 	for (int  i  =  0 ; i  <  next_free_segment ; i ++ )
134+ 	{
135+ 		AnonymousMapping  m  =  Mappings [i ];
136+ 		elog (DEBUG1 , "Mapping[%s]: addr %p, size %zu" ,
137+ 			 MappingName (i ), m .shmem , m .shmem_size );
138+ 	}
139+ }
107140
108141/* 
109142 *	InternalIpcMemoryCreate(memKey, size) 
@@ -591,14 +624,13 @@ check_huge_page_size(int *newval, void **extra, GucSource source)
591624/* 
592625 * Creates an anonymous mmap()ed shared memory segment. 
593626 * 
594-  * Pass the requested size in *size.  This function will modify *size to the 
595-  * actual size of the allocation, if it ends up allocating a segment that is 
596-  * larger than requested. 
627+  * This function will modify mapping size to the actual size of the allocation, 
628+  * if it ends up allocating a segment that is larger than requested. 
597629 */ 
598- static  void   * 
599- CreateAnonymousSegment (Size   * size )
630+ static  void 
631+ CreateAnonymousSegment (AnonymousMapping   * mapping )
600632{
601- 	Size 		allocsize  =  * size ;
633+ 	Size 		allocsize  =  mapping -> shmem_size ;
602634	void 	   * ptr  =  MAP_FAILED ;
603635	int 			mmap_errno  =  0 ;
604636
@@ -623,8 +655,11 @@ CreateAnonymousSegment(Size *size)
623655				   PG_MMAP_FLAGS  | mmap_flags , -1 , 0 );
624656		mmap_errno  =  errno ;
625657		if  (huge_pages  ==  HUGE_PAGES_TRY  &&  ptr  ==  MAP_FAILED )
626- 			elog (DEBUG1 , "mmap(%zu) with MAP_HUGETLB failed, huge pages disabled: %m" ,
627- 				 allocsize );
658+ 		{
659+ 			DebugMappings ();
660+ 			elog (DEBUG1 , "segment[%s]: mmap(%zu) with MAP_HUGETLB failed, huge pages disabled: %m" ,
661+ 				 MappingName (mapping -> shmem_segment ), allocsize );
662+ 		}
628663	}
629664#endif 
630665
@@ -642,7 +677,7 @@ CreateAnonymousSegment(Size *size)
642677		 * Use the original size, not the rounded-up value, when falling back 
643678		 * to non-huge pages. 
644679		 */ 
645- 		allocsize  =  * size ;
680+ 		allocsize  =  mapping -> shmem_size ;
646681		ptr  =  mmap (NULL , allocsize , PROT_READ  | PROT_WRITE ,
647682				   PG_MMAP_FLAGS , -1 , 0 );
648683		mmap_errno  =  errno ;
@@ -651,8 +686,10 @@ CreateAnonymousSegment(Size *size)
651686	if  (ptr  ==  MAP_FAILED )
652687	{
653688		errno  =  mmap_errno ;
689+ 		DebugMappings ();
654690		ereport (FATAL ,
655- 				(errmsg ("could not map anonymous shared memory: %m" ),
691+ 				(errmsg ("segment[%s]: could not map anonymous shared memory: %m" ,
692+ 						MappingName (mapping -> shmem_segment )),
656693				 (mmap_errno  ==  ENOMEM ) ?
657694				 errhint ("This error usually means that PostgreSQL's request " 
658695						 "for a shared memory segment exceeded available memory, " 
@@ -663,8 +700,8 @@ CreateAnonymousSegment(Size *size)
663700						 allocsize ) : 0 ));
664701	}
665702
666- 	* size  =  allocsize ;
667- 	return   ptr ;
703+ 	mapping -> shmem  =  ptr ;
704+ 	mapping -> shmem_size   =   allocsize ;
668705}
669706
670707/* 
@@ -674,13 +711,18 @@ CreateAnonymousSegment(Size *size)
674711static  void 
675712AnonymousShmemDetach (int  status , Datum  arg )
676713{
677- 	/* Release anonymous shared memory block, if any. */ 
678- 	if  (AnonymousShmem  !=  NULL )
714+ 	for (int  i  =  0 ; i  <  next_free_segment ; i ++ )
679715	{
680- 		if  (munmap (AnonymousShmem , AnonymousShmemSize ) <  0 )
681- 			elog (LOG , "munmap(%p, %zu) failed: %m" ,
682- 				 AnonymousShmem , AnonymousShmemSize );
683- 		AnonymousShmem  =  NULL ;
716+ 		AnonymousMapping  m  =  Mappings [i ];
717+ 
718+ 		/* Release anonymous shared memory block, if any. */ 
719+ 		if  (m .shmem  !=  NULL )
720+ 		{
721+ 			if  (munmap (m .shmem , m .shmem_size ) <  0 )
722+ 				elog (LOG , "munmap(%p, %zu) failed: %m" ,
723+ 					 m .shmem , m .shmem_size );
724+ 			m .shmem  =  NULL ;
725+ 		}
684726	}
685727}
686728
@@ -705,6 +747,7 @@ PGSharedMemoryCreate(Size size,
705747	PGShmemHeader  * hdr ;
706748	struct  stat  statbuf ;
707749	Size 		sysvsize ;
750+ 	AnonymousMapping  * mapping  =  & Mappings [next_free_segment ];
708751
709752	/* 
710753	 * We use the data directory's ID info (inode and device numbers) to 
@@ -733,11 +776,15 @@ PGSharedMemoryCreate(Size size,
733776
734777	/* Room for a header? */ 
735778	Assert (size  >  MAXALIGN (sizeof (PGShmemHeader )));
779+ 	mapping -> shmem_size  =  size ;
780+ 	mapping -> shmem_segment  =  next_free_segment ;
736781
737782	if  (shared_memory_type  ==  SHMEM_TYPE_MMAP )
738783	{
739- 		AnonymousShmem  =  CreateAnonymousSegment (& size );
740- 		AnonymousShmemSize  =  size ;
784+ 		/* On success, mapping data will be modified. */ 
785+ 		CreateAnonymousSegment (mapping );
786+ 
787+ 		next_free_segment ++ ;
741788
742789		/* Register on-exit routine to unmap the anonymous segment */ 
743790		on_shmem_exit (AnonymousShmemDetach , (Datum ) 0 );
@@ -760,7 +807,7 @@ PGSharedMemoryCreate(Size size,
760807	 * loop simultaneously.  (CreateDataDirLockFile() does not entirely ensure 
761808	 * that, but prefer fixing it over coping here.) 
762809	 */ 
763- 	NextShmemSegID  =  statbuf .st_ino ;
810+ 	NextShmemSegID  =  statbuf .st_ino   +   next_free_segment ;
764811
765812	for  (;;)
766813	{
@@ -852,24 +899,24 @@ PGSharedMemoryCreate(Size size,
852899	/* 
853900	 * Initialize space allocation status for segment. 
854901	 */ 
855- 	hdr -> totalsize  =  size ;
902+ 	hdr -> totalsize  =  mapping -> shmem_size ;
856903	hdr -> freeoffset  =  MAXALIGN (sizeof (PGShmemHeader ));
857904	* shim  =  hdr ;
858905
859906	/* Save info for possible future use */ 
860- 	UsedShmemSegAddr  =  memAddress ;
861- 	UsedShmemSegID  =  (unsigned long ) NextShmemSegID ;
907+ 	mapping -> seg_addr  =  memAddress ;
908+ 	mapping -> seg_id  =  (unsigned long ) NextShmemSegID ;
862909
863910	/* 
864911	 * If AnonymousShmem is NULL here, then we're not using anonymous shared 
865912	 * memory, and should return a pointer to the System V shared memory 
866913	 * block. Otherwise, the System V shared memory block is only a shim, and 
867914	 * we must return a pointer to the real block. 
868915	 */ 
869- 	if  (AnonymousShmem  ==  NULL )
916+ 	if  (mapping -> shmem  ==  NULL )
870917		return  hdr ;
871- 	memcpy (AnonymousShmem , hdr , sizeof (PGShmemHeader ));
872- 	return  (PGShmemHeader  * ) AnonymousShmem ;
918+ 	memcpy (mapping -> shmem , hdr , sizeof (PGShmemHeader ));
919+ 	return  (PGShmemHeader  * ) mapping -> shmem ;
873920}
874921
875922#ifdef  EXEC_BACKEND 
@@ -969,23 +1016,28 @@ PGSharedMemoryNoReAttach(void)
9691016void 
9701017PGSharedMemoryDetach (void )
9711018{
972- 	if  ( UsedShmemSegAddr   !=   NULL )
1019+ 	for ( int   i   =   0 ;  i   <   next_free_segment ;  i ++ )
9731020	{
974- 		if  ((shmdt (UsedShmemSegAddr ) <  0 )
1021+ 		AnonymousMapping  m  =  Mappings [i ];
1022+ 
1023+ 		if  (m .seg_addr  !=  NULL )
1024+ 		{
1025+ 			if  ((shmdt (m .seg_addr ) <  0 )
9751026#if  defined(EXEC_BACKEND ) &&  defined(__CYGWIN__ )
976- 		/* Work-around for cygipc exec bug */ 
977- 			& &  shmdt (NULL ) <  0 
1027+ 			 /* Work-around for cygipc exec bug */ 
1028+ 				 & &  shmdt (NULL ) <  0 
9781029#endif 
979- 			)
980- 			elog (LOG , "shmdt(%p) failed: %m" , UsedShmemSegAddr );
981- 		UsedShmemSegAddr  =  NULL ;
982- 	}
1030+ 				 )
1031+ 				 elog (LOG , "shmdt(%p) failed: %m" , m . seg_addr );
1032+ 			 m . seg_addr  =  NULL ;
1033+ 		 }
9831034
984- 	if  (AnonymousShmem  !=  NULL )
985- 	{
986- 		if  (munmap (AnonymousShmem , AnonymousShmemSize ) <  0 )
987- 			elog (LOG , "munmap(%p, %zu) failed: %m" ,
988- 				 AnonymousShmem , AnonymousShmemSize );
989- 		AnonymousShmem  =  NULL ;
1035+ 		if  (m .shmem  !=  NULL )
1036+ 		{
1037+ 			if  (munmap (m .shmem , m .shmem_size ) <  0 )
1038+ 				elog (LOG , "munmap(%p, %zu) failed: %m" ,
1039+ 					 m .shmem , m .shmem_size );
1040+ 			m .shmem  =  NULL ;
1041+ 		}
9901042	}
9911043}
0 commit comments