Fix failure in CreateCheckPoint on some Alpha boxes --- it's not OK to
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 29 Dec 2000 21:31:21 +0000 (21:31 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 29 Dec 2000 21:31:21 +0000 (21:31 +0000)
assume that TAS() will always succeed the first time, even if the lock
is known to be free.  Also, make sure that code will eventually time out
and report a stuck spinlock, rather than looping forever.  Small cleanups
in s_lock.h, too.

src/backend/access/transam/xlog.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/s_lock.c
src/include/storage/s_lock.h

index 7294b97ff341101550ef52463c4ca3562723f223..ff8916cd37bc7eb654c266c00b24ea83ac111bd4 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.45 2000/12/28 13:00:08 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.46 2000/12/29 21:31:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -411,7 +411,7 @@ begin:;
                    }
                }
            }
-           s_lock_sleep(i++);
+           S_LOCK_SLEEP(&(XLogCtl->insert_lck), i++);
            if (!TAS(&(XLogCtl->insert_lck)))
                break;
        }
@@ -599,17 +599,10 @@ begin:;
 
    if (updrqst)
    {
-       for (;;)
-       {
-           if (!TAS(&(XLogCtl->info_lck)))
-           {
-               if (XLByteLT(XLogCtl->LgwrRqst.Write, LgwrRqst.Write))
-                   XLogCtl->LgwrRqst.Write = LgwrRqst.Write;
-               S_UNLOCK(&(XLogCtl->info_lck));
-               break;
-           }
-           s_lock_sleep(i++);
-       }
+       S_LOCK(&(XLogCtl->info_lck));
+       if (XLByteLT(XLogCtl->LgwrRqst.Write, LgwrRqst.Write))
+           XLogCtl->LgwrRqst.Write = LgwrRqst.Write;
+       S_UNLOCK(&(XLogCtl->info_lck));
    }
 
    END_CRIT_CODE;
@@ -622,7 +615,7 @@ XLogFlush(XLogRecPtr record)
    XLogRecPtr  WriteRqst;
    char        buffer[BLCKSZ];
    char       *usebuf = NULL;
-   unsigned    i = 0;
+   unsigned    spins = 0;
    bool        force_lgwr = false;
 
    if (XLOG_DEBUG)
@@ -715,7 +708,7 @@ XLogFlush(XLogRecPtr record)
                break;
            }
        }
-       s_lock_sleep(i++);
+       S_LOCK_SLEEP(&(XLogCtl->lgwr_lck), spins++);
    }
 
    if (logFile >= 0 && (LgwrResult.Write.xlogid != logId ||
@@ -740,18 +733,12 @@ XLogFlush(XLogRecPtr record)
             logId, logSeg);
    LgwrResult.Flush = LgwrResult.Write;
 
-   for (i = 0;;)
-   {
-       if (!TAS(&(XLogCtl->info_lck)))
-       {
-           XLogCtl->LgwrResult = LgwrResult;
-           if (XLByteLT(XLogCtl->LgwrRqst.Write, LgwrResult.Write))
-               XLogCtl->LgwrRqst.Write = LgwrResult.Write;
-           S_UNLOCK(&(XLogCtl->info_lck));
-           break;
-       }
-       s_lock_sleep(i++);
-   }
+   S_LOCK(&(XLogCtl->info_lck));
+   XLogCtl->LgwrResult = LgwrResult;
+   if (XLByteLT(XLogCtl->LgwrRqst.Write, LgwrResult.Write))
+       XLogCtl->LgwrRqst.Write = LgwrResult.Write;
+   S_UNLOCK(&(XLogCtl->info_lck));
+
    XLogCtl->Write.LgwrResult = LgwrResult;
 
    S_UNLOCK(&(XLogCtl->lgwr_lck));
@@ -767,6 +754,7 @@ GetFreeXLBuffer()
    XLogCtlInsert *Insert = &XLogCtl->Insert;
    XLogCtlWrite *Write = &XLogCtl->Write;
    uint16      curridx = NextBufIdx(Insert->curridx);
+   unsigned    spins = 0;
 
    LgwrRqst.Write = XLogCtl->xlblocks[Insert->curridx];
    for (;;)
@@ -809,9 +797,8 @@ GetFreeXLBuffer()
            InitXLBuffer(curridx);
            return;
        }
+       S_LOCK_SLEEP(&(XLogCtl->lgwr_lck), spins++);
    }
-
-   return;
 }
 
 static void
@@ -820,7 +807,6 @@ XLogWrite(char *buffer)
    XLogCtlWrite *Write = &XLogCtl->Write;
    char       *from;
    uint32      wcnt = 0;
-   int         i = 0;
    bool        usexistent;
 
    for (; XLByteLT(LgwrResult.Write, LgwrRqst.Write);)
@@ -919,18 +905,12 @@ XLogWrite(char *buffer)
        LgwrResult.Flush = LgwrResult.Write;
    }
 
-   for (;;)
-   {
-       if (!TAS(&(XLogCtl->info_lck)))
-       {
-           XLogCtl->LgwrResult = LgwrResult;
-           if (XLByteLT(XLogCtl->LgwrRqst.Write, LgwrResult.Write))
-               XLogCtl->LgwrRqst.Write = LgwrResult.Write;
-           S_UNLOCK(&(XLogCtl->info_lck));
-           break;
-       }
-       s_lock_sleep(i++);
-   }
+   S_LOCK(&(XLogCtl->info_lck));
+   XLogCtl->LgwrResult = LgwrResult;
+   if (XLByteLT(XLogCtl->LgwrRqst.Write, LgwrResult.Write))
+       XLogCtl->LgwrRqst.Write = LgwrResult.Write;
+   S_UNLOCK(&(XLogCtl->info_lck));
+
    Write->LgwrResult = LgwrResult;
 }
 
@@ -2062,18 +2042,17 @@ CreateCheckPoint(bool shutdown)
    uint32      _logId;
    uint32      _logSeg;
    char        archdir[MAXPGPATH];
+   unsigned    spins = 0;
 
    if (MyLastRecPtr.xrecoff != 0)
        elog(ERROR, "CreateCheckPoint: cannot be called inside transaction block");
  
    START_CRIT_CODE;
+
+   /* Grab lock, using larger than normal sleep between tries (1 sec) */
    while (TAS(&(XLogCtl->chkp_lck)))
    {
-       struct timeval delay = {2, 0};
-
-       if (shutdown)
-           elog(STOP, "Checkpoint lock is busy while data base is shutting down");
-       (void) select(0, NULL, NULL, NULL, &delay);
+       S_LOCK_SLEEP_INTERVAL(&(XLogCtl->chkp_lck), spins++, 1000000);
    }
 
    memset(&checkPoint, 0, sizeof(checkPoint));
@@ -2087,14 +2066,7 @@ CreateCheckPoint(bool shutdown)
    checkPoint.Shutdown = shutdown;
 
    /* Get REDO record ptr */
-   while (TAS(&(XLogCtl->insert_lck)))
-   {
-       struct timeval delay = {1, 0};
-
-       if (shutdown)
-           elog(STOP, "XLog insert lock is busy while data base is shutting down");
-       (void) select(0, NULL, NULL, NULL, &delay);
-   }
+   S_LOCK(&(XLogCtl->insert_lck));
    freespace = ((char *) Insert->currpage) + BLCKSZ - Insert->currpos;
    if (freespace < SizeOfXLogRecord)
    {
index 2adea99e82ca60db94a78b5542be121e6ad2d2fa..d97ddfdbff449210a2c0f260f895697be8a6d201 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.100 2000/12/28 13:00:21 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.101 2000/12/29 21:31:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1987,7 +1987,7 @@ LockBuffer(Buffer buffer, int mode)
        while (buf->ri_lock || buf->w_lock)
        {
            S_UNLOCK(&(buf->cntx_lock));
-           s_lock_sleep(i++);
+           S_LOCK_SLEEP(&(buf->cntx_lock), i++);
            S_LOCK(&(buf->cntx_lock));
        }
        (buf->r_locks)++;
@@ -2013,7 +2013,7 @@ LockBuffer(Buffer buffer, int mode)
                buf->ri_lock = true;
            }
            S_UNLOCK(&(buf->cntx_lock));
-           s_lock_sleep(i++);
+           S_LOCK_SLEEP(&(buf->cntx_lock), i++);
            S_LOCK(&(buf->cntx_lock));
        }
        buf->w_lock = true;
index 7f658ad26a8bf8977696a8e7f2b7e97cd25e6dfa..932e5b0049b9dcfc41a155d170c4065c15d9e9da 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.27 2000/12/11 00:49:51 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.28 2000/12/29 21:31:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  * number of microseconds to wait. This accomplishes pseudo random back-off.
  * Values are not critical but 10 milliseconds is a common platform
  * granularity.
- * note: total time to cycle through all 16 entries might be about .07 sec.
+ *
+ * Total time to cycle through all 20 entries might be about .07 sec,
+ * so the given value of S_MAX_BUSY results in timeout after ~70 sec.
  */
 #define S_NSPINCYCLE   20
 #define S_MAX_BUSY     1000 * S_NSPINCYCLE
 
 int            s_spincycle[S_NSPINCYCLE] =
-{0, 0, 0, 0, 10000, 0, 0, 0, 10000, 0,
+{  0, 0, 0, 0, 10000, 0, 0, 0, 10000, 0,
    0, 10000, 0, 0, 10000, 0, 10000, 0, 10000, 10000
 };
 
 
 /*
- * s_lock_stuck(lock) - complain about a stuck spinlock
+ * s_lock_stuck() - complain about a stuck spinlock
  */
 static void
 s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
@@ -52,13 +54,38 @@ s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
 }
 
 
+/*
+ * s_lock_sleep() - sleep a pseudo-random amount of time, check for timeout
+ *
+ * Normally 'microsec' is 0, specifying to use the next s_spincycle[] value.
+ * Some callers may pass a nonzero interval, specifying to use exactly that
+ * delay value rather than a pseudo-random delay.
+ */
 void
-s_lock_sleep(unsigned spin)
+s_lock_sleep(unsigned spins, int microsec,
+            volatile slock_t *lock,
+            const char *file, const int line)
 {
    struct timeval delay;
+   unsigned    max_spins;
+
+   if (microsec > 0)
+   {
+       delay.tv_sec = 0;
+       delay.tv_usec = microsec;
+       /* two-minute timeout in this case */
+       max_spins = 120000000 / microsec;
+   }
+   else
+   {
+       delay.tv_sec = 0;
+       delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE];
+       max_spins = S_MAX_BUSY;
+   }
+
+   if (spins > max_spins)
+       s_lock_stuck(lock, file, line);
 
-   delay.tv_sec = 0;
-   delay.tv_usec = s_spincycle[spin % S_NSPINCYCLE];
    (void) select(0, NULL, NULL, NULL, &delay);
 }
 
@@ -71,14 +98,13 @@ s_lock(volatile slock_t *lock, const char *file, const int line)
 {
    unsigned    spins = 0;
 
+   /*
+    * If you are thinking of changing this code, be careful.  This same
+    * loop logic is used in other places that call TAS() directly.
+    */
    while (TAS(lock))
    {
-       s_lock_sleep(spins);
-       if (++spins > S_MAX_BUSY)
-       {
-           /* It's been over a minute...  */
-           s_lock_stuck(lock, file, line);
-       }
+       s_lock_sleep(spins++, 0, lock, file, line);
    }
 }
 
index 863801f8ee37d3c53658239a4542d75db8c3bf3e..9f6b8d3a12c34cf9ffee9388f5e8533b9f000e43 100644 (file)
@@ -1,75 +1,97 @@
 /*-------------------------------------------------------------------------
  *
  * s_lock.h
- *    This file contains the implementation (if any) for spinlocks.
+ *    This file contains the in-line portion of the implementation
+ *    of spinlocks.
  *
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.75 2000/12/03 14:41:42 thomas Exp $
+ *   $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.76 2000/12/29 21:31:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
-/*
- *  DESCRIPTION
- *     The public macros that must be provided are:
+/*----------
+ * DESCRIPTION
+ * The public macros that must be provided are:
+ *
+ * void S_INIT_LOCK(slock_t *lock)
+ *     Initialize a spinlock (to the unlocked state).
+ *
+ * void S_LOCK(slock_t *lock)
+ *     Acquire a spinlock, waiting if necessary.
+ *     Time out and abort() if unable to acquire the lock in a
+ *     "reasonable" amount of time --- typically ~ 1 minute.
  *
- *     void S_INIT_LOCK(slock_t *lock)
+ * void S_UNLOCK(slock_t *lock)
+ *     Unlock a previously acquired lock.
  *
- *     void S_LOCK(slock_t *lock)
+ * bool S_LOCK_FREE(slock_t *lock)
+ *     Tests if the lock is free. Returns TRUE if free, FALSE if locked.
+ *     This does *not* change the state of the lock.
  *
- *     void S_UNLOCK(slock_t *lock)
+ * 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.
  *
- *     void S_LOCK_FREE(slock_t *lock)
- *         Tests if the lock is free. Returns non-zero if free, 0 if locked.
+ * TAS() is a lower-level part of the API, but is used directly in a
+ * few places that want to do other things while waiting for a lock.
+ * The S_LOCK() macro is equivalent to
  *
- *     The S_LOCK() macro implements a primitive but still useful random
- *     backoff to avoid hordes of busywaiting lockers chewing CPU.
+ * void
+ * S_LOCK(slock_t *lock)
+ * {
+ *     unsigned    spins = 0;
  *
- *     Effectively:
- *     void
- *     S_LOCK(slock_t *lock)
+ *     while (TAS(lock))
  *     {
- *         while (TAS(lock))
- *         {
- *         // back off the cpu for a semi-random short time
- *         }
+ *         S_LOCK_SLEEP(lock, spins++);
  *     }
+ * }
  *
- *     This implementation takes advantage of a tas function written
- *     (in assembly language) on machines that have a native test-and-set
- *     instruction. Alternative mutex implementations may also be used.
- *     This function is hidden under the TAS macro to allow substitutions.
+ * where S_LOCK_SLEEP() checks for timeout and sleeps for a short
+ * interval.  Callers that want to perform useful work while waiting
+ * can write out this entire loop and insert the "useful work" inside
+ * the loop.
  *
- *     #define TAS(lock) tas(lock)
- *     int tas(slock_t *lock)      // True if lock already set
+ * CAUTION to TAS() callers: on some platforms TAS() may sometimes
+ * report failure to acquire a lock even when the lock is not locked.
+ * For example, on Alpha TAS() will "fail" if interrupted.  Therefore
+ * TAS() must *always* be invoked in a retry loop as depicted, even when
+ * you are certain the lock is free.
  *
- *     There are default implementations for all these macros at the bottom
- *     of this file. Check if your platform can use these or needs to
- *     override them.
+ * On most supported platforms, TAS() uses a tas() function written
+ * in assembly language to execute a hardware atomic-test-and-set
+ * instruction.  Equivalent OS-supplied mutex routines could be used too.
  *
- * NOTES
- *     If none of this can be done, POSTGRES will default to using
- *     System V semaphores (and take a large performance hit -- around 40%
- *     of its time on a DS5000/240 is spent in semop(3)...).
- *
- *     AIX has a test-and-set but the recommended interface is the cs(3)
- *     system call.  This provides an 8-instruction (plus system call
- *     overhead) uninterruptible compare-and-set operation.  True
- *     spinlocks might be faster but using cs(3) still speeds up the
- *     regression test suite by about 25%.  I don't have an assembler
- *     manual for POWER in any case.
+ * If no system-specific TAS() is available (ie, HAS_TEST_AND_SET is not
+ * defined), then we fall back on an emulation that uses SysV semaphores.
+ * This emulation will be MUCH MUCH MUCH slower than a proper TAS()
+ * implementation, because of the cost of a kernel call per lock or unlock.
+ * An old report is that Postgres spends around 40% of its time in semop(2)
+ * when using the SysV semaphore code.
  *
+ * Note to implementors: there are default implementations for all these
+ * macros at the bottom of the file.  Check if your platform can use
+ * these or needs to override them.
+ *----------
  */
 #ifndef S_LOCK_H
 #define S_LOCK_H
 
 #include "storage/ipc.h"
 
-extern void s_lock_sleep(unsigned spin);
+/* 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)
 
@@ -216,7 +238,6 @@ tas(volatile slock_t *lock)
 #endif  /* NEED_VAX_TAS_ASM */
 
 
-
 #if defined(NEED_NS32K_TAS_ASM)
 #define TAS(lock) tas(lock)
 
@@ -234,28 +255,13 @@ tas(volatile slock_t *lock)
 
 
 
-#else                          /* __GNUC__ */
-/***************************************************************************
- * All non gcc
- */
+#else                          /* !__GNUC__ */
 
-#if defined(__QNX__)
-/*
- * QNX 4
- *
- * Note that slock_t under QNX is sem_t instead of char
+/***************************************************************************
+ * All non-gcc inlines
  */
-#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(NEED_I386_TAS_ASM)
-/* non gcc i386 based things */
-
-#if defined(USE_UNIVEL_CC)
+#if defined(NEED_I386_TAS_ASM) && defined(USE_UNIVEL_CC)
 #define TAS(lock)  tas(lock)
 
 asm int
@@ -271,16 +277,15 @@ tas(volatile slock_t *s_lock)
    popl %ebx
 }
 
-#endif  /* USE_UNIVEL_CC */
-
-#endif  /* NEED_I386_TAS_ASM */
+#endif /* defined(NEED_I386_TAS_ASM) && defined(USE_UNIVEL_CC) */
 
 #endif  /* defined(__GNUC__) */
 
 
 
 /*************************************************************************
- * These are the platforms that have common code for gcc and non-gcc
+ * These are the platforms that do not use inline assembler (and hence
+ * have common code for gcc and non-gcc compilers, if both are available).
  */
 
 
@@ -342,7 +347,7 @@ __asm__("    ldq   $0, %0              \n\
  * (see include/port/hpux.h).
  *
  * a "set" slock_t has a single word cleared.  a "clear" slock_t has
- * all words set to non-zero. tas() in tas.s
+ * all words set to non-zero. tas() is in tas.s
  */
 
 #define S_UNLOCK(lock) \
@@ -356,6 +361,19 @@ do { \
 #endif  /* __hpux */
 
 
+#if defined(__QNX__)
+/*
+ * QNX 4
+ *
+ * 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
@@ -416,21 +434,57 @@ do { \
 
 
 
+#else   /* !HAS_TEST_AND_SET */
+
+/*
+ * Fake spinlock implementation using SysV semaphores --- slow and prone
+ * to fall foul of kernel limits on number of semaphores, so don't use this
+ * unless you must!
+ */
+
+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 */
+
+
 
 /****************************************************************************
  * Default Definitions - override these above as needed.
  */
 
 #if !defined(S_LOCK)
-extern void s_lock(volatile slock_t *lock, const char *file, const int line);
-
 #define S_LOCK(lock) \
    do { \
-       if (TAS((volatile slock_t *) (lock))) \
-           s_lock((volatile slock_t *) (lock), __FILE__, __LINE__); \
+       if (TAS(lock)) \
+           s_lock((lock), __FILE__, __LINE__); \
    } while (0)
 #endif  /* S_LOCK */
 
+#if !defined(S_LOCK_SLEEP)
+#define S_LOCK_SLEEP(lock,spins) \
+   s_lock_sleep((spins), 0, (lock), __FILE__, __LINE__)
+#endif  /* S_LOCK_SLEEP */
+
+#if !defined(S_LOCK_SLEEP_INTERVAL)
+#define S_LOCK_SLEEP_INTERVAL(lock,spins,microsec) \
+   s_lock_sleep((spins), (microsec), (lock), __FILE__, __LINE__)
+#endif  /* S_LOCK_SLEEP_INTERVAL */
+
 #if !defined(S_LOCK_FREE)
 #define S_LOCK_FREE(lock)  (*(lock) == 0)
 #endif  /* S_LOCK_FREE */
@@ -444,46 +498,11 @@ extern void s_lock(volatile slock_t *lock, const char *file, const int line);
 #endif  /* S_INIT_LOCK */
 
 #if !defined(TAS)
-extern int tas(volatile slock_t *lock);        /* port/.../tas.s, or
+extern int tas(volatile slock_t *lock);        /* in port/.../tas.s, or
                                                 * s_lock.c */
 
-#define TAS(lock)      tas((volatile slock_t *) (lock))
+#define TAS(lock)      tas(lock)
 #endif  /* TAS */
 
 
-#else   /* !HAS_TEST_AND_SET */
-
-/*
- * Fake spinlock implementation using SysV semaphores --- slow and prone
- * to fall foul of kernel limits on number of semaphores, so don't use this
- * unless you must!
- */
-
-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);
-
-extern void s_lock(volatile slock_t *lock, const char *file, const int line);
-
-#define S_LOCK(lock) \
-   do { \
-       if (TAS((volatile slock_t *) (lock))) \
-           s_lock((volatile slock_t *) (lock), __FILE__, __LINE__); \
-   } while (0)
-
-#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 */
-
 #endif  /* S_LOCK_H */