Re: [PATCHES] Win32 CHECK_FOR_INTERRUPTS() performance - Mailing list pgsql-hackers
From | Qingqing Zhou |
---|---|
Subject | Re: [PATCHES] Win32 CHECK_FOR_INTERRUPTS() performance |
Date | |
Msg-id | Pine.LNX.4.58.0510222325400.17162@eon.cs Whole thread Raw |
In response to | Re: [PATCHES] Win32 CHECK_FOR_INTERRUPTS() performance (Qingqing Zhou <zhouqq@cs.toronto.edu>) |
List | pgsql-hackers |
Here is the full patch of the timer implemenation with threading safty added. Basic test is by several rounds of "make check" and threading safty test is by a SQL file with many lines of "set statement_timeout = x". I don't know if there are any corner cases that I should consider, if any, let me know. Regards, Qingqing --- Index: timer.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/port/win32/timer.c,v retrieving revision 1.5 diff -c -r1.5 timer.c *** timer.c 31 Dec 2004 22:00:37 -0000 1.5 --- timer.c 23 Oct 2005 03:04:53 -0000 *************** *** 15,22 **** --- 15,31 ---- #include "libpq/pqsignal.h" + /* Communication area of timer settings */ + typedef struct timerCA{ + int which; + struct itimerval value; + HANDLE event; + CRITICAL_SECTION crit_sec; + }timerCA; + static timerCA timerCommArea; static HANDLE timerHandle = INVALID_HANDLE_VALUE; + static HANDLE timerThreadHandle = INVALID_HANDLE_VALUE; static VOID CALLBACK timer_completion(LPVOID arg, DWORD timeLow, DWORD timeHigh) *************** *** 24,43 **** pg_queue_signal(SIGALRM); } - /* * Limitations of this implementation: * - * - Does not support setting ovalue * - Does not support interval timer (value->it_interval) * - Only supports ITIMER_REAL */ ! 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); --- 33,49 ---- pg_queue_signal(SIGALRM); } /* * Limitations of this implementation: * * - Does not support interval timer (value->it_interval) * - Only supportsITIMER_REAL */ ! static int ! do_setitimer(int which, const struct itimerval * value) { LARGE_INTEGER dueTime; Assert(value != NULL); Assert(value->it_interval.tv_sec == 0 && value->it_interval.tv_usec == 0); Assert(which== ITIMER_REAL); *************** *** 69,71 **** --- 75,136 ---- return 0; } + + /* Timer ticking thread */ + static DWORD WINAPI + pg_timer_thread(LPVOID param) + { + Assert(param == NULL); + + for (;;) + { + if (WaitForSingleObjectEx(timerCommArea.event, INFINITE, TRUE) == WAIT_OBJECT_0) + { + EnterCriticalSection(&timerCommArea.crit_sec); + do_setitimer(timerCommArea.which, + &timerCommArea.value); + ResetEvent(timerCommArea.event); + LeaveCriticalSection(&timerCommArea.crit_sec); + } + } + + return 0; + } + + /* + * 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) + { + Assert(value != NULL); + + if (timerThreadHandle == INVALID_HANDLE_VALUE) + { + /* 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 timer event: %d", (int) GetLastError()))); + MemSet(&timerCommArea.value, 0, sizeof(struct itimerval)); + InitializeCriticalSection(&timerCommArea.crit_sec); + + 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()))); + } + + /* Request the timer thread to change settings */ + EnterCriticalSection(&timerCommArea.crit_sec); + if (ovalue) + *ovalue = timerCommArea.value; + timerCommArea.which = which; + timerCommArea.value = *value; + LeaveCriticalSection(&timerCommArea.crit_sec); + SetEvent(timerCommArea.event); + + /* Timer thread will handle possible errors */ + return 0; + }
pgsql-hackers by date: