|
31 | 31 | * macros at the bottom of the file. Check if your platform can use
|
32 | 32 | * these or needs to override them.
|
33 | 33 | *
|
34 |
| - * Usually, S_LOCK() is implemented in terms of an even lower-level macro |
35 |
| - * TAS(): |
| 34 | + * Usually, S_LOCK() is implemented in terms of even lower-level macros |
| 35 | + * TAS() and TAS_SPIN(): |
36 | 36 | *
|
37 | 37 | * int TAS(slock_t *lock)
|
38 | 38 | * Atomic test-and-set instruction. Attempt to acquire the lock,
|
39 | 39 | * but do *not* wait. Returns 0 if successful, nonzero if unable
|
40 | 40 | * to acquire the lock.
|
41 | 41 | *
|
42 |
| - * TAS() is NOT part of the API, and should never be called directly. |
| 42 | + * int TAS_SPIN(slock_t *lock) |
| 43 | + * Like TAS(), but this version is used when waiting for a lock |
| 44 | + * previously found to be contended. Typically, this is the |
| 45 | + * same as TAS(), but on some architectures it's better to poll a |
| 46 | + * contended lock using an unlocked instruction and retry the |
| 47 | + * atomic test-and-set only when it appears free. |
43 | 48 | *
|
44 |
| - * CAUTION: on some platforms TAS() may sometimes report failure to acquire |
45 |
| - * a lock even when the lock is not locked. For example, on Alpha TAS() |
46 |
| - * will "fail" if interrupted. Therefore TAS() should always be invoked |
47 |
| - * in a retry loop, even if you are certain the lock is free. |
| 49 | + * TAS() and TAS_SPIN() are NOT part of the API, and should never be called |
| 50 | + * directly. |
48 | 51 | *
|
49 |
| - * ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence |
50 |
| - * points, ie, loads and stores of other values must not be moved across |
51 |
| - * a lock or unlock. In most cases it suffices to make the operation be |
52 |
| - * done through a "volatile" pointer. |
| 52 | + * CAUTION: on some platforms TAS() and/or TAS_SPIN() may sometimes report |
| 53 | + * failure to acquire a lock even when the lock is not locked. For example, |
| 54 | + * on Alpha TAS() will "fail" if interrupted. Therefore a retry loop must |
| 55 | + * always be used, even if you are certain the lock is free. |
| 56 | + * |
| 57 | + * ANOTHER CAUTION: be sure that TAS(), TAS_SPIN(), and S_UNLOCK() represent |
| 58 | + * sequence points, ie, loads and stores of other values must not be moved |
| 59 | + * across a lock or unlock. In most cases it suffices to make the operation |
| 60 | + * be done through a "volatile" pointer. |
53 | 61 | *
|
54 | 62 | * On most supported platforms, TAS() uses a tas() function written
|
55 | 63 | * in assembly language to execute a hardware atomic-test-and-set
|
@@ -727,6 +735,7 @@ typedef unsigned int slock_t;
|
727 | 735 |
|
728 | 736 | #include <ia64/sys/inline.h>
|
729 | 737 | #define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
|
| 738 | +#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock)) |
730 | 739 |
|
731 | 740 | #endif /* HPUX on IA64, non gcc */
|
732 | 741 |
|
@@ -925,6 +934,10 @@ extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
|
925 | 934 | #define TAS(lock) tas(lock)
|
926 | 935 | #endif /* TAS */
|
927 | 936 |
|
| 937 | +#if !defined(TAS_SPIN) |
| 938 | +#define TAS_SPIN(lock) TAS(lock) |
| 939 | +#endif /* TAS_SPIN */ |
| 940 | + |
928 | 941 |
|
929 | 942 | /*
|
930 | 943 | * Platform-independent out-of-line support routines
|
|
0 commit comments