aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-10-25 15:15:16 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-10-25 15:15:16 +0000
commit25777f6fd312b3f3e32edb921d79e3d8c7b499a6 (patch)
treed69976608fc3d97df70ed1f50a944f4e1a2ec036 /src
parentb83547201fb321bca43276911d6839ab7ad7e7f7 (diff)
downloadpostgresql-25777f6fd312b3f3e32edb921d79e3d8c7b499a6.tar.gz
postgresql-25777f6fd312b3f3e32edb921d79e3d8c7b499a6.zip
Fix Windows setitimer() emulation to not depend on delivering an APC
to the main thread. This allows removal of WaitForSingleObjectEx() calls from the main thread, thereby allowing us to re-enable Qingqing Zhou's CHECK_FOR_INTERRUPTS performance improvement. Qingqing, Magnus, et al.
Diffstat (limited to 'src')
-rw-r--r--src/backend/port/win32/signal.c12
-rw-r--r--src/backend/port/win32/socket.c4
-rw-r--r--src/backend/port/win32/timer.c113
-rw-r--r--src/include/miscadmin.h5
-rw-r--r--src/include/port/win32.h3
5 files changed, 87 insertions, 50 deletions
diff --git a/src/backend/port/win32/signal.c b/src/backend/port/win32/signal.c
index fa7d8cf6a2c..3204c9c20e1 100644
--- a/src/backend/port/win32/signal.c
+++ b/src/backend/port/win32/signal.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.13 2005/10/21 21:43:45 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.14 2005/10/25 15:15:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -90,16 +90,6 @@ pgwin32_signal_initialize(void)
}
/*
- * Support routine for CHECK_FOR_INTERRUPTS() macro
- */
-void
-pgwin32_check_queued_signals(void)
-{
- if (WaitForSingleObjectEx(pgwin32_signal_event, 0, TRUE) == WAIT_OBJECT_0)
- pgwin32_dispatch_queued_signals();
-}
-
-/*
* Dispatch all signals currently queued and not blocked
* Blocked signals are ignored, and will be fired at the time of
* the sigsetmask() call.
diff --git a/src/backend/port/win32/socket.c b/src/backend/port/win32/socket.c
index 808977a2374..b4bd121ca94 100644
--- a/src/backend/port/win32/socket.c
+++ b/src/backend/port/win32/socket.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.9 2005/10/15 02:49:23 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/port/win32/socket.c,v 1.10 2005/10/25 15:15:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -93,7 +93,7 @@ TranslateSocketError(void)
static int
pgwin32_poll_signals(void)
{
- if (WaitForSingleObjectEx(pgwin32_signal_event, 0, TRUE) == WAIT_OBJECT_0)
+ if (UNBLOCKED_SIGNAL_QUEUE())
{
pgwin32_dispatch_queued_signals();
errno = EINTR;
diff --git a/src/backend/port/win32/timer.c b/src/backend/port/win32/timer.c
index c31c7bc114e..b6c0b407e6e 100644
--- a/src/backend/port/win32/timer.c
+++ b/src/backend/port/win32/timer.c
@@ -3,10 +3,15 @@
* 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
- * $PostgreSQL: pgsql/src/backend/port/win32/timer.c,v 1.5 2004/12/31 22:00:37 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/port/win32/timer.c,v 1.6 2005/10/25 15:15:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,56 +21,98 @@
#include "libpq/pqsignal.h"
-static HANDLE timerHandle = INVALID_HANDLE_VALUE;
+/* Communication area for inter-thread communication */
+typedef struct timerCA {
+ struct itimerval value;
+ HANDLE event;
+ CRITICAL_SECTION crit_sec;
+} timerCA;
+
+static timerCA timerCommArea;
+static HANDLE timerThreadHandle = INVALID_HANDLE_VALUE;
-static VOID CALLBACK
-timer_completion(LPVOID arg, DWORD timeLow, DWORD timeHigh)
+
+/* Timer management thread */
+static DWORD WINAPI
+pg_timer_thread(LPVOID param)
{
- pg_queue_signal(SIGALRM);
-}
+ DWORD waittime;
+
+ Assert(param == NULL);
+ waittime = INFINITE;
+
+ for (;;)
+ {
+ int r;
+
+ r = WaitForSingleObjectEx(timerCommArea.event, waittime, FALSE);
+ if (r == WAIT_OBJECT_0)
+ {
+ /* Event signalled from main thread, 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 interrupt */
+ 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 SIGALRM and turn it off */
+ pg_queue_signal(SIGALRM);
+ waittime = INFINITE;
+ }
+ else
+ {
+ /* Should never happen */
+ Assert(false);
+ }
+ }
+
+ return 0;
+}
/*
- * Limitations of this implementation:
- *
- * - Does not support setting ovalue
- * - Does not support interval timer (value->it_interval)
- * - Only supports ITIMER_REAL
+ * 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)
{
- 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)
+ if (timerThreadHandle == INVALID_HANDLE_VALUE)
{
- /* First call in this backend, create new timer object */
- timerHandle = CreateWaitableTimer(NULL, TRUE, NULL);
- if (timerHandle == NULL)
+ /* 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 waitable timer: %i", (int) GetLastError())));
- }
+ (errmsg_internal("failed to create timer event: %d",
+ (int) GetLastError())));
- if (value->it_value.tv_sec == 0 &&
- value->it_value.tv_usec == 0)
- {
- /* Turn timer off */
- CancelWaitableTimer(timerHandle);
- return 0;
- }
+ MemSet(&timerCommArea.value, 0, sizeof(struct itimerval));
+
+ InitializeCriticalSection(&timerCommArea.crit_sec);
- /* Negative time to SetWaitableTimer means relative time */
- dueTime.QuadPart = -(value->it_value.tv_usec * 10 + value->it_value.tv_sec * 10000000L);
+ 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())));
+ }
- /* 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())));
+ /* 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;
}
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index f82fffed77c..fc13891e414 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.182 2005/10/22 17:09:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.183 2005/10/25 15:15:16 tgl Exp $
*
* NOTES
* some of the information in this file should be moved to other files.
@@ -88,7 +88,8 @@ do { \
#define CHECK_FOR_INTERRUPTS() \
do { \
- pgwin32_check_queued_signals(); \
+ if (UNBLOCKED_SIGNAL_QUEUE()) \
+ pgwin32_dispatch_queued_signals(); \
if (InterruptPending) \
ProcessInterrupts(); \
} while(0)
diff --git a/src/include/port/win32.h b/src/include/port/win32.h
index 9d1a6da6c6c..5bf6ce208fc 100644
--- a/src/include/port/win32.h
+++ b/src/include/port/win32.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.48 2005/10/21 21:43:46 tgl Exp $ */
+/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.49 2005/10/25 15:15:16 tgl Exp $ */
/* undefine and redefine after #include */
#undef mkdir
@@ -224,7 +224,6 @@ extern HANDLE pgwin32_initial_signal_pipe;
void pgwin32_signal_initialize(void);
HANDLE pgwin32_create_signal_listener(pid_t pid);
-void pgwin32_check_queued_signals(void);
void pgwin32_dispatch_queued_signals(void);
void pg_queue_signal(int signum);