Improve performance of CHECK_FOR_INTERRUPTS() macro on Windows by not doing
authorTom Lane <[email protected]>
Fri, 21 Oct 2005 21:43:46 +0000 (21:43 +0000)
committerTom Lane <[email protected]>
Fri, 21 Oct 2005 21:43:46 +0000 (21:43 +0000)
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
src/include/miscadmin.h
src/include/port/win32.h

index 28ce27d5c27e1c61c1862053ec04ee1ec04c78b0..4669002b23fe74282a04d6513f5c8676894c29f0 100644 (file)
 
 #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++)
                {
index de8f2f83f762c04e7731200d0a8d6776fba18bed..f2a49db4b505b6c718dbcd26bfbc0424aee0a5f1 100644 (file)
@@ -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 */
 
 
index 9c832f05d3c13ef2e912f7414fbaa8fcffa71c06..16928d767f4489fd2c8eb405ccae30ee81281758 100644 (file)
@@ -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);