Обсуждение: pg_usleep
Tom Lane wrote:
>Andrew Dunstan <andrew@dunslane.net> writes:
>
>
>>I wrote:
>>
>>
>>>There are a couple of other places where [select()] is used for small
>>>sleeps (storage/lmgr/s_lock.c and access/transam/xact.c) -
>>>
>>>
>
>
>
>>What is the preferred way to handle these 2 cases? We could handle them
>>with #ifdef'd code inline, or create a new function pg_usleep(), or
>>possibly handle it with conditional macros inline. If a new function or
>>macro, where should they go?
>>
>>
>
>I'd go with a new function. There is no reason to try to "optimize"
>this code by putting it inline; if you're trying to delay, another few
>nanoseconds to enter a subroutine doesn't matter.
>
>As for where, maybe make a new file in src/port/. That would make it
>relatively easy to use the same function in client-side code if we
>needed to.
>
>
>
patch + new file attached. Haven't tested on Windows, but should be fine.
cheers
andrew
/*-------------------------------------------------------------------------
*
* pg_usleep.c
* platform independent version of usleep
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
* Uses select() everywhere except for Windows, where it doesn't work
*
* IDENTIFICATION
* $PostgreSQL$
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <sys/time.h>
#endif
void
pg_usleep (unsigned int usecs)
{
#ifdef WIN32
Sleep(usecs < 500 : 1 : (usecs+500)/ 1000);
#else
struct timeval tv;
tv.tv_sec = usecs / 1000000;
tv.tv_usec = usecs % 1000000;
select(0,NULL,NULL,NULL,&tv);
#endif
}
Index: src/Makefile.global.in
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/Makefile.global.in,v
retrieving revision 1.172
diff -c -w -r1.172 Makefile.global.in
*** src/Makefile.global.in 19 Dec 2003 23:29:15 -0000 1.172
--- src/Makefile.global.in 30 Dec 2003 18:50:56 -0000
***************
*** 342,348 ****
#
# substitute implementations of the C library
! LIBOBJS = @LIBOBJS@ path.o sprompt.o thread.o
ifneq (,$(LIBOBJS))
LIBS += -lpgport
--- 342,348 ----
#
# substitute implementations of the C library
! LIBOBJS = @LIBOBJS@ path.o sprompt.o thread.o pg_usleep.o
ifneq (,$(LIBOBJS))
LIBS += -lpgport
Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/access/transam/xact.c,v
retrieving revision 1.158
diff -c -w -r1.158 xact.c
*** src/backend/access/transam/xact.c 2 Dec 2003 19:26:47 -0000 1.158
--- src/backend/access/transam/xact.c 30 Dec 2003 18:50:56 -0000
***************
*** 562,572 ****
if (CommitDelay > 0 && enableFsync &&
CountActiveBackends() >= CommitSiblings)
{
! struct timeval delay;
!
! delay.tv_sec = 0;
! delay.tv_usec = CommitDelay;
! (void) select(0, NULL, NULL, NULL, &delay);
}
XLogFlush(recptr);
--- 562,569 ----
if (CommitDelay > 0 && enableFsync &&
CountActiveBackends() >= CommitSiblings)
{
! /* call platform independent usleep */
! pg_usleep(CommitDelay);
}
XLogFlush(recptr);
Index: src/backend/storage/lmgr/s_lock.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/lmgr/s_lock.c,v
retrieving revision 1.23
diff -c -w -r1.23 s_lock.c
*** src/backend/storage/lmgr/s_lock.c 27 Dec 2003 20:58:58 -0000 1.23
--- src/backend/storage/lmgr/s_lock.c 30 Dec 2003 18:50:56 -0000
***************
*** 46,52 ****
s_lock(volatile slock_t *lock, const char *file, int line)
{
/*
! * We loop tightly for awhile, then delay using select() and try
* again. Preferably, "awhile" should be a small multiple of the
* maximum time we expect a spinlock to be held. 100 iterations seems
* about right. In most multi-CPU scenarios, the spinlock is probably
--- 46,52 ----
s_lock(volatile slock_t *lock, const char *file, int line)
{
/*
! * We loop tightly for awhile, then delay using pg_usleep() and try
* again. Preferably, "awhile" should be a small multiple of the
* maximum time we expect a spinlock to be held. 100 iterations seems
* about right. In most multi-CPU scenarios, the spinlock is probably
***************
*** 84,90 ****
int spins = 0;
int delays = 0;
int cur_delay = MIN_DELAY_CSEC;
- struct timeval delay;
while (TAS(lock))
{
--- 84,89 ----
***************
*** 97,105 ****
if (++delays > NUM_DELAYS)
s_lock_stuck(lock, file, line);
! delay.tv_sec = cur_delay / 100;
! delay.tv_usec = (cur_delay % 100) * 10000;
! (void) select(0, NULL, NULL, NULL, &delay);
#if defined(S_LOCK_TEST)
fprintf(stdout, "*");
--- 96,102 ----
if (++delays > NUM_DELAYS)
s_lock_stuck(lock, file, line);
! pg_usleep(cur_delay * 10000);
#if defined(S_LOCK_TEST)
fprintf(stdout, "*");
Index: src/include/port.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/port.h,v
retrieving revision 1.15
diff -c -w -r1.15 port.h
*** src/include/port.h 29 Nov 2003 22:40:53 -0000 1.15
--- src/include/port.h 30 Dec 2003 18:50:56 -0000
***************
*** 122,124 ****
--- 122,127 ----
char *buffer, size_t buflen,
struct hostent **result,
int *herrno);
+
+ extern void pg_usleep(unsigned int usecs);
+
> patch + new file attached. Haven't tested on Windows, but > should be fine. Would be, except for a small typo (conditional operator has an additional : instead of a ?). Also, we might want to change to SleepEx, depending on how we eventually get signals implemented, but that's a story for another day. This, + the pipe() patch from a couple days ago, means we can just about tick off the "Problems with select()" item on the Win32 TODO list :-) Cheers, Claudio --- Certain disclaimers and policies apply to all email sent from Memetrics. For the full text of these disclaimers and policies see <a href="http://www.memetrics.com/emailpolicy.html">http://www.memetrics.com/em ailpolicy.html</a>
Claudio Natoli said: > > >> patch + new file attached. Haven't tested on Windows, but >> should be fine. > > Would be, except for a small typo (conditional operator has an > additional : instead of a ?). Darnit. please fix when applying. > Also, we might want to change to SleepEx, > depending on how we eventually get signals implemented, but that's a > story for another day. > Yes. If we use a separate thread to catch signal events then only calls in that thread would need to use SleepEx, no? Anyway, as you say if necessary it can be adjusted later. > This, + the pipe() patch from a couple days ago, means we can just > about tick off the "Problems with select()" item on the Win32 TODO list > :-) > That was the intention :-) cheers andrew
Andrew Dunstan wrote: > Claudio Natoli said: > > > > > >> patch + new file attached. Haven't tested on Windows, but > >> should be fine. > > > > Would be, except for a small typo (conditional operator has an > > additional : instead of a ?). > > Darnit. please fix when applying. > > > Also, we might want to change to SleepEx, > > depending on how we eventually get signals implemented, but that's a > > story for another day. > > > > Yes. If we use a separate thread to catch signal events then only calls in > that thread would need to use SleepEx, no? Anyway, as you say if necessary > it can be adjusted later. > > > This, + the pipe() patch from a couple days ago, means we can just > > about tick off the "Problems with select()" item on the Win32 TODO list > > :-) > > > > That was the intention :-) OK, Sleep() win32 patch attached and applied. We already had PG_DELAY in milliseconds, and no one was going anywhere near 2000 seconds (overflow), so I just converted it to PG_USLEEP and used it consistenly, with the Win32 Sleep() call added. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 Index: src/backend/access/transam/xact.c =================================================================== RCS file: /cvsroot/pgsql-server/src/backend/access/transam/xact.c,v retrieving revision 1.159 diff -c -c -r1.159 xact.c *** src/backend/access/transam/xact.c 7 Jan 2004 18:56:24 -0000 1.159 --- src/backend/access/transam/xact.c 9 Jan 2004 20:59:04 -0000 *************** *** 561,573 **** */ if (CommitDelay > 0 && enableFsync && CountActiveBackends() >= CommitSiblings) ! { ! struct timeval delay; ! ! delay.tv_sec = 0; ! delay.tv_usec = CommitDelay; ! (void) select(0, NULL, NULL, NULL, &delay); ! } XLogFlush(recptr); } --- 561,567 ---- */ if (CommitDelay > 0 && enableFsync && CountActiveBackends() >= CommitSiblings) ! PG_USLEEP(CommitDelay); XLogFlush(recptr); } Index: src/backend/storage/buffer/bufmgr.c =================================================================== RCS file: /cvsroot/pgsql-server/src/backend/storage/buffer/bufmgr.c,v retrieving revision 1.151 diff -c -c -r1.151 bufmgr.c *** src/backend/storage/buffer/bufmgr.c 7 Jan 2004 18:56:27 -0000 1.151 --- src/backend/storage/buffer/bufmgr.c 9 Jan 2004 20:59:05 -0000 *************** *** 1031,1039 **** * there was nothing to do at all. */ if (n > 0) ! { ! PG_DELAY(BgWriterDelay); ! } else sleep(10); } --- 1031,1037 ---- * there was nothing to do at all. */ if (n > 0) ! PG_USLEEP(BgWriterDelay * 1000); else sleep(10); } Index: src/backend/storage/lmgr/s_lock.c =================================================================== RCS file: /cvsroot/pgsql-server/src/backend/storage/lmgr/s_lock.c,v retrieving revision 1.23 diff -c -c -r1.23 s_lock.c *** src/backend/storage/lmgr/s_lock.c 27 Dec 2003 20:58:58 -0000 1.23 --- src/backend/storage/lmgr/s_lock.c 9 Jan 2004 20:59:06 -0000 *************** *** 19,25 **** #include <unistd.h> #include "storage/s_lock.h" ! /* * s_lock_stuck() - complain about a stuck spinlock --- 19,25 ---- #include <unistd.h> #include "storage/s_lock.h" ! #include "miscadmin.h" /* * s_lock_stuck() - complain about a stuck spinlock *************** *** 84,90 **** int spins = 0; int delays = 0; int cur_delay = MIN_DELAY_CSEC; - struct timeval delay; while (TAS(lock)) { --- 84,89 ---- *************** *** 97,105 **** if (++delays > NUM_DELAYS) s_lock_stuck(lock, file, line); ! delay.tv_sec = cur_delay / 100; ! delay.tv_usec = (cur_delay % 100) * 10000; ! (void) select(0, NULL, NULL, NULL, &delay); #if defined(S_LOCK_TEST) fprintf(stdout, "*"); --- 96,102 ---- if (++delays > NUM_DELAYS) s_lock_stuck(lock, file, line); ! PG_USLEEP(cur_delay * 10000); #if defined(S_LOCK_TEST) fprintf(stdout, "*"); Index: src/include/miscadmin.h =================================================================== RCS file: /cvsroot/pgsql-server/src/include/miscadmin.h,v retrieving revision 1.142 diff -c -c -r1.142 miscadmin.h *** src/include/miscadmin.h 6 Jan 2004 23:15:22 -0000 1.142 --- src/include/miscadmin.h 9 Jan 2004 20:59:06 -0000 *************** *** 75,108 **** extern void ProcessInterrupts(void); #define CHECK_FOR_INTERRUPTS() \ ! do { \ ! if (InterruptPending) \ ! ProcessInterrupts(); \ ! } while(0) #define HOLD_INTERRUPTS() (InterruptHoldoffCount++) #define RESUME_INTERRUPTS() \ ! do { \ ! Assert(InterruptHoldoffCount > 0); \ ! InterruptHoldoffCount--; \ ! } while(0) #define START_CRIT_SECTION() (CritSectionCount++) #define END_CRIT_SECTION() \ ! do { \ ! Assert(CritSectionCount > 0); \ ! CritSectionCount--; \ ! } while(0) ! #define PG_DELAY(_msec) \ ! { \ struct timeval delay; \ ! delay.tv_sec = (_msec) / 1000; \ ! delay.tv_usec = ((_msec) % 1000) * 1000; \ (void) select(0, NULL, NULL, NULL, &delay); \ ! } /***************************************************************************** * globals.h -- * --- 75,114 ---- extern void ProcessInterrupts(void); #define CHECK_FOR_INTERRUPTS() \ ! do { \ ! if (InterruptPending) \ ! ProcessInterrupts(); \ ! } while(0) #define HOLD_INTERRUPTS() (InterruptHoldoffCount++) #define RESUME_INTERRUPTS() \ ! do { \ ! Assert(InterruptHoldoffCount > 0); \ ! InterruptHoldoffCount--; \ ! } while(0) #define START_CRIT_SECTION() (CritSectionCount++) #define END_CRIT_SECTION() \ ! do { \ ! Assert(CritSectionCount > 0); \ ! CritSectionCount--; \ ! } while(0) ! #define PG_USLEEP(_usec) \ ! do { \ ! #ifndef WIN32 ! /* This will overflow on systems with 32-bit ints for > ~2000 secs */ \ struct timeval delay; \ ! \ ! delay.tv_sec = (_usec) / 1000000; \ ! delay.tv_usec = ((_usec) % 1000000); \ (void) select(0, NULL, NULL, NULL, &delay); \ ! #else ! Sleep(_usec < 500) ? 1 : (_usec+500)/ 1000); ! #endif ! } while(0) /***************************************************************************** * globals.h -- *