1 /*-------------------------------------------------------------------------
4 * Microsoft Windows Win32 Timer Implementation
6 * Limitations of this implementation:
8 * - Does not support interval timer (value->it_interval)
9 * - Only supports ITIMER_REAL
11 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
16 *-------------------------------------------------------------------------
21 #include "libpq/pqsignal.h"
24 /* Communication area for inter-thread communication */
25 typedef struct timerCA
27 struct itimerval value
;
29 CRITICAL_SECTION crit_sec
;
32 static timerCA timerCommArea
;
33 static HANDLE timerThreadHandle
= INVALID_HANDLE_VALUE
;
36 /* Timer management thread */
38 pg_timer_thread(LPVOID param
)
42 Assert(param
== NULL
);
50 r
= WaitForSingleObjectEx(timerCommArea
.event
, waittime
, FALSE
);
51 if (r
== WAIT_OBJECT_0
)
53 /* Event signalled from main thread, change the timer */
54 EnterCriticalSection(&timerCommArea
.crit_sec
);
55 if (timerCommArea
.value
.it_value
.tv_sec
== 0 &&
56 timerCommArea
.value
.it_value
.tv_usec
== 0)
57 waittime
= INFINITE
; /* Cancel the interrupt */
60 /* WaitForSingleObjectEx() uses milliseconds, round up */
61 waittime
= (timerCommArea
.value
.it_value
.tv_usec
+ 999) / 1000 +
62 timerCommArea
.value
.it_value
.tv_sec
* 1000;
64 ResetEvent(timerCommArea
.event
);
65 LeaveCriticalSection(&timerCommArea
.crit_sec
);
67 else if (r
== WAIT_TIMEOUT
)
69 /* Timeout expired, signal SIGALRM and turn it off */
70 pg_queue_signal(SIGALRM
);
75 /* Should never happen */
84 * Win32 setitimer emulation by creating a persistent thread
85 * to handle the timer setting and notification upon timeout.
88 setitimer(int which
, const struct itimerval
* value
, struct itimerval
* ovalue
)
90 Assert(value
!= NULL
);
91 Assert(value
->it_interval
.tv_sec
== 0 && value
->it_interval
.tv_usec
== 0);
92 Assert(which
== ITIMER_REAL
);
94 if (timerThreadHandle
== INVALID_HANDLE_VALUE
)
96 /* First call in this backend, create event and the timer thread */
97 timerCommArea
.event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
98 if (timerCommArea
.event
== NULL
)
100 (errmsg_internal("failed to create timer event: %d",
101 (int) GetLastError())));
103 MemSet(&timerCommArea
.value
, 0, sizeof(struct itimerval
));
105 InitializeCriticalSection(&timerCommArea
.crit_sec
);
107 timerThreadHandle
= CreateThread(NULL
, 0, pg_timer_thread
, NULL
, 0, NULL
);
108 if (timerThreadHandle
== INVALID_HANDLE_VALUE
)
110 (errmsg_internal("failed to create timer thread: %d",
111 (int) GetLastError())));
114 /* Request the timer thread to change settings */
115 EnterCriticalSection(&timerCommArea
.crit_sec
);
117 *ovalue
= timerCommArea
.value
;
118 timerCommArea
.value
= *value
;
119 LeaveCriticalSection(&timerCommArea
.crit_sec
);
120 SetEvent(timerCommArea
.event
);