Add more critical-section calls: all code sections that hold spinlocks
authorTom Lane
Fri, 12 Jan 2001 21:54:01 +0000 (21:54 +0000)
committerTom Lane
Fri, 12 Jan 2001 21:54:01 +0000 (21:54 +0000)
are now critical sections, so as to ensure die() won't interrupt us while
we are munging shared-memory data structures.  Avoid insecure intermediate
states in some code that proc_exit will call, like palloc/pfree.  Rename
START/END_CRIT_CODE to START/END_CRIT_SECTION, since that seems to be
what people tend to call them anyway, and make them be called with () like
a function call, in hopes of not confusing pg_indent.
I doubt that this is sufficient to make SIGTERM safe anywhere; there's
just too much code that could get invoked during proc_exit().

17 files changed:
src/backend/access/heap/heapam.c
src/backend/access/nbtree/nbtinsert.c
src/backend/access/nbtree/nbtpage.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/commands/sequence.c
src/backend/commands/vacuum.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/file/fd.c
src/backend/storage/ipc/spin.c
src/backend/storage/lmgr/proc.c
src/backend/tcop/postgres.c
src/backend/utils/cache/temprel.c
src/backend/utils/init/postinit.c
src/backend/utils/mmgr/aset.c
src/include/access/xlog.h
src/include/utils/elog.h

index 612e4c68611fc52d87226715c5cba40e181e9790..db443218b4def352bf3b2d5939a26dc85f9cc137 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.106 2001/01/07 22:14:31 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.107 2001/01/12 21:53:54 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1359,7 +1359,7 @@ heap_insert(Relation relation, HeapTuple tup)
    buffer = RelationGetBufferForTuple(relation, tup->t_len);
 
    /* NO ELOG(ERROR) from here till changes are logged */
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
    RelationPutHeapTuple(relation, buffer, tup);
 
    /* XLOG stuff */
@@ -1405,7 +1405,7 @@ heap_insert(Relation relation, HeapTuple tup)
        PageSetLSN(page, recptr);
        PageSetSUI(page, ThisStartUpID);
    }
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
    LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
    WriteBuffer(buffer);
@@ -1503,7 +1503,7 @@ l1:
        return result;
    }
 
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
    /* store transaction information of xact deleting the tuple */
    TransactionIdStore(GetCurrentTransactionId(), &(tp.t_data->t_xmax));
    tp.t_data->t_cmax = GetCurrentCommandId();
@@ -1532,7 +1532,7 @@ l1:
        PageSetLSN(dp, recptr);
        PageSetSUI(dp, ThisStartUpID);
    }
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
 #ifdef TUPLE_TOASTER_ACTIVE
    /* ----------
@@ -1702,7 +1702,7 @@ l2:
    }
 
    /* NO ELOG(ERROR) from here till changes are logged */
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
 
    RelationPutHeapTuple(relation, newbuf, newtup); /* insert new tuple */
    if (buffer == newbuf)
@@ -1734,7 +1734,7 @@ l2:
        PageSetLSN(BufferGetPage(buffer), recptr);
        PageSetSUI(BufferGetPage(buffer), ThisStartUpID);
    }
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
    if (newbuf != buffer)
        LockBuffer(newbuf, BUFFER_LOCK_UNLOCK);
index cdd5c6d620710852ba08178cc714abadba0267b9..1aae86c00257918a258eed8ceec5d14d999d63d1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.72 2000/12/29 20:47:16 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.73 2001/01/12 21:53:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -518,7 +518,7 @@ _bt_insertonpg(Relation rel,
    }
    else
    {
-       START_CRIT_CODE;
+       START_CRIT_SECTION();
        _bt_pgaddtup(rel, page, itemsz, btitem, newitemoff, "page");
        itup_off = newitemoff;
        itup_blkno = BufferGetBlockNumber(buf);
@@ -563,7 +563,7 @@ _bt_insertonpg(Relation rel,
            PageSetSUI(page, ThisStartUpID);
        }
 
-       END_CRIT_CODE;
+       END_CRIT_SECTION();
        /* Write out the updated page and release pin/lock */
        _bt_wrtbuf(rel, buf);
    }
@@ -774,7 +774,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
     * NO ELOG(ERROR) till right sibling is updated.
     *
     */
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
    {
        xl_btree_split  xlrec;
        int             flag = (newitemonleft) ? 
@@ -863,7 +863,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
    /* write and release the old right sibling */
    if (!P_RIGHTMOST(ropaque))
        _bt_wrtbuf(rel, sbuf);
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
    /* split's done */
    return rbuf;
@@ -1160,7 +1160,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
    metad = BTPageGetMeta(metapg);
 
    /* NO ELOG(ERROR) from here till newroot op is logged */
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
 
    /* set btree special data */
    rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
@@ -1253,7 +1253,7 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
        PageSetSUI(metapg, ThisStartUpID);
 
    }
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
    /* write and let go of the new root buffer */
    _bt_wrtbuf(rel, rootbuf);
index e2e403a2afc837608ec74761a387e72b9480cfc5..81faf71c9d42b090d1b7b05474bca0d6f676a032 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.45 2000/12/29 20:47:17 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.46 2001/01/12 21:53:55 tgl Exp $
  *
  * NOTES
  *    Postgres btree pages look like ordinary relation pages.  The opaque
@@ -165,7 +165,7 @@ _bt_getroot(Relation rel, int access)
            rootpage = BufferGetPage(rootbuf);
 
            /* NO ELOG(ERROR) till meta is updated */
-           START_CRIT_CODE;
+           START_CRIT_SECTION();
 
            metad->btm_root = rootblkno;
            metad->btm_level = 1;
@@ -197,7 +197,7 @@ _bt_getroot(Relation rel, int access)
                PageSetSUI(metapg, ThisStartUpID);
            }
 
-           END_CRIT_CODE;
+           END_CRIT_SECTION();
 
            _bt_wrtnorelbuf(rel, rootbuf);
 
@@ -410,7 +410,7 @@ _bt_pagedel(Relation rel, ItemPointer tid)
    buf = _bt_getbuf(rel, blkno, BT_WRITE);
    page = BufferGetPage(buf);
 
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
    PageIndexTupleDelete(page, offno);
    /* XLOG stuff */
    {
@@ -435,7 +435,7 @@ _bt_pagedel(Relation rel, ItemPointer tid)
        PageSetLSN(page, recptr);
        PageSetSUI(page, ThisStartUpID);
    }
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
    /* write the buffer and release the lock */
    _bt_wrtbuf(rel, buf);
index 50f4f1a10091baa67fb5a50546802afab763637d..e3f4a5618f7a3b6decd36fe361af4e84b01fdd6d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.91 2000/12/28 13:00:08 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.92 2001/01/12 21:53:56 tgl Exp $
  *
  * NOTES
  *     Transaction aborts can now occur two ways:
@@ -678,7 +678,7 @@ RecordTransactionCommit()
        rdata.len = SizeOfXactCommit;
        rdata.next = NULL;
 
-       START_CRIT_CODE;
+       START_CRIT_SECTION();
        /*
         * SHOULD SAVE ARRAY OF RELFILENODE-s TO DROP
         */
@@ -697,7 +697,7 @@ RecordTransactionCommit()
        TransactionIdCommit(xid);
 
        MyProc->logRec.xrecoff = 0;
-       END_CRIT_CODE;
+       END_CRIT_SECTION();
    }
 
    if (leak)
@@ -800,12 +800,12 @@ RecordTransactionAbort(void)
        rdata.len = SizeOfXactAbort;
        rdata.next = NULL;
 
-       START_CRIT_CODE;
+       START_CRIT_SECTION();
        recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, &rdata);
 
        TransactionIdAbort(xid);
        MyProc->logRec.xrecoff = 0;
-       END_CRIT_CODE;
+       END_CRIT_SECTION();
    }
 
    /*
index c0b6104db5ab2f011d0a1846c357f7bc4c151bbf..e995b06f914f76a5473b43d3bc4510ea15dce820 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.48 2001/01/09 06:24:32 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.49 2001/01/12 21:53:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,7 +42,7 @@
 int            XLOGbuffers = 8;
 int            XLOGfiles = 0;  /* how many files to pre-allocate */
 XLogRecPtr MyLastRecPtr = {0, 0};
-uint32     CritSectionCount = 0;
+volatile uint32 CritSectionCount = 0;
 bool       InRecovery = false;
 StartUpID  ThisStartUpID = 0;
 XLogRecPtr RedoRecPtr;
@@ -382,7 +382,7 @@ begin:;
    if (len == 0 || len > MAXLOGRECSZ)
        elog(STOP, "XLogInsert: invalid record len %u", len);
 
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
 
    /* obtain xlog insert lock */
    if (TAS(&(XLogCtl->insert_lck)))    /* busy */
@@ -447,7 +447,7 @@ begin:;
    if (repeat)
    {
        S_UNLOCK(&(XLogCtl->insert_lck));
-       END_CRIT_CODE;
+       END_CRIT_SECTION();
        goto begin;
    }
 
@@ -618,7 +618,7 @@ begin:;
        S_UNLOCK(&(XLogCtl->info_lck));
    }
 
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
    return (RecPtr);
 }
 
@@ -647,7 +647,7 @@ XLogFlush(XLogRecPtr record)
    if (XLByteLE(record, LgwrResult.Flush))
        return;
 
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
 
    WriteRqst = LgwrRqst.Write;
    for (;;)
@@ -659,7 +659,7 @@ XLogFlush(XLogRecPtr record)
            if (XLByteLE(record, LgwrResult.Flush))
            {
                S_UNLOCK(&(XLogCtl->info_lck));
-               END_CRIT_CODE;
+               END_CRIT_SECTION();
                return;
            }
            if (XLByteLT(XLogCtl->LgwrRqst.Flush, record))
@@ -705,7 +705,7 @@ XLogFlush(XLogRecPtr record)
                if (XLByteLE(record, LgwrResult.Flush))
                {
                    S_UNLOCK(&(XLogCtl->lgwr_lck));
-                   END_CRIT_CODE;
+                   END_CRIT_SECTION();
                    return;
                }
                if (XLByteLT(LgwrResult.Write, WriteRqst))
@@ -715,7 +715,7 @@ XLogFlush(XLogRecPtr record)
                    S_UNLOCK(&(XLogCtl->lgwr_lck));
                    if (XLByteLT(LgwrResult.Flush, record))
                        elog(STOP, "XLogFlush: request is not satisfied");
-                   END_CRIT_CODE;
+                   END_CRIT_SECTION();
                    return;
                }
                break;
@@ -756,7 +756,7 @@ XLogFlush(XLogRecPtr record)
 
    S_UNLOCK(&(XLogCtl->lgwr_lck));
 
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
    return;
 
 }
@@ -2081,7 +2081,7 @@ CreateCheckPoint(bool shutdown)
    if (MyLastRecPtr.xrecoff != 0)
        elog(ERROR, "CreateCheckPoint: cannot be called inside transaction block");
  
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
 
    /* Grab lock, using larger than normal sleep between tries (1 sec) */
    while (TAS(&(XLogCtl->chkp_lck)))
@@ -2230,7 +2230,7 @@ CreateCheckPoint(bool shutdown)
    S_UNLOCK(&(XLogCtl->chkp_lck));
 
    MyLastRecPtr.xrecoff = 0;   /* to avoid commit record */
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
    return;
 }
index 64fc0102a876871913bc4fad74683a8197413b9c..f6e63283121d39ada5d044510b6353b8c91938e5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.47 2000/12/28 13:00:17 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.48 2001/01/12 21:53:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -301,7 +301,7 @@ nextval(PG_FUNCTION_ARGS)
    elm->last = result;         /* last returned number */
    elm->cached = last;         /* last fetched number */
 
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
    if (logit)
    {
        xl_seq_rec  xlrec;
@@ -338,7 +338,7 @@ nextval(PG_FUNCTION_ARGS)
    seq->is_called = 't';
    Assert(log >= 0);
    seq->log_cnt = log;         /* how much is logged */
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
    LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 
@@ -398,7 +398,7 @@ do_setval(char *seqname, int32 next, bool iscalled)
    elm->last = next;           /* last returned number */
    elm->cached = next;         /* last cached number (forget cached values) */
 
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
    {
        xl_seq_rec  xlrec;
        XLogRecPtr  recptr;
@@ -429,7 +429,7 @@ do_setval(char *seqname, int32 next, bool iscalled)
    seq->last_value = next;     /* last fetched number */
    seq->is_called = iscalled ? 't' : 'f';
    seq->log_cnt = (iscalled) ? 0 : 1;
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
    LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 
index 738d9e72838acfed081b1bbbbee500fb66165f57..76425652b9703b134062cbc38b6508e8a05e1052 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.181 2000/12/30 15:19:55 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.182 2001/01/12 21:53:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1427,7 +1427,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
                    Cpage = BufferGetPage(Cbuf);
 
                    /* NO ELOG(ERROR) TILL CHANGES ARE LOGGED */
-                   START_CRIT_CODE;
+                   START_CRIT_SECTION();
 
                    Citemid = PageGetItemId(Cpage,
                            ItemPointerGetOffsetNumber(&(tuple.t_self)));
@@ -1512,7 +1512,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
                        PageSetLSN(ToPage, recptr);
                        PageSetSUI(ToPage, ThisStartUpID);
                    }
-                   END_CRIT_CODE;
+                   END_CRIT_SECTION();
 
                    if (((int) destvacpage->blkno) > last_move_dest_block)
                        last_move_dest_block = destvacpage->blkno;
@@ -1637,7 +1637,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
            newtup.t_data->t_infomask |= HEAP_MOVED_IN;
 
            /* NO ELOG(ERROR) TILL CHANGES ARE LOGGED */
-           START_CRIT_CODE;
+           START_CRIT_SECTION();
 
            /* add tuple to the page */
            newoff = PageAddItem(ToPage, (Item) newtup.t_data, tuple_len,
@@ -1675,7 +1675,7 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
                PageSetLSN(ToPage, recptr);
                PageSetSUI(ToPage, ThisStartUpID);
            }
-           END_CRIT_CODE;
+           END_CRIT_SECTION();
 
            cur_page->offsets_used++;
            num_moved++;
@@ -1905,7 +1905,7 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
 
            buf = ReadBuffer(onerel, vacpage->blkno);
            LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
-           START_CRIT_CODE;
+           START_CRIT_SECTION();
            page = BufferGetPage(buf);
            num_tuples = 0;
            for (offnum = FirstOffsetNumber;
@@ -1941,7 +1941,7 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
                PageSetLSN(page, recptr);
                PageSetSUI(page, ThisStartUpID);
            }
-           END_CRIT_CODE;
+           END_CRIT_SECTION();
            LockBuffer(buf, BUFFER_LOCK_UNLOCK);
            WriteBuffer(buf);
        }
@@ -2056,7 +2056,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
    /* There shouldn't be any tuples moved onto the page yet! */
    Assert(vacpage->offsets_used == 0);
 
-   START_CRIT_CODE;
+   START_CRIT_SECTION();
    for (i = 0; i < vacpage->offsets_free; i++)
    {
        itemid = &(((PageHeader) page)->pd_linp[vacpage->offsets[i] - 1]);
@@ -2070,7 +2070,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
        PageSetLSN(page, recptr);
        PageSetSUI(page, ThisStartUpID);
    }
-   END_CRIT_CODE;
+   END_CRIT_SECTION();
 
 }
 
index 6ba74f5e06c73e94d5cc04cd812d6c673871cc73..2be519193bbf6fb253fff99d4f3a65ac9f1966be 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.102 2001/01/08 18:31:49 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.103 2001/01/12 21:53:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -404,8 +404,7 @@ BufferAlloc(Relation reln,
             */
            if ((buf->flags & BM_IO_ERROR) != 0)
            {
-               PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
-               buf->refcount--;
+               UnpinBuffer(buf);
                buf = (BufferDesc *) NULL;
                continue;
            }
@@ -869,8 +868,10 @@ WaitIO(BufferDesc *buf, SPINLOCK spinlock)
    while ((buf->flags & BM_IO_IN_PROGRESS) != 0)
    {
        SpinRelease(spinlock);
+       START_CRIT_SECTION();   /* don't want to die() holding the lock... */
        S_LOCK(&(buf->io_in_progress_lock));
        S_UNLOCK(&(buf->io_in_progress_lock));
+       END_CRIT_SECTION();
        SpinAcquire(spinlock);
    }
 }
@@ -921,14 +922,11 @@ ResetBufferUsage()
  *     ResetBufferPool
  *
  *     This routine is supposed to be called when a transaction aborts.
- *     it will release all the buffer pins held by the transaction.
+ *     It will release all the buffer pins held by the transaction.
  *     Currently, we also call it during commit if BufferPoolCheckLeak
  *     detected a problem --- in that case, isCommit is TRUE, and we
  *     only clean up buffer pin counts.
  *
- * During abort, we also forget any pending fsync requests.  Dirtied buffers
- * will still get written, eventually, but there will be no fsync for them.
- *
  * ----------------------------------------------
  */
 void
@@ -943,6 +941,7 @@ ResetBufferPool(bool isCommit)
            BufferDesc *buf = &BufferDescriptors[i];
 
            SpinAcquire(BufMgrLock);
+           PrivateRefCount[i] = 0;
            Assert(buf->refcount > 0);
            buf->refcount--;
            if (buf->refcount == 0)
@@ -952,7 +951,6 @@ ResetBufferPool(bool isCommit)
            }
            SpinRelease(BufMgrLock);
        }
-       PrivateRefCount[i] = 0;
    }
 
    ResetLocalBufferPool();
@@ -1900,7 +1898,7 @@ SetBufferCommitInfoNeedsSave(Buffer buffer)
 }
 
 void
-UnlockBuffers()
+UnlockBuffers(void)
 {
    BufferDesc *buf;
    int         i;
@@ -1913,6 +1911,8 @@ UnlockBuffers()
        Assert(BufferIsValid(i + 1));
        buf = &(BufferDescriptors[i]);
 
+       START_CRIT_SECTION();   /* don't want to die() holding the lock... */
+
        S_LOCK(&(buf->cntx_lock));
 
        if (BufferLocks[i] & BL_R_LOCK)
@@ -1940,6 +1940,8 @@ UnlockBuffers()
        S_UNLOCK(&(buf->cntx_lock));
 
        BufferLocks[i] = 0;
+
+       END_CRIT_SECTION();
    }
 }
 
@@ -1956,6 +1958,8 @@ LockBuffer(Buffer buffer, int mode)
    buf = &(BufferDescriptors[buffer - 1]);
    buflock = &(BufferLocks[buffer - 1]);
 
+   START_CRIT_SECTION();       /* don't want to die() holding the lock... */
+
    S_LOCK(&(buf->cntx_lock));
 
    if (mode == BUFFER_LOCK_UNLOCK)
@@ -1979,6 +1983,7 @@ LockBuffer(Buffer buffer, int mode)
        else
        {
            S_UNLOCK(&(buf->cntx_lock));
+           END_CRIT_SECTION();
            elog(ERROR, "UNLockBuffer: buffer %lu is not locked", buffer);
        }
    }
@@ -1990,7 +1995,9 @@ LockBuffer(Buffer buffer, int mode)
        while (buf->ri_lock || buf->w_lock)
        {
            S_UNLOCK(&(buf->cntx_lock));
+           END_CRIT_SECTION();
            S_LOCK_SLEEP(&(buf->cntx_lock), i++);
+           START_CRIT_SECTION();
            S_LOCK(&(buf->cntx_lock));
        }
        (buf->r_locks)++;
@@ -2016,7 +2023,9 @@ LockBuffer(Buffer buffer, int mode)
                buf->ri_lock = true;
            }
            S_UNLOCK(&(buf->cntx_lock));
+           END_CRIT_SECTION();
            S_LOCK_SLEEP(&(buf->cntx_lock), i++);
+           START_CRIT_SECTION();
            S_LOCK(&(buf->cntx_lock));
        }
        buf->w_lock = true;
@@ -2038,10 +2047,12 @@ LockBuffer(Buffer buffer, int mode)
    else
    {
        S_UNLOCK(&(buf->cntx_lock));
+       END_CRIT_SECTION();
        elog(ERROR, "LockBuffer: unknown lock mode %d", mode);
    }
 
    S_UNLOCK(&(buf->cntx_lock));
+   END_CRIT_SECTION();
 }
 
 /*
@@ -2062,7 +2073,9 @@ static bool IsForInput;
  * BM_IO_IN_PROGRESS mask is not set for the buffer
  * The buffer is Pinned
  *
-*/
+ * Because BufMgrLock is held, we are already in a CRIT_SECTION here,
+ * and do not need another.
+ */
 static void
 StartBufferIO(BufferDesc *buf, bool forInput)
 {
@@ -2094,7 +2107,9 @@ StartBufferIO(BufferDesc *buf, bool forInput)
  * BufMgrLock is held
  * The buffer is Pinned
  *
-*/
+ * Because BufMgrLock is held, we are already in a CRIT_SECTION here,
+ * and do not need another.
+ */
 static void
 TerminateBufferIO(BufferDesc *buf)
 {
@@ -2110,7 +2125,9 @@ TerminateBufferIO(BufferDesc *buf)
  * BufMgrLock is held
  * The buffer is Pinned
  *
-*/
+ * Because BufMgrLock is held, we are already in a CRIT_SECTION here,
+ * and do not need another.
+ */
 static void
 ContinueBufferIO(BufferDesc *buf, bool forInput)
 {
@@ -2132,7 +2149,7 @@ InitBufferIO(void)
  * This function is called from ProcReleaseSpins().
  * BufMgrLock isn't held when this function is called.
  *
- * If I/O was in progress, BM_IO_ERROR is always set.
+ * If I/O was in progress, we always set BM_IO_ERROR.
  */
 void
 AbortBufferIO(void)
@@ -2141,8 +2158,8 @@ AbortBufferIO(void)
 
    if (buf)
    {
-       Assert(buf->flags & BM_IO_IN_PROGRESS);
        SpinAcquire(BufMgrLock);
+       Assert(buf->flags & BM_IO_IN_PROGRESS);
        if (IsForInput)
            Assert(!(buf->flags & BM_DIRTY) && !(buf->cntxDirty));
        else
index 3cff7932129626a57dc4d58c80196625004e9252..9ad40849eb3d28397369c8a47cb2163f552c895e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.69 2000/12/08 22:21:32 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.70 2001/01/12 21:53:58 tgl Exp $
  *
  * NOTES:
  *
@@ -770,7 +770,11 @@ FileClose(File file)
     * Delete the file if it was temporary
     */
    if (VfdCache[file].fdstate & FD_TEMPORARY)
+   {
+       /* reset flag so that die() interrupt won't cause problems */
+       VfdCache[file].fdstate &= ~FD_TEMPORARY;
        unlink(VfdCache[file].fileName);
+   }
 
    /*
     * Return the Vfd slot to the free list
@@ -1049,7 +1053,8 @@ AllocateFile(char *name, char *mode)
 TryAgain:
    if ((file = fopen(name, mode)) != NULL)
    {
-       allocatedFiles[numAllocatedFiles++] = file;
+       allocatedFiles[numAllocatedFiles] = file;
+       numAllocatedFiles++;
        return file;
    }
 
@@ -1080,7 +1085,8 @@ FreeFile(FILE *file)
    {
        if (allocatedFiles[i] == file)
        {
-           allocatedFiles[i] = allocatedFiles[--numAllocatedFiles];
+           numAllocatedFiles--;
+           allocatedFiles[i] = allocatedFiles[numAllocatedFiles];
            break;
        }
    }
index 554eeba797e7a82d358a7d506cb99ed3a1b561c0..ed71d79ad9f3cb7b278e502a4a44377f3bc37d3d 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.27 2000/12/11 00:49:52 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.28 2001/01/12 21:53:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -144,8 +144,21 @@ SpinAcquire(SPINLOCK lockid)
    SLock      *slckP = &(SLockArray[lockid]);
 
    PRINT_SLDEBUG("SpinAcquire", lockid, slckP);
+   /*
+    * Lock out die() until we exit the critical section protected by the
+    * spinlock.  This ensures that die() will not interrupt manipulations
+    * of data structures in shared memory.  We don't want die() to
+    * interrupt this routine between S_LOCK and PROC_INCR_SLOCK, either,
+    * so must do it before acquiring the lock, not after.
+    */
+   START_CRIT_SECTION();
+   /*
+    * Acquire the lock, then record that we have done so (for recovery
+    * in case of elog(ERROR) during the critical section).
+    */
    S_LOCK(&(slckP->shlock));
    PROC_INCR_SLOCK(lockid);
+
     PRINT_SLDEBUG("SpinAcquire/done", lockid, slckP);
 }
 
@@ -154,15 +167,22 @@ SpinRelease(SPINLOCK lockid)
 {
    SLock      *slckP = &(SLockArray[lockid]);
 
+    PRINT_SLDEBUG("SpinRelease", lockid, slckP);
    /*
     * Check that we are actually holding the lock we are releasing. This
     * can be done only after MyProc has been initialized.
     */
     Assert(!MyProc || MyProc->sLocks[lockid] > 0);
-
+   /*
+    * Record that we no longer hold the spinlock, and release it.
+    */
    PROC_DECR_SLOCK(lockid);
-    PRINT_SLDEBUG("SpinRelease", lockid, slckP);
    S_UNLOCK(&(slckP->shlock));
+   /*
+    * Exit the critical section entered in SpinAcquire().
+    */
+   END_CRIT_SECTION();
+
     PRINT_SLDEBUG("SpinRelease/done", lockid, slckP);
 }
 
@@ -187,7 +207,7 @@ SpinRelease(SPINLOCK lockid)
  *
  * Note that the SpinLockIds array is not in shared memory; it is filled
  * by the postmaster and then inherited through fork() by backends.  This
- * is OK because its contents do not change after system startup.
+ * is OK because its contents do not change after shmem initialization.
  */
 
 #define SPINLOCKS_PER_SET  PROC_NSEMS_PER_SET
@@ -285,6 +305,8 @@ SpinFreeAllSemaphores(void)
        if (SpinLockIds[i] >= 0)
            IpcSemaphoreKill(SpinLockIds[i]);
    }
+   free(SpinLockIds);
+   SpinLockIds = NULL;
 }
 
 /*
@@ -295,6 +317,8 @@ SpinFreeAllSemaphores(void)
 void
 SpinAcquire(SPINLOCK lock)
 {
+   /* See the TAS() version of this routine for commentary */
+   START_CRIT_SECTION();
    IpcSemaphoreLock(SpinLockIds[0], lock);
    PROC_INCR_SLOCK(lock);
 }
@@ -307,15 +331,18 @@ SpinAcquire(SPINLOCK lock)
 void
 SpinRelease(SPINLOCK lock)
 {
+   /* See the TAS() version of this routine for commentary */
 #ifdef USE_ASSERT_CHECKING
    /* Check it's locked */
    int         semval;
 
    semval = IpcSemaphoreGetValue(SpinLockIds[0], lock);
    Assert(semval < 1);
+    Assert(!MyProc || MyProc->sLocks[lockid] > 0);
 #endif
    PROC_DECR_SLOCK(lock);
    IpcSemaphoreUnlock(SpinLockIds[0], lock);
+   END_CRIT_SECTION();
 }
 
 /*
index 2730c8811e6e91a19bd215c8ebf522c58c2e66c5..baa31413e2fefd5c8ebda9a81f39b8c0246c74b8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.90 2001/01/09 09:38:57 inoue Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.91 2001/01/12 21:53:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,7 +48,7 @@
  *     This is so that we can support more backends. (system-wide semaphore
  *     sets run out pretty fast.)                -ay 4/95
  *
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.90 2001/01/09 09:38:57 inoue Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.91 2001/01/12 21:53:59 tgl Exp $
  */
 #include "postgres.h"
 
@@ -241,7 +241,6 @@ InitProcess(void)
    MemSet(MyProc->sLocks, 0, sizeof(MyProc->sLocks));
    MyProc->sLocks[ProcStructLock] = 1;
 
-
    if (IsUnderPostmaster)
    {
        IpcSemaphoreId  semId;
@@ -264,23 +263,16 @@ InitProcess(void)
    else
        MyProc->sem.semId = -1;
 
-   /* ----------------------
-    * Release the lock.
-    * ----------------------
-    */
-   SpinRelease(ProcStructLock);
-
    MyProc->pid = MyProcPid;
    MyProc->databaseId = MyDatabaseId;
    MyProc->xid = InvalidTransactionId;
    MyProc->xmin = InvalidTransactionId;
 
-   /* ----------------
-    * Start keeping spin lock stats from here on.  Any botch before
-    * this initialization is forever botched
-    * ----------------
+   /* ----------------------
+    * Release the lock.
+    * ----------------------
     */
-   MemSet(MyProc->sLocks, 0, MAX_SPINS * sizeof(*MyProc->sLocks));
+   SpinRelease(ProcStructLock);
 
    /* -------------------------
     * Install ourselves in the shmem index table.  The name to
@@ -412,15 +404,6 @@ ProcKill(int exitStatus, Datum pid)
 {
    PROC       *proc;
 
-   /* --------------------
-    * If this is a FATAL exit the postmaster will have to kill all the
-    * existing backends and reinitialize shared memory.  So we don't
-    * need to do anything here.
-    * --------------------
-    */
-   if (exitStatus != 0)
-       return;
-
    if ((int) pid == MyProcPid)
    {
        proc = MyProc;
index a73ba4df4abc1ba33cad7356e0c9f114f044998c..1a0aa5d0cdf1c347b83fcccf7f6ef0f4a27e8a56 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.199 2001/01/07 04:17:29 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.200 2001/01/12 21:53:59 tgl Exp $
  *
  * NOTES
  *   this is the "main" module of the postgres backend and
@@ -982,7 +982,7 @@ die(SIGNAL_ARGS)
 
 /*
  * This is split out of die() so that it can be invoked later from
- * END_CRIT_CODE.
+ * END_CRIT_SECTION().
  */
 void
 ForceProcDie(void)
@@ -1683,7 +1683,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
    if (!IsUnderPostmaster)
    {
        puts("\nPOSTGRES backend interactive interface ");
-       puts("$Revision: 1.199 $ $Date: 2001/01/07 04:17:29 $\n");
+       puts("$Revision: 1.200 $ $Date: 2001/01/12 21:53:59 $\n");
    }
 
    /*
index a0066f2eaff4ed24e2027aa420f7f345755a4e65..b1580d65b4903f48395af183990779cca2b4ce70 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.32 2000/12/22 23:12:07 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.33 2001/01/12 21:54:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -263,8 +263,6 @@ AtEOXact_temp_relations(bool isCommit)
            temp_rel->created_in_cur_xact)
        {
            /* This entry must be removed */
-           pfree(temp_rel);
-           /* remove from linked list */
            if (prev != NIL)
            {
                lnext(prev) = lnext(l);
@@ -277,6 +275,7 @@ AtEOXact_temp_relations(bool isCommit)
                pfree(l);
                l = temp_rels;
            }
+           pfree(temp_rel);
        }
        else
        {
index c8bd8a0d26687ca7d0705967cf848e3d88edd343..6248c7bea6c60ec92a4042f8b1572685ceefd7c8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.76 2000/12/18 00:44:48 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.77 2001/01/12 21:54:00 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -395,11 +395,12 @@ ShutdownPostgres(void)
     * We don't want to do any inessential cleanup, since that just raises
     * the odds of failure --- but there's some stuff we need to do.
     *
-    * Release any spinlocks that we may hold.  This is a kluge to improve
-    * the odds that we won't get into a self-made stuck spinlock scenario
-    * while trying to shut down.
+    * Release any spinlocks or buffer context locks we might be holding.
+    * This is a kluge to improve the odds that we won't get into a self-made
+    * stuck-spinlock scenario while trying to shut down.
     */
    ProcReleaseSpins(NULL);
+   UnlockBuffers();
    /*
     * In case a transaction is open, delete any files it created.  This
     * has to happen before bufmgr shutdown, so having smgr register a
index cdb2601e38d1153c70497a4bd1d0605495b364a9..5c0cf3074531a92da0e0afa912e8a14179ef87ce 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.36 2001/01/06 21:59:39 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.37 2001/01/12 21:54:01 tgl Exp $
  *
  * NOTE:
  * This is a new (Feb. 05, 1999) implementation of the allocation set
@@ -384,6 +384,11 @@ AllocSetReset(MemoryContext context)
    AllocSetCheck(context);
 #endif
 
+   /* Clear chunk freelists */
+   MemSet(set->freelist, 0, sizeof(set->freelist));
+   /* New blocks list is either empty or just the keeper block */
+   set->blocks = set->keeper;
+
    while (block != NULL)
    {
        AllocBlock  next = block->next;
@@ -411,11 +416,6 @@ AllocSetReset(MemoryContext context)
        }
        block = next;
    }
-
-   /* Now blocks list is either empty or just the keeper block */
-   set->blocks = set->keeper;
-   /* Clear chunk freelists in any case */
-   MemSet(set->freelist, 0, sizeof(set->freelist));
 }
 
 /*
@@ -439,6 +439,11 @@ AllocSetDelete(MemoryContext context)
    AllocSetCheck(context);
 #endif
 
+   /* Make it look empty, just in case... */
+   MemSet(set->freelist, 0, sizeof(set->freelist));
+   set->blocks = NULL;
+   set->keeper = NULL;
+
    while (block != NULL)
    {
        AllocBlock  next = block->next;
@@ -450,11 +455,6 @@ AllocSetDelete(MemoryContext context)
        free(block);
        block = next;
    }
-
-   /* Make it look empty, just in case... */
-   set->blocks = NULL;
-   MemSet(set->freelist, 0, sizeof(set->freelist));
-   set->keeper = NULL;
 }
 
 /*
@@ -605,15 +605,16 @@ AllocSetAlloc(MemoryContext context, Size size)
                }
 
                chunk = (AllocChunk) (block->freeptr);
+
+               block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
+               availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
+
                chunk->size = availchunk;
 #ifdef MEMORY_CONTEXT_CHECKING
                chunk->requested_size = 0; /* mark it free */
 #endif
                chunk->aset = (void *) set->freelist[a_fidx];
                set->freelist[a_fidx] = chunk;
-
-               block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
-               availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
            }
 
            /* Mark that we need to create a new block */
@@ -696,6 +697,10 @@ AllocSetAlloc(MemoryContext context, Size size)
     * OK, do the allocation
     */
    chunk = (AllocChunk) (block->freeptr);
+
+   block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
+   Assert(block->freeptr <= block->endptr);
+
    chunk->aset = (void *) set;
    chunk->size = chunk_size;
 #ifdef MEMORY_CONTEXT_CHECKING
@@ -705,9 +710,6 @@ AllocSetAlloc(MemoryContext context, Size size)
        ((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;
 #endif 
 
-   block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
-   Assert(block->freeptr <= block->endptr);
-
    AllocAllocInfo(set, chunk);
    return AllocChunkGetPointer(chunk);
 }
index 88268b0b0b20ac614fb4987b38b3de042163a6e0..7736ec92e8733b88cc4139c1b6eff98285de0535 100644 (file)
@@ -3,7 +3,7 @@
  *
  * PostgreSQL transaction log manager
  *
- * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.15 2000/12/28 13:00:25 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.16 2001/01/12 21:54:01 tgl Exp $
  */
 #ifndef XLOG_H
 #define XLOG_H
@@ -101,7 +101,7 @@ typedef XLogPageHeaderData *XLogPageHeader;
 extern StartUpID   ThisStartUpID;  /* current SUI */
 extern bool        InRecovery;
 extern XLogRecPtr  MyLastRecPtr;
-extern uint32      CritSectionCount;
+extern volatile uint32     CritSectionCount;
 
 typedef struct RmgrData
 {
index e7305d67fc266bd18df746530de43508c3f938d7..da9178b2767f3d41f5e0344bea37941b3ad542f4 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: elog.h,v 1.22 2001/01/07 04:17:28 tgl Exp $
+ * $Id: elog.h,v 1.23 2001/01/12 21:54:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -34,16 +34,15 @@ extern int Use_syslog;
  * ProcDiePending will be honored at critical section exit,
  * but QueryCancel is only checked at specified points.
  */
-extern uint32 CritSectionCount;    /* duplicates access/xlog.h */
+extern volatile uint32 CritSectionCount;   /* duplicates access/xlog.h */
 extern volatile bool ProcDiePending;
 extern void ForceProcDie(void);    /* in postgres.c */
 
-#define    START_CRIT_CODE     (CritSectionCount++)
+#define    START_CRIT_SECTION()  (CritSectionCount++)
 
-#define END_CRIT_CODE  \
+#define END_CRIT_SECTION() \
    do { \
-       if (CritSectionCount == 0) \
-           elog(STOP, "Not in critical section"); \
+       Assert(CritSectionCount > 0); \
        CritSectionCount--; \
        if (CritSectionCount == 0 && ProcDiePending) \
            ForceProcDie(); \