Index: src/backend/port/win32/timer.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/port/win32/timer.c,v
retrieving revision 1.5
diff -c -r1.5 timer.c
*** src/backend/port/win32/timer.c	31 Dec 2004 22:00:37 -0000	1.5
--- src/backend/port/win32/timer.c	23 Oct 2005 15:17:33 -0000
***************
*** 3,8 ****
--- 3,13 ----
   * timer.c
   *	  Microsoft Windows Win32 Timer Implementation
   *
+  *    Limitations of this implementation:
+  *
+  *    - Does not support interval timer (value->it_interval)
+  *    - Only supports ITIMER_REAL
+  *
   * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
   *
   * IDENTIFICATION
***************
*** 15,71 ****
  
  #include "libpq/pqsignal.h"
  
  
! static HANDLE timerHandle = INVALID_HANDLE_VALUE;
  
! static VOID CALLBACK
! timer_completion(LPVOID arg, DWORD timeLow, DWORD timeHigh)
! {
! 	pg_queue_signal(SIGALRM);
! }
  
  
  /*
!  * Limitations of this implementation:
!  *
!  * - Does not support setting ovalue
!  * - Does not support interval timer (value->it_interval)
!  * - Only supports ITIMER_REAL
   */
  int
  setitimer(int which, const struct itimerval * value, struct itimerval * ovalue)
  {
- 	LARGE_INTEGER dueTime;
- 
- 	Assert(ovalue == NULL);
  	Assert(value != NULL);
  	Assert(value->it_interval.tv_sec == 0 && value->it_interval.tv_usec == 0);
  	Assert(which == ITIMER_REAL);
  
! 	if (timerHandle == INVALID_HANDLE_VALUE)
  	{
! 		/* First call in this backend, create new timer object */
! 		timerHandle = CreateWaitableTimer(NULL, TRUE, NULL);
! 		if (timerHandle == NULL)
  			ereport(FATAL,
! 					(errmsg_internal("failed to create waitable timer: %i", (int) GetLastError())));
! 	}
  
! 	if (value->it_value.tv_sec == 0 &&
! 		value->it_value.tv_usec == 0)
! 	{
! 		/* Turn timer off */
! 		CancelWaitableTimer(timerHandle);
! 		return 0;
  	}
  
! 	/* Negative time to SetWaitableTimer means relative time */
! 	dueTime.QuadPart = -(value->it_value.tv_usec * 10 + value->it_value.tv_sec * 10000000L);
! 
! 	/* Turn timer on, or change timer */
! 	if (!SetWaitableTimer(timerHandle, &dueTime, 0, timer_completion, NULL, FALSE))
! 		ereport(FATAL,
! 				(errmsg_internal("failed to set waitable timer: %i", (int) GetLastError())));
  
  	return 0;
  }
--- 20,112 ----
  
  #include "libpq/pqsignal.h"
  
+ /* Communication area of timer settings */
+ typedef struct timerCA{
+ 	struct itimerval value;
+ 	HANDLE event;
+ 	CRITICAL_SECTION crit_sec;
+ }timerCA;
+ 
+ static timerCA timerCommArea;
+ static HANDLE timerThreadHandle = INVALID_HANDLE_VALUE;
+ 
+ /* Timer ticking thread */
+ static DWORD WINAPI
+ pg_timer_thread(LPVOID param)
+ {
+     DWORD waittime;
  
! 	Assert(param == NULL);
!     
!     waittime = INFINITE;
  
! 	for (;;)
! 	{
!         int r;
! 
!         r = WaitForSingleObjectEx(timerCommArea.event, waittime, FALSE);
!         if (r == WAIT_OBJECT_0)
!         {
!             /* Event signalled, change the timer */
!             EnterCriticalSection(&timerCommArea.crit_sec);
!             if (timerCommArea.value.it_value.tv_sec == 0 &&
!                 timerCommArea.value.it_value.tv_usec == 0)
!                 waittime = INFINITE; /* Cancel the timer */
!             else
!                 waittime = timerCommArea.value.it_value.tv_usec / 10 + timerCommArea.value.it_value.tv_sec * 1000;
!             ResetEvent(timerCommArea.event);
!             LeaveCriticalSection(&timerCommArea.crit_sec);
!         }
!         else if (r == WAIT_TIMEOUT)
!         {
!             /* Timeout expired, signal timer and turn it off */
!             pg_queue_signal(SIGALRM);
!             waittime = INFINITE;
!         }
!         else
!         {
!             /* Should never happen */
!             Assert(false);
!         }
! 	}
  
+ 	return 0;
+ }
  
  /*
!  * Win32 setitimer emulation by creating a persistent thread
!  * to handle the timer setting and notification upon timeout.
   */
  int
  setitimer(int which, const struct itimerval * value, struct itimerval * ovalue)
  {
  	Assert(value != NULL);
  	Assert(value->it_interval.tv_sec == 0 && value->it_interval.tv_usec == 0);
  	Assert(which == ITIMER_REAL);
  
! 	if (timerThreadHandle == INVALID_HANDLE_VALUE)
  	{
! 		/* First call in this backend, create event and the timer thread */
! 		timerCommArea.event = CreateEvent(NULL, TRUE, FALSE, NULL);
! 		if (timerCommArea.event == NULL)
  			ereport(FATAL,
! 				(errmsg_internal("failed to create timer event: %d", (int) GetLastError())));
! 		MemSet(&timerCommArea.value, 0, sizeof(struct itimerval));
! 		InitializeCriticalSection(&timerCommArea.crit_sec);
  
! 		timerThreadHandle = CreateThread(NULL, 0, pg_timer_thread, NULL, 0, NULL);
! 		if (timerThreadHandle == INVALID_HANDLE_VALUE)
! 			ereport(FATAL,
! 				(errmsg_internal("failed to create timer thread: %d", (int) GetLastError())));
  	}
  
! 	/* Request the timer thread to change settings */
! 	EnterCriticalSection(&timerCommArea.crit_sec);
! 	if (ovalue)
! 		*ovalue = timerCommArea.value;
! 	timerCommArea.value = *value;
! 	LeaveCriticalSection(&timerCommArea.crit_sec);
! 	SetEvent(timerCommArea.event);
  
  	return 0;
  }
Index: src/include/miscadmin.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/miscadmin.h,v
retrieving revision 1.182
diff -c -r1.182 miscadmin.h
*** src/include/miscadmin.h	22 Oct 2005 17:09:48 -0000	1.182
--- src/include/miscadmin.h	23 Oct 2005 15:07:54 -0000
***************
*** 88,94 ****
  
  #define CHECK_FOR_INTERRUPTS() \
  do { \
! 	pgwin32_check_queued_signals(); \
  	if (InterruptPending) \
  		ProcessInterrupts(); \
  } while(0)
--- 88,95 ----
  
  #define CHECK_FOR_INTERRUPTS() \
  do { \
!     if (UNBLOCKED_SIGNAL_QUEUE()) \
!     	pgwin32_check_queued_signals(); \
  	if (InterruptPending) \
  		ProcessInterrupts(); \
  } while(0)
