* macros at the bottom of the file. Check if your platform can use
* these or needs to override them.
*
- * Usually, S_LOCK() is implemented in terms of an even lower-level macro
- * TAS():
+ * Usually, S_LOCK() is implemented in terms of even lower-level macros
+ * TAS() and TAS_SPIN():
*
* 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 NOT part of the API, and should never be called directly.
+ * int TAS_SPIN(slock_t *lock)
+ * Like TAS(), but this version is used when waiting for a lock
+ * previously found to be contended. Typically, this is the
+ * same as TAS(), but on some architectures it's better to poll a
+ * contended lock using an unlocked instruction and retry the
+ * atomic test-and-set only when it appears free.
*
- * CAUTION: 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() should always be invoked
- * in a retry loop, even if you are certain the lock is free.
+ * TAS() and TAS_SPIN() are NOT part of the API, and should never be called
+ * directly.
*
- * ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
- * points, ie, loads and stores of other values must not be moved across
- * a lock or unlock. In most cases it suffices to make the operation be
- * done through a "volatile" pointer.
+ * CAUTION: on some platforms TAS() and/or TAS_SPIN() 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 a retry loop must
+ * always be used, even if you are certain the lock is free.
+ *
+ * ANOTHER CAUTION: be sure that TAS(), TAS_SPIN(), and S_UNLOCK() represent
+ * sequence points, ie, loads and stores of other values must not be moved
+ * across a lock or unlock. In most cases it suffices to make the operation
+ * be done through a "volatile" pointer.
*
* On most supported platforms, TAS() uses a tas() function written
* in assembly language to execute a hardware atomic-test-and-set
#include <ia64/sys/inline.h>
#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
+#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
#endif /* HPUX on IA64, non gcc */
#define TAS(lock) tas(lock)
#endif /* TAS */
+#if !defined(TAS_SPIN)
+#define TAS_SPIN(lock) TAS(lock)
+#endif /* TAS_SPIN */
+
/*
* Platform-independent out-of-line support routines