diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/transam/xlog.c | 82 | ||||
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 6 | ||||
-rw-r--r-- | src/backend/storage/buffer/s_lock.c | 52 |
3 files changed, 69 insertions, 71 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 7294b97ff34..ff8916cd37b 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -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) { diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 2adea99e82c..d97ddfdbff4 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -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; 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); } } |