Thread: pg_usleep

pg_usleep

From
Andrew Dunstan
Date:
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);
+

Re: pg_usleep

From
Claudio Natoli
Date:

> 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>

Re: pg_usleep

From
"Andrew Dunstan"
Date:
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





Re: pg_usleep

From
Bruce Momjian
Date:
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 --                                                             *