Thread: s_lock.h cleanup

s_lock.h cleanup

From
Bruce Momjian
Date:
In looking at the VAX ASM problem, I realized that the ASM in s_lock.h
is all formatted differently, making it even more confusing.  I have
applied the following patch to s_lock.h to try and clean it up.

The new standard format is:

    /*
     * Standard __asm__ format:
     *
     *  __asm__(
     *          "command;"
     *          "command;"
     *          "command;"
     *      :   "=r"(_res)          return value, in register
     *      :   "r"(lock)           argument, 'lock pointer', in register
     *      :   "r0");              inline code uses this register
     */

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
? config.log
? config.cache
? config.status
? GNUmakefile
? src/Makefile.custom
? src/GNUmakefile
? src/Makefile.global
? src/log
? src/crtags
? src/backend/postgres
? src/backend/catalog/global.bki
? src/backend/catalog/global.description
? src/backend/catalog/template1.bki
? src/backend/catalog/template1.description
? src/backend/port/Makefile
? src/bin/initdb/initdb
? src/bin/initlocation/initlocation
? src/bin/ipcclean/ipcclean
? src/bin/pg_config/pg_config
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/pg_dump
? src/bin/pg_dump/pg_restore
? src/bin/pg_dump/pg_dumpall
? src/bin/pg_id/pg_id
? src/bin/pg_passwd/pg_passwd
? src/bin/pgaccess/pgaccess
? src/bin/pgtclsh/Makefile.tkdefs
? src/bin/pgtclsh/Makefile.tcldefs
? src/bin/pgtclsh/pgtclsh
? src/bin/pgtclsh/pgtksh
? src/bin/psql/psql
? src/bin/scripts/createlang
? src/include/config.h
? src/include/stamp-h
? src/interfaces/ecpg/lib/libecpg.so.3.2.0
? src/interfaces/ecpg/preproc/ecpg
? src/interfaces/libpgeasy/libpgeasy.so.2.1
? src/interfaces/libpgtcl/libpgtcl.so.2.1
? src/interfaces/libpq/libpq.so.2.1
? src/interfaces/perl5/blib
? src/interfaces/perl5/Makefile
? src/interfaces/perl5/pm_to_blib
? src/interfaces/perl5/Pg.c
? src/interfaces/perl5/Pg.bs
? src/pl/plperl/blib
? src/pl/plperl/Makefile
? src/pl/plperl/pm_to_blib
? src/pl/plperl/SPI.c
? src/pl/plperl/plperl.bs
? src/pl/plpgsql/src/libplpgsql.so.1.0
? src/pl/tcl/Makefile.tcldefs
Index: src/include/storage/s_lock.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/storage/s_lock.h,v
retrieving revision 1.78
diff -c -r1.78 s_lock.h
*** src/include/storage/s_lock.h    2001/01/18 23:40:26    1.78
--- src/include/storage/s_lock.h    2001/01/19 02:52:49
***************
*** 35,41 ****
   *
   *    int TAS(slock_t *lock)
   *        Atomic test-and-set instruction.  Attempt to acquire the lock,
!  *        but do *not* wait.  Returns 0 if successful, nonzero if unable
   *        to acquire the lock.
   *
   *    TAS() is a lower-level part of the API, but is used directly in a
--- 35,41 ----
   *
   *    int TAS(slock_t *lock)
   *        Atomic test-and-set instruction.  Attempt to acquire the lock,
!  *        but do *not* wait.    Returns 0 if successful, nonzero if unable
   *        to acquire the lock.
   *
   *    TAS() is a lower-level part of the API, but is used directly in a
***************
*** 48,56 ****
   *        unsigned    spins = 0;
   *
   *        while (TAS(lock))
-  *        {
   *            S_LOCK_SLEEP(lock, spins++);
-  *        }
   *    }
   *
   *    where S_LOCK_SLEEP() checks for timeout and sleeps for a short
--- 48,54 ----
***************
*** 87,96 ****

  /* Platform-independent out-of-line support routines */
  extern void s_lock(volatile slock_t *lock,
!                    const char *file, const int line);
  extern void s_lock_sleep(unsigned spins, int microsec,
!                          volatile slock_t *lock,
!                          const char *file, const int line);


  #if defined(HAS_TEST_AND_SET)
--- 85,94 ----

  /* Platform-independent out-of-line support routines */
  extern void s_lock(volatile slock_t *lock,
!        const char *file, const int line);
  extern void s_lock_sleep(unsigned spins, int microsec,
!              volatile slock_t *lock,
!              const char *file, const int line);


  #if defined(HAS_TEST_AND_SET)
***************
*** 101,106 ****
--- 99,116 ----
   * All the gcc inlines
   */

+ /*
+  * Standard __asm__ format:
+  *
+  *    __asm__(
+  *            "command;"
+  *            "command;"
+  *            "command;"
+  *        :    "=r"(_res)            return value, in register
+  *        :    "r"(lock)            argument, 'lock pointer', in register
+  *        :    "r0");                inline code uses this register
+  */
+

  #if defined(__i386__)
  #define TAS(lock) tas(lock)
***************
*** 110,116 ****
  {
      register slock_t _res = 1;

! __asm__("lock; xchgb %0,%1": "=q"(_res), "=m"(*lock):"0"(_res));
      return (int) _res;
  }

--- 120,130 ----
  {
      register slock_t _res = 1;

!     __asm__(
!             "lock;"
!             "xchgb %0,%1;"
! :            "=q"(_res), "=m"(*lock)
! :            "0"(_res));
      return (int) _res;
  }

***************
*** 121,139 ****
  #define TAS(lock) tas(lock)

  static __inline__ int
! tas (volatile slock_t *lock)
  {
!   long int ret;

!   __asm__ __volatile__(
!        "xchg4 %0=%1,%2"
!        : "=r"(ret), "=m"(*lock)
!        : "r"(1), "1"(*lock)
!        : "memory");

!   return (int) ret;
  }
! #endif /* __ia64__ */


  #if defined(__arm__) || defined(__arm__)
--- 135,154 ----
  #define TAS(lock) tas(lock)

  static __inline__ int
! tas(volatile slock_t *lock)
  {
!     long int    ret;

!     __asm__        __volatile__(
!                                          "xchg4 %0=%1,%2;"
!                              :             "=r"(ret), "=m"(*lock)
!                              :             "r"(1), "1"(*lock)
!                              :             "memory");

!     return (int) ret;
  }
!
! #endif     /* __ia64__ */


  #if defined(__arm__) || defined(__arm__)
***************
*** 142,180 ****
  static __inline__ int
  tas(volatile slock_t *lock)
  {
!         register slock_t _res = 1;

! __asm__("swpb %0, %0, [%3]": "=r"(_res), "=m"(*lock):"0"(_res), "r" (lock));
!         return (int) _res;
  }

! #endif   /* __arm__ */

  #if defined(__s390__)
  /*
   * S/390 Linux
   */
! #define TAS(lock)      tas(lock)

  static inline int
  tas(volatile slock_t *lock)
  {
!  int _res;

!         __asm__ __volatile("    la    1,1\n"
!                            "    l     2,%2\n"
!                            "    slr   0,0\n"
!                            "    cs    0,1,0(2)\n"
!                            "    lr    %1,0"
!                            : "=m" (lock), "=d" (_res)
!                            : "m" (lock)
!                            : "0", "1", "2");

!        return (_res);
  }
- #endif  /* __s390__ */


  #if defined(__sparc__)
  #define TAS(lock) tas(lock)

--- 157,200 ----
  static __inline__ int
  tas(volatile slock_t *lock)
  {
!     register slock_t _res = 1;

!     __asm__(
!             "swpb %0, %0, [%3];"
! :            "=r"(_res), "=m"(*lock)
! :            "0"(_res), "r"(lock));
!     return (int) _res;
  }

! #endif     /* __arm__ */

  #if defined(__s390__)
  /*
   * S/390 Linux
   */
! #define TAS(lock)       tas(lock)

  static inline int
  tas(volatile slock_t *lock)
  {
!     int            _res;

!     __asm__        __volatile(
!                                        "la 1,1;"
!                                        "l 2,%2;"
!                                        "slr 0,0;"
!                                        "cs 0,1,0(2);"
!                                        "lr %1,0;"
!                            :           "=m"(lock), "=d"(_res)
!                            :           "m"(lock)
!                            :           "0", "1", "2");

!     return (_res);
  }

+ #endif     /* __s390__ */

+
  #if defined(__sparc__)
  #define TAS(lock) tas(lock)

***************
*** 183,190 ****
  {
      register slock_t _res = 1;

!     __asm__("ldstub [%2], %0" \
! :            "=r"(_res), "=m"(*lock) \
  :            "r"(lock));
      return (int) _res;
  }
--- 203,211 ----
  {
      register slock_t _res = 1;

!     __asm__(
!             "ldstub [%2], %0;"
! :            "=r"(_res), "=m"(*lock)
  :            "r"(lock));
      return (int) _res;
  }
***************
*** 199,214 ****
  tas(volatile slock_t *lock)
  {
      register int rv;
!
!     __asm__ __volatile__ (
!         "tas %1; sne %0"
!         : "=d" (rv), "=m"(*lock)
!         : "1" (*lock)
!         : "cc" );
      return rv;
  }

! #endif /* defined(__mc68000__) && defined(__linux__) */


  #if defined(NEED_VAX_TAS_ASM)
--- 220,237 ----
  tas(volatile slock_t *lock)
  {
      register int rv;
!
!     __asm__        __volatile__(
!                                          "tas %1;"
!                                          "sne %0;"
!                              :             "=d"(rv), "=m"(*lock)
!                              :             "1"(*lock)
!                              :             "cc");
!
      return rv;
  }

! #endif     /* defined(__mc68000__) && defined(__linux__) */


  #if defined(NEED_VAX_TAS_ASM)
***************
*** 225,237 ****
  {
      register    _res;

!     __asm__("    movl $1, r0 \
!             bbssi $0, (%1), 1f \
!             clrl r0 \
! 1:            movl r0, %0 "
! :            "=r"(_res)            /* return value, in register */
! :            "r"(lock)            /* argument, 'lock pointer', in register */
! :            "r0");                /* inline code uses this register */
      return (int) _res;
  }

--- 248,261 ----
  {
      register    _res;

!     __asm__(
!             "movl $1, r0;"
!             "bbssi $0, (%1), 1f;"
!             "clrl r0;"
!             "1: movl r0, %0;"
! :            "=r"(_res)
! :            "r"(lock)
! :            "r0");
      return (int) _res;
  }

***************
*** 244,257 ****
  static __inline__ int
  tas(volatile slock_t *lock)
  {
!   register _res;
!   __asm__("sbitb 0, %0 \n\
!     sfsd %1"
!     : "=m"(*lock), "=r"(_res));
!   return (int) _res;
  }

! #endif  /* NEED_NS32K_TAS_ASM */



--- 268,283 ----
  static __inline__ int
  tas(volatile slock_t *lock)
  {
!     register    _res;
!
!     __asm__(
!             "sbitb 0, %0;"
!             "sfsd %1;"
! :            "=m"(*lock), "=r"(_res));
!     return (int) _res;
  }

! #endif     /* NEED_NS32K_TAS_ASM */



***************
*** 268,274 ****
  tas(volatile slock_t *s_lock)
  {
  /* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
! %mem s_lock
      pushl %ebx
      movl s_lock, %ebx
      movl $255, %eax
--- 294,300 ----
  tas(volatile slock_t *s_lock)
  {
  /* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
!     %mem s_lock
      pushl %ebx
      movl s_lock, %ebx
      movl $255, %eax
***************
*** 277,283 ****
      popl %ebx
  }

! #endif /* defined(NEED_I386_TAS_ASM) && defined(USE_UNIVEL_CC) */

  #endif     /* defined(__GNUC__) */

--- 303,309 ----
      popl %ebx
  }

! #endif     /* defined(NEED_I386_TAS_ASM) && defined(USE_UNIVEL_CC) */

  #endif     /* defined(__GNUC__) */

***************
*** 300,329 ****
  #if defined(__GNUC__)

  #define TAS(lock)  tas(lock)
! #define S_UNLOCK(lock)  do { __asm__ volatile ("mb"); *(lock) = 0; } while (0)

  static __inline__ int
  tas(volatile slock_t *lock)
  {
      register slock_t _res;

!     __asm__ volatile
! ("        ldq   $0, %0        \n\
!         bne   $0, 2f        \n\
!         ldq_l %1, %0        \n\
!         bne   %1, 2f        \n\
!         mov   1, $0            \n\
!         stq_c $0, %0        \n\
!         beq   $0, 2f        \n\
!         mb                    \n\
!         br    3f            \n\
!      2: mov   1, %1            \n\
!      3:       \n" : "=m"(*lock), "=r"(_res) : : "0");

      return (int) _res;
  }

! #else /* !defined(__GNUC__) */

  /*
   * The Tru64 compiler doesn't support gcc-style inline asm, but it does
--- 326,358 ----
  #if defined(__GNUC__)

  #define TAS(lock)  tas(lock)
! #define S_UNLOCK(lock)    do { __asm__ volatile ("mb"); *(lock) = 0; } while (0)

  static __inline__ int
  tas(volatile slock_t *lock)
  {
      register slock_t _res;

!     __asm__        volatile(
!                                      "ldq   $0, %0;"
!                                      "bne   $0, 2f;"
!                                      "ldq_l %1, %0;"
!                                      "bne   %1, 2f;"
!                                      "mov   1, $0;"
!                                      "stq_c $0, %0;"
!                                      "beq   $0, 2f;"
!                                      "mb;"
!                                      "br 3f;"
!                                      "2: mov   1, %1;"
!                                      "3:"
!                          :             "=m"(*lock), "=r"(_res)
!                          :
!                          :             "0");

      return (int) _res;
  }

! #else                            /* !defined(__GNUC__) */

  /*
   * The Tru64 compiler doesn't support gcc-style inline asm, but it does
***************
*** 337,348 ****
  #include <alpha/builtins.h>

  #define S_INIT_LOCK(lock)  (*(lock) = 0)
! #define TAS(lock)          (__LOCK_LONG_RETRY((lock), 1) == 0)
! #define S_UNLOCK(lock)     __UNLOCK_LONG(lock)

! #endif /* defined(__GNUC__) */

! #endif /* __alpha */


  #if defined(__hpux)
--- 366,377 ----
  #include <alpha/builtins.h>

  #define S_INIT_LOCK(lock)  (*(lock) = 0)
! #define TAS(lock)           (__LOCK_LONG_RETRY((lock), 1) == 0)
! #define S_UNLOCK(lock)       __UNLOCK_LONG(lock)

! #endif     /* defined(__GNUC__) */

! #endif     /* __alpha */


  #if defined(__hpux)
***************
*** 373,390 ****
   *
   * Note that slock_t under QNX is sem_t instead of char
   */
! #define TAS(lock)       (sem_trywait((lock)) < 0)
! #define S_UNLOCK(lock)  sem_post((lock))
! #define S_INIT_LOCK(lock)       sem_init((lock), 1, 1)
! #define S_LOCK_FREE(lock)       ((lock)->value)
! #endif   /* __QNX__ */


  #if defined(__sgi)
  /*
   * SGI IRIX 5
   * slock_t is defined as a unsigned long. We use the standard SGI
!  * mutex API.
   *
   * The following comment is left for historical reasons, but is probably
   * not a good idea since the mutex ABI is supported.
--- 402,419 ----
   *
   * Note that slock_t under QNX is sem_t instead of char
   */
! #define TAS(lock)        (sem_trywait((lock)) < 0)
! #define S_UNLOCK(lock)    sem_post((lock))
! #define S_INIT_LOCK(lock)        sem_init((lock), 1, 1)
! #define S_LOCK_FREE(lock)        ((lock)->value)
! #endif     /* __QNX__ */


  #if defined(__sgi)
  /*
   * SGI IRIX 5
   * slock_t is defined as a unsigned long. We use the standard SGI
!  * mutex API.
   *
   * The following comment is left for historical reasons, but is probably
   * not a good idea since the mutex ABI is supported.
***************
*** 402,408 ****

  #if defined(sinix)
  /*
!  * SINIX / Reliant UNIX
   * slock_t is defined as a struct abilock_t, which has a single unsigned long
   * member. (Basically same as SGI)
   *
--- 431,437 ----

  #if defined(sinix)
  /*
!  * SINIX / Reliant UNIX
   * slock_t is defined as a struct abilock_t, which has a single unsigned long
   * member. (Basically same as SGI)
   *
***************
*** 412,418 ****
  #define S_INIT_LOCK(lock)    init_lock(lock)
  #define S_LOCK_FREE(lock)    (stat_lock(lock) == UNLOCKED)
  #endif     /* sinix */
!

  #if defined(_AIX)
  /*
--- 441,447 ----
  #define S_INIT_LOCK(lock)    init_lock(lock)
  #define S_LOCK_FREE(lock)    (stat_lock(lock) == UNLOCKED)
  #endif     /* sinix */
!

  #if defined(_AIX)
  /*
***************
*** 440,446 ****



! #else     /* !HAS_TEST_AND_SET */

  /*
   * Fake spinlock implementation using SysV semaphores --- slow and prone
--- 469,475 ----



! #else                            /* !HAS_TEST_AND_SET */

  /*
   * Fake spinlock implementation using SysV semaphores --- slow and prone
***************
*** 451,469 ****
  typedef struct
  {
      /* reference to semaphore used to implement this spinlock */
!     IpcSemaphoreId    semId;
!     int                sem;
  } slock_t;

  extern bool s_lock_free_sema(volatile slock_t *lock);
  extern void s_unlock_sema(volatile slock_t *lock);
  extern void s_init_lock_sema(volatile slock_t *lock);
! extern int tas_sema(volatile slock_t *lock);

! #define S_LOCK_FREE(lock)   s_lock_free_sema(lock)
! #define S_UNLOCK(lock)   s_unlock_sema(lock)
! #define S_INIT_LOCK(lock)   s_init_lock_sema(lock)
! #define TAS(lock)   tas_sema(lock)

  #endif     /* HAS_TEST_AND_SET */

--- 480,498 ----
  typedef struct
  {
      /* reference to semaphore used to implement this spinlock */
!     IpcSemaphoreId semId;
!     int            sem;
  } slock_t;

  extern bool s_lock_free_sema(volatile slock_t *lock);
  extern void s_unlock_sema(volatile slock_t *lock);
  extern void s_init_lock_sema(volatile slock_t *lock);
! extern int    tas_sema(volatile slock_t *lock);

! #define S_LOCK_FREE(lock)    s_lock_free_sema(lock)
! #define S_UNLOCK(lock)     s_unlock_sema(lock)
! #define S_INIT_LOCK(lock)    s_init_lock_sema(lock)
! #define TAS(lock)    tas_sema(lock)

  #endif     /* HAS_TEST_AND_SET */


Re: [HACKERS] s_lock.h cleanup

From
Tom Lane
Date:
As long as we're cleaning things up, I would suggest that all the ports
that use gcc assembler be made to declare it uniformly, as

    __asm__ __volatile__ ( ... );

As I read the GCC manual, there's some risk of the asm sections getting
moved around in the program flow if they are not marked volatile.  Also
we oughta be consistent about using the double-underscore keywords IMHO.

            regards, tom lane

Re: [HACKERS] s_lock.h cleanup

From
Bruce Momjian
Date:
Done and applied.

> As long as we're cleaning things up, I would suggest that all the ports
> that use gcc assembler be made to declare it uniformly, as
>
>     __asm__ __volatile__ ( ... );
>
> As I read the GCC manual, there's some risk of the asm sections getting
> moved around in the program flow if they are not marked volatile.  Also
> we oughta be consistent about using the double-underscore keywords IMHO.
>
>             regards, tom lane
>


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026