From 6aad07d270ca2ba42c3083daf7bd640c272ecd4c Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 21 Oct 2005 21:43:46 +0000 Subject: [PATCH] Improve performance of CHECK_FOR_INTERRUPTS() macro on Windows by not doing a kernel call unless there's some evidence of a pending signal. This should bring its performance on Windows into line with the Unix version. Problem diagnosis and patch by Qingqing Zhou. Minor stylistic tweaks by moi ... if it's broken, it's my fault. --- src/backend/port/win32/signal.c | 44 +++++++++++++++++++++++++++++------------ src/include/miscadmin.h | 8 +++++--- src/include/port/win32.h | 10 ++++++++-- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/backend/port/win32/signal.c b/src/backend/port/win32/signal.c index a32427f28f..fa7d8cf6a2 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.12 2005/10/15 02:49:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.13 2005/10/21 21:43:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,18 +15,26 @@ #include +/* + * These are exported for use by the UNBLOCKED_SIGNAL_QUEUE() macro. + * pg_signal_queue must be volatile since it is changed by the signal + * handling thread and inspected without any lock by the main thread. + * pg_signal_mask is only changed by main thread so shouldn't need it. + */ +volatile int pg_signal_queue; +int pg_signal_mask; -/* pg_signal_crit_sec is used to protect only pg_signal_queue. That is the only - * variable that can be accessed from the signal sending threads! */ +HANDLE pgwin32_signal_event; +HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE; + +/* + * pg_signal_crit_sec is used to protect only pg_signal_queue. That is the only + * variable that can be accessed from the signal sending threads! + */ static CRITICAL_SECTION pg_signal_crit_sec; -static int pg_signal_queue; static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT]; static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT]; -static int pg_signal_mask; - -DLLIMPORT HANDLE pgwin32_signal_event; -HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE; /* Signal handling thread function */ @@ -81,21 +89,31 @@ pgwin32_signal_initialize(void) (errmsg_internal("failed to set console control handler"))); } +/* + * 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 +/* + * Dispatch all signals currently queued and not blocked * Blocked signals are ignored, and will be fired at the time of - * the sigsetmask() call. */ + * the sigsetmask() call. + */ void pgwin32_dispatch_queued_signals(void) { int i; EnterCriticalSection(&pg_signal_crit_sec); - while (pg_signal_queue & ~pg_signal_mask) + while (UNBLOCKED_SIGNAL_QUEUE()) { /* One or more unblocked signals queued for execution */ - - int exec_mask = pg_signal_queue & ~pg_signal_mask; + int exec_mask = UNBLOCKED_SIGNAL_QUEUE(); for (i = 0; i < PG_SIGNAL_COUNT; i++) { diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index a2a802cacc..10f7519755 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.180 2005/10/15 02:49:41 momjian Exp $ + * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.181 2005/10/21 21:43:46 tgl Exp $ * * NOTES * some of the information in this file should be moved to other files. @@ -83,15 +83,17 @@ do { \ if (InterruptPending) \ ProcessInterrupts(); \ } while(0) + #else /* WIN32 */ #define CHECK_FOR_INTERRUPTS() \ do { \ - if (WaitForSingleObjectEx(pgwin32_signal_event,0,TRUE) == WAIT_OBJECT_0) \ - pgwin32_dispatch_queued_signals(); \ + if (UNBLOCKED_SIGNAL_QUEUE()) \ + pgwin32_check_queued_signals(); \ if (InterruptPending) \ ProcessInterrupts(); \ } while(0) + #endif /* WIN32 */ diff --git a/src/include/port/win32.h b/src/include/port/win32.h index 44c449443a..9d1a6da6c6 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.47 2005/10/15 02:49:45 momjian Exp $ */ +/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.48 2005/10/21 21:43:46 tgl Exp $ */ /* undefine and redefine after #include */ #undef mkdir @@ -214,11 +214,17 @@ typedef int pid_t; /* In backend/port/win32/signal.c */ -extern DLLIMPORT HANDLE pgwin32_signal_event; +extern DLLIMPORT volatile int pg_signal_queue; +extern DLLIMPORT int pg_signal_mask; +extern HANDLE pgwin32_signal_event; extern HANDLE pgwin32_initial_signal_pipe; +#define UNBLOCKED_SIGNAL_QUEUE() (pg_signal_queue & ~pg_signal_mask) + + 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); -- 2.11.0