Attached is a patch for Win32 semaphore reimplementation per discussion
with Tom and Magnus. Basically it implements the interfaces defined in
pg_sema.h using unnamed semaphores in Win32. Change in configure.in is
needed to support this modification.

Regards,
Qingqing
Index: configure.in
===================================================================
RCS file: /projects/cvsroot/pgsql/configure.in,v
retrieving revision 1.456
diff -c -r1.456 configure.in
*** configure.in        7 Apr 2006 17:50:03 -0000       1.456
--- configure.in        20 Apr 2006 11:55:16 -0000
***************
*** 1253,1269 ****
  
  
  # 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.])
      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
  
  
--- 1253,1274 ----
  
  
  # Select semaphore implementation type.
! 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
!     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
  
  
Index: src/include/storage/pg_sema.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/storage/pg_sema.h,v
retrieving revision 1.8
diff -c -r1.8 pg_sema.h
*** src/include/storage/pg_sema.h       5 Mar 2006 15:58:59 -0000       1.8
--- src/include/storage/pg_sema.h       20 Apr 2006 11:56:58 -0000
***************
*** 54,59 ****
--- 54,64 ----
  } PGSemaphoreData;
  #endif
  
+ #ifdef USE_WIN32_SEMAPHORES
+ 
+ typedef HANDLE        PGSemaphoreData;
+ #endif
+ 
  typedef PGSemaphoreData *PGSemaphore;
  
  
/*-------------------------------------------------------------------------

 *

 * win32_sema.c

 *        Microsoft Windows Win32 Semaphores Emulation

 *

 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group

 *

 * IDENTIFICATION

 *        $Header$

 *

 *-------------------------------------------------------------------------

 */



#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.

 */

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;

}
---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings

Reply via email to