diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-12-29 21:31:21 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-12-29 21:31:21 +0000 |
commit | 7f60b81e1ab7cbb27298e980f25445dfa58d50bb (patch) | |
tree | f1ace7fa85f8f4037bf254008b41e65c9a7ce7f8 /src/backend/storage/buffer/s_lock.c | |
parent | 7d363c4c3376459bc9389b250bc7b70e9cf7aa75 (diff) | |
download | postgresql-7f60b81e1ab7cbb27298e980f25445dfa58d50bb.tar.gz postgresql-7f60b81e1ab7cbb27298e980f25445dfa58d50bb.zip |
Fix failure in CreateCheckPoint on some Alpha boxes --- it's not OK to
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.
Diffstat (limited to 'src/backend/storage/buffer/s_lock.c')
-rw-r--r-- | src/backend/storage/buffer/s_lock.c | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/src/backend/storage/buffer/s_lock.c b/src/backend/storage/buffer/s_lock.c index 7f658ad26a8..932e5b0049b 100644 --- a/src/backend/storage/buffer/s_lock.c +++ b/src/backend/storage/buffer/s_lock.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -25,19 +25,21 @@ * 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); } } |