diff options
author | Sergey Uzhakov <uzhastik@gmail.com> | 2022-06-22 21:23:19 +0300 |
---|---|---|
committer | Sergey Uzhakov <uzhastik@gmail.com> | 2022-06-22 21:23:19 +0300 |
commit | b86c509aaa5b19d5659a4548395a47c9e87826e9 (patch) | |
tree | 98025d7bd574b788f6679b24f91711ea86bf07ae /contrib/libs/postgresql/src/backend/port/win32/timer.c | |
parent | f55ada30d924b55d15fad9001944df1323a9598a (diff) | |
download | ydb-b86c509aaa5b19d5659a4548395a47c9e87826e9.tar.gz |
YQ-1154: allow pg translator in OSS
ref:bc7b8dcc7b45e5f527a87a1bed622dff6f06d41a
Diffstat (limited to 'contrib/libs/postgresql/src/backend/port/win32/timer.c')
-rw-r--r-- | contrib/libs/postgresql/src/backend/port/win32/timer.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/contrib/libs/postgresql/src/backend/port/win32/timer.c b/contrib/libs/postgresql/src/backend/port/win32/timer.c new file mode 100644 index 0000000000..53fdae9468 --- /dev/null +++ b/contrib/libs/postgresql/src/backend/port/win32/timer.c @@ -0,0 +1,121 @@ +/*------------------------------------------------------------------------- + * + * timer.c + * Microsoft Windows Win32 Timer Implementation + * + * Limitations of this implementation: + * + * - Does not support interval timer (value->it_interval) + * - Only supports ITIMER_REAL + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/port/win32/timer.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + + +/* Communication area for inter-thread communication */ +typedef struct timerCA +{ + struct itimerval value; + HANDLE event; + CRITICAL_SECTION crit_sec; +} timerCA; + +static timerCA timerCommArea; +static HANDLE timerThreadHandle = INVALID_HANDLE_VALUE; + + +/* Timer management thread */ +static DWORD WINAPI +pg_timer_thread(LPVOID param) +{ + DWORD waittime; + + Assert(param == NULL); + + waittime = INFINITE; + + for (;;) + { + int r; + + r = WaitForSingleObjectEx(timerCommArea.event, waittime, FALSE); + if (r == WAIT_OBJECT_0) + { + /* Event signaled from main thread, change the timer */ + EnterCriticalSection(&timerCommArea.crit_sec); + if (timerCommArea.value.it_value.tv_sec == 0 && + timerCommArea.value.it_value.tv_usec == 0) + waittime = INFINITE; /* Cancel the interrupt */ + else + { + /* WaitForSingleObjectEx() uses milliseconds, round up */ + waittime = (timerCommArea.value.it_value.tv_usec + 999) / 1000 + + timerCommArea.value.it_value.tv_sec * 1000; + } + ResetEvent(timerCommArea.event); + LeaveCriticalSection(&timerCommArea.crit_sec); + } + else if (r == WAIT_TIMEOUT) + { + /* Timeout expired, signal SIGALRM and turn it off */ + pg_queue_signal(SIGALRM); + waittime = INFINITE; + } + else + { + /* Should never happen */ + Assert(false); + } + } + + 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); + Assert(value->it_interval.tv_sec == 0 && value->it_interval.tv_usec == 0); + Assert(which == ITIMER_REAL); + + 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("could not create timer event: error code %lu", + 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("could not create timer thread: error code %lu", + GetLastError()))); + } + + /* Request the timer thread to change settings */ + EnterCriticalSection(&timerCommArea.crit_sec); + if (ovalue) + *ovalue = timerCommArea.value; + timerCommArea.value = *value; + LeaveCriticalSection(&timerCommArea.crit_sec); + SetEvent(timerCommArea.event); + + return 0; +} |