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.
This commit is contained in:
Tom Lane 2005-10-21 21:43:46 +00:00
parent fdff883aca
commit 6aad07d270
3 changed files with 44 additions and 18 deletions

View File

@ -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 <libpq/pqsignal.h>
/*
* 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++)
{

View File

@ -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 */

View File

@ -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);