mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-30 00:04:49 -04:00 
			
		
		
		
	Add Win32 semaphore implementation, rather than mimicking SysV
semaphores. Qingqing Zhou
This commit is contained in:
		
							parent
							
								
									291724dfa8
								
							
						
					
					
						commit
						908f317b73
					
				
							
								
								
									
										23
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								configure.in
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| dnl Process this file with autoconf to produce a configure script. | ||||
| dnl $PostgreSQL: pgsql/configure.in,v 1.462 2006/04/29 00:51:41 momjian Exp $ | ||||
| dnl $PostgreSQL: pgsql/configure.in,v 1.463 2006/04/29 16:34:41 momjian Exp $ | ||||
| dnl | ||||
| dnl Developers, please strive to achieve this order: | ||||
| dnl | ||||
| @ -1269,17 +1269,22 @@ AC_FUNC_MEMCMP | ||||
| 
 | ||||
| 
 | ||||
| # Select semaphore implementation type. | ||||
| if test x"$USE_NAMED_POSIX_SEMAPHORES" = x"1" ; then | ||||
|   AC_DEFINE(USE_NAMED_POSIX_SEMAPHORES, 1, [Define to select named POSIX semaphores.]) | ||||
|   SEMA_IMPLEMENTATION="src/backend/port/posix_sema.c" | ||||
| else | ||||
|   if test x"$USE_UNNAMED_POSIX_SEMAPHORES" = x"1" ; then | ||||
|     AC_DEFINE(USE_UNNAMED_POSIX_SEMAPHORES, 1, [Define to select unnamed POSIX semaphores.]) | ||||
| if test "$PORTNAME" != "win32"; then | ||||
|   if test x"$USE_NAMED_POSIX_SEMAPHORES" = x"1" ; then | ||||
|     AC_DEFINE(USE_NAMED_POSIX_SEMAPHORES, 1, [Define to select named POSIX semaphores.]) | ||||
|     SEMA_IMPLEMENTATION="src/backend/port/posix_sema.c" | ||||
|   else | ||||
|     AC_DEFINE(USE_SYSV_SEMAPHORES, 1, [Define to select SysV-style semaphores.]) | ||||
|     SEMA_IMPLEMENTATION="src/backend/port/sysv_sema.c" | ||||
|     if test x"$USE_UNNAMED_POSIX_SEMAPHORES" = x"1" ; then | ||||
|       AC_DEFINE(USE_UNNAMED_POSIX_SEMAPHORES, 1, [Define to select unnamed POSIX semaphores.]) | ||||
|       SEMA_IMPLEMENTATION="src/backend/port/posix_sema.c" | ||||
|     else | ||||
|       AC_DEFINE(USE_SYSV_SEMAPHORES, 1, [Define to select SysV-style semaphores.]) | ||||
|       SEMA_IMPLEMENTATION="src/backend/port/sysv_sema.c" | ||||
|     fi | ||||
|   fi | ||||
| else | ||||
|   AC_DEFINE(USE_WIN32_SEMAPHORES, 1, [Define to select Win32-style semaphores.]) | ||||
|   SEMA_IMPLEMENTATION="src/backend/port/win32_sema.c" | ||||
| fi | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										195
									
								
								src/backend/port/win32_sema.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								src/backend/port/win32_sema.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,195 @@ | ||||
| /*-------------------------------------------------------------------------
 | ||||
|  * | ||||
|  * win32_sema.c | ||||
|  *	  Microsoft Windows Win32 Semaphores Emulation | ||||
|  * | ||||
|  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/port/win32_sema.c,v 1.1 2006/04/29 16:34:41 momjian Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| 
 | ||||
| #include "postgres.h" | ||||
| 
 | ||||
| #include "miscadmin.h" | ||||
| #include "storage/ipc.h" | ||||
| #include "storage/pg_sema.h" | ||||
| 
 | ||||
| static HANDLE *mySemSet;		/* IDs of sema sets acquired so far */ | ||||
| static int	numSems;			/* number of sema sets acquired so far */ | ||||
| static int	maxSems;			/* allocated size of mySemaSet array */ | ||||
| 
 | ||||
| static void ReleaseSemaphores(int code, Datum arg); | ||||
| 
 | ||||
| /*
 | ||||
|  * PGReserveSemaphores --- initialize semaphore support | ||||
|  * | ||||
|  * In the Win32 implementation, we acquire semaphores on-demand; the | ||||
|  * maxSemas parameter is just used to size the array that keeps track of | ||||
|  * acquired semas for subsequent releasing.  We use anonymous semaphores | ||||
|  * so the semaphores are automatically freed when the last referencing | ||||
|  * process exits. | ||||
|  */ | ||||
| void PGReserveSemaphores(int maxSemas, int port) | ||||
| { | ||||
| 	mySemSet = (HANDLE *)malloc(maxSemas * sizeof(HANDLE)); | ||||
| 	if (mySemSet == NULL) | ||||
| 		elog(PANIC, "out of memory"); | ||||
| 	numSems = 0; | ||||
| 	maxSems = maxSemas; | ||||
| 
 | ||||
| 	on_shmem_exit(ReleaseSemaphores, 0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Release semaphores at shutdown or shmem reinitialization | ||||
|  * | ||||
|  * (called as an on_shmem_exit callback, hence funny argument list) | ||||
|  */ | ||||
| static void | ||||
| ReleaseSemaphores(int code, Datum arg) | ||||
| { | ||||
| 	int			i; | ||||
| 
 | ||||
| 	for (i = 0; i < numSems; i++) | ||||
| 		CloseHandle(mySemSet[i]); | ||||
| 	free(mySemSet); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * PGSemaphoreCreate | ||||
|  * | ||||
|  * Initialize a PGSemaphore structure to represent a sema with count 1 | ||||
|  */ | ||||
| void PGSemaphoreCreate(PGSemaphore sema) | ||||
| { | ||||
| 	HANDLE		cur_handle; | ||||
| 	SECURITY_ATTRIBUTES sec_attrs; | ||||
| 
 | ||||
| 	/* Can't do this in a backend, because static state is postmaster's */ | ||||
| 	Assert(!IsUnderPostmaster); | ||||
| 
 | ||||
| 	if (numSems >= maxSems) | ||||
| 		elog(PANIC, "too many semaphores created"); | ||||
| 
 | ||||
| 	ZeroMemory(&sec_attrs, sizeof(sec_attrs)); | ||||
| 	sec_attrs.nLength = sizeof(sec_attrs); | ||||
| 	sec_attrs.lpSecurityDescriptor = NULL; | ||||
| 	sec_attrs.bInheritHandle = TRUE; | ||||
| 
 | ||||
| 	/* We don't need a named semaphore */ | ||||
| 	cur_handle = CreateSemaphore(&sec_attrs, 1, 1, NULL); | ||||
| 	if (cur_handle) | ||||
| 	{ | ||||
| 		/* Successfully done */ | ||||
| 		*sema = cur_handle; | ||||
| 		mySemSet[numSems++] = cur_handle; | ||||
| 	} | ||||
| 	else | ||||
| 		ereport(PANIC, | ||||
| 				(errmsg("could not create semaphore: error code %d", (int)GetLastError()))); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * PGSemaphoreReset | ||||
|  * | ||||
|  * Reset a previously-initialized PGSemaphore to have count 0 | ||||
|  */ | ||||
| void PGSemaphoreReset(PGSemaphore sema) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * There's no direct API for this in Win32, so we have to ratchet the | ||||
| 	 * semaphore down to 0 with repeated trylock's. | ||||
| 	 */ | ||||
| 	while (PGSemaphoreTryLock(sema)); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * PGSemaphoreLock | ||||
|  * | ||||
|  * Lock a semaphore (decrement count), blocking if count would be < 0. | ||||
|  * Serve the interrupt if interruptOK is true. | ||||
|  */ | ||||
| void PGSemaphoreLock(PGSemaphore sema, bool interruptOK) | ||||
| { | ||||
| 	DWORD		ret; | ||||
| 	HANDLE		wh[2]; | ||||
| 
 | ||||
| 	wh[0] = *sema; | ||||
| 	wh[1] = pgwin32_signal_event; | ||||
| 
 | ||||
| 	do | ||||
| 	{ | ||||
| 		ImmediateInterruptOK = interruptOK; | ||||
| 		CHECK_FOR_INTERRUPTS(); | ||||
| 
 | ||||
| 		errno = 0; | ||||
| 		ret = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE); | ||||
| 
 | ||||
| 		if (ret == WAIT_OBJECT_0) | ||||
| 		{ | ||||
| 			/* We got it! */ | ||||
| 			return; | ||||
| 		} | ||||
| 		else if (ret == WAIT_OBJECT_0 + 1) | ||||
| 		{ | ||||
| 			/* Signal event is set - we have a signal to deliver */ | ||||
| 			pgwin32_dispatch_queued_signals(); | ||||
| 			errno = EINTR; | ||||
| 		} | ||||
| 		else | ||||
| 			/* Otherwise we are in trouble */ | ||||
| 			errno = EIDRM; | ||||
| 
 | ||||
| 		ImmediateInterruptOK = false; | ||||
| 	} while (errno == EINTR); | ||||
| 
 | ||||
| 	if (errno != 0) | ||||
| 		ereport(FATAL, | ||||
| 				(errmsg("could not lock semaphore: error code %d", (int) GetLastError()))); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * PGSemaphoreUnlock | ||||
|  * | ||||
|  * Unlock a semaphore (increment count) | ||||
|  */ | ||||
| void PGSemaphoreUnlock(PGSemaphore sema) | ||||
| { | ||||
| 	if (!ReleaseSemaphore(*sema, 1, NULL)) | ||||
| 		ereport(FATAL, | ||||
| 				(errmsg("could not unlock semaphore: error code %d", (int) GetLastError()))); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * PGSemaphoreTryLock | ||||
|  * | ||||
|  * Lock a semaphore only if able to do so without blocking | ||||
|  */ | ||||
| bool PGSemaphoreTryLock(PGSemaphore sema) | ||||
| { | ||||
| 	DWORD		ret; | ||||
| 
 | ||||
| 	ret = WaitForSingleObject(*sema, 0); | ||||
| 
 | ||||
| 	if (ret == WAIT_OBJECT_0) | ||||
| 	{ | ||||
| 		/* We got it! */ | ||||
| 		return true; | ||||
| 	} | ||||
| 	else if (ret == WAIT_TIMEOUT) | ||||
| 	{ | ||||
| 		/* Can't get it */ | ||||
| 		errno = EAGAIN; | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Otherwise we are in trouble */ | ||||
| 	ereport(FATAL, | ||||
| 			(errmsg("could not try-lock semaphore: error code %d", (int) GetLastError()))); | ||||
| 	 | ||||
| 	/* keep compiler quiet */ | ||||
| 	return false; | ||||
| } | ||||
| @ -13,7 +13,7 @@ | ||||
|  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $PostgreSQL: pgsql/src/include/storage/pg_sema.h,v 1.8 2006/03/05 15:58:59 momjian Exp $ | ||||
|  * $PostgreSQL: pgsql/src/include/storage/pg_sema.h,v 1.9 2006/04/29 16:34:41 momjian Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -54,6 +54,11 @@ typedef struct PGSemaphoreData | ||||
| } PGSemaphoreData; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_WIN32_SEMAPHORES | ||||
| 
 | ||||
| typedef HANDLE	PGSemaphoreData; | ||||
| #endif | ||||
| 
 | ||||
| typedef PGSemaphoreData *PGSemaphore; | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user