]> granicus.if.org Git - postgresql/blobdiff - src/backend/storage/lmgr/proc.c
Banish caddr_t (mostly), use Datum where appropriate.
[postgresql] / src / backend / storage / lmgr / proc.c
index 01097fcd2fe642ebada361535a2b3b6cd020fce8..e68d96d772951f89f4aaf1093e92b152ca0eed26 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.67 2000/01/26 05:57:02 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.80 2000/10/02 19:42:48 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
  *             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.67 2000/01/26 05:57:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.80 2000/10/02 19:42:48 petere Exp $
  */
+#include "postgres.h"
+
 #include <sys/time.h>
 #include <unistd.h>
 #include <signal.h>
 #include <sys/sem.h>
 #endif
 
-#include "postgres.h"
 #include "miscadmin.h"
-#include "libpq/pqsignal.h"
 
 
-#include "storage/ipc.h"
 /* In Ultrix and QNX, sem.h must be included after ipc.h */
 #include <sys/sem.h>
 
-#include "storage/lmgr.h"
 #include "storage/proc.h"
-#include "utils/trace.h"
 
-void HandleDeadLock(SIGNAL_ARGS);
+void           HandleDeadLock(SIGNAL_ARGS);
 static void ProcFreeAllSemaphores(void);
+static bool GetOffWaitqueue(PROC *);
 
-#define DeadlockCheckTimer pg_options[OPT_DEADLOCKTIMEOUT]
+int DeadlockTimeout = 1000;
 
 /* --------------------
  * Spin lock for manipulating the shared process data structure:
@@ -122,7 +120,7 @@ InitProcGlobal(IPCKey key, int maxBackends)
 
        /* attach to the free list */
        ProcGlobal = (PROC_HDR *)
-               ShmemInitStruct("Proc Header", (unsigned) sizeof(PROC_HDR), &found);
+               ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
 
        /* --------------------
         * We're the first - initialize.
@@ -143,7 +141,7 @@ InitProcGlobal(IPCKey key, int maxBackends)
                 * Arrange to delete semas on exit --- set this up now so that we
                 * will clean up if pre-allocation fails...
                 */
-               on_shmem_exit(ProcFreeAllSemaphores, NULL);
+               on_shmem_exit(ProcFreeAllSemaphores, 0);
 
                /*
                 * Pre-create the semaphores for the first maxBackends processes,
@@ -188,7 +186,7 @@ InitProcess(IPCKey key)
 
        /* attach to the free list */
        ProcGlobal = (PROC_HDR *)
-               ShmemInitStruct("Proc Header", (unsigned) sizeof(PROC_HDR), &found);
+               ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
        if (!found)
        {
                /* this should not happen. InitProcGlobal() is called before this. */
@@ -221,7 +219,7 @@ InitProcess(IPCKey key)
                 * cleanup dead processes).
                 */
 
-               MyProc = (PROC *) ShmemAlloc((unsigned) sizeof(PROC));
+               MyProc = (PROC *) ShmemAlloc(sizeof(PROC));
                if (!MyProc)
                {
                        SpinRelease(ProcStructLock);
@@ -309,7 +307,42 @@ InitProcess(IPCKey key)
        MyProc->errType = NO_ERROR;
        SHMQueueElemInit(&(MyProc->links));
 
-       on_shmem_exit(ProcKill, (caddr_t) MyProcPid);
+       on_shmem_exit(ProcKill, (Datum) MyProcPid);
+}
+
+/* -----------------------
+ * get off the wait queue
+ * -----------------------
+ */
+static bool
+GetOffWaitqueue(PROC *proc)
+{
+       bool            getoffed = false;
+
+       LockLockTable();
+       if (proc->links.next != INVALID_OFFSET)
+       {
+               int                     lockmode = proc->token;
+               LOCK    *waitLock = proc->waitLock;
+
+               Assert(waitLock);
+               Assert(waitLock->waitProcs.size > 0);
+               SHMQueueDelete(&(proc->links));
+               --waitLock->waitProcs.size;
+               Assert(waitLock->nHolding > 0);
+               Assert(waitLock->nHolding > proc->waitLock->nActive);
+               --waitLock->nHolding;
+               Assert(waitLock->holders[lockmode] > 0);
+               --waitLock->holders[lockmode];
+               if (waitLock->activeHolders[lockmode] == waitLock->holders[lockmode])
+                       waitLock->waitMask &= ~(1 << lockmode);
+               ProcLockWakeup(&(waitLock->waitProcs), LOCK_LOCKMETHOD(*waitLock), waitLock);
+               getoffed = true;
+       }
+       SHMQueueElemInit(&(proc->links));
+       UnlockLockTable();
+
+       return getoffed;
 }
 
 /*
@@ -322,6 +355,7 @@ ProcReleaseLocks()
        if (!MyProc)
                return;
        LockReleaseAll(1, &MyProc->lockQueue);
+       GetOffWaitqueue(MyProc);
 }
 
 /*
@@ -405,15 +439,7 @@ ProcKill(int exitStatus, int pid)
         * get off the wait queue
         * ----------------
         */
-       LockLockTable();
-       if (proc->links.next != INVALID_OFFSET)
-       {
-               Assert(proc->waitLock->waitProcs.size > 0);
-               SHMQueueDelete(&(proc->links));
-               --proc->waitLock->waitProcs.size;
-       }
-       SHMQueueElemInit(&(proc->links));
-       UnlockLockTable();
+       GetOffWaitqueue(proc);
 
        return;
 }
@@ -435,7 +461,7 @@ ProcQueueAlloc(char *name)
 {
        bool            found;
        PROC_QUEUE *queue = (PROC_QUEUE *)
-       ShmemInitStruct(name, (unsigned) sizeof(PROC_QUEUE), &found);
+               ShmemInitStruct(name, sizeof(PROC_QUEUE), &found);
 
        if (!queue)
                return NULL;
@@ -457,6 +483,50 @@ ProcQueueInit(PROC_QUEUE *queue)
 }
 
 
+/*
+ *     Handling cancel request while waiting for lock
+ *
+ */
+static bool lockWaiting = false;
+void
+SetWaitingForLock(bool waiting)
+{
+       if (waiting == lockWaiting)
+               return;
+       lockWaiting = waiting;
+       if (lockWaiting)
+       {
+               /* The lock was already released ? */
+               if (MyProc->links.next == INVALID_OFFSET)
+               {
+                       lockWaiting = false;
+                       return;
+               }
+               if (QueryCancel)                /* cancel request pending */
+               {
+                       if (GetOffWaitqueue(MyProc))
+                       {
+                               lockWaiting = false;
+                               elog(ERROR, "Query cancel requested while waiting lock");
+                       }
+               }
+       }
+}
+void
+LockWaitCancel(void)
+{
+       struct itimerval timeval,
+                               dummy;
+
+       if (!lockWaiting)
+               return;
+       lockWaiting = false;
+       /* Deadlock timer off */
+       MemSet(&timeval, 0, sizeof(struct itimerval));
+       setitimer(ITIMER_REAL, &timeval, &dummy);
+       if (GetOffWaitqueue(MyProc))
+               elog(ERROR, "Query cancel requested while waiting lock");
+}
 
 /*
  * ProcSleep -- put a process to sleep
@@ -566,9 +636,10 @@ ins:;
         * --------------
         */
        MemSet(&timeval, 0, sizeof(struct itimerval));
-       timeval.it_value.tv_sec = \
-               (DeadlockCheckTimer ? DeadlockCheckTimer : DEADLOCK_CHECK_TIMER);
+       timeval.it_value.tv_sec = DeadlockTimeout / 1000;
+       timeval.it_value.tv_usec = (DeadlockTimeout % 1000) * 1000;
 
+       SetWaitingForLock(true);
        do
        {
                MyProc->errType = NO_ERROR;             /* reset flag after deadlock check */
@@ -588,12 +659,14 @@ ins:;
                                                 IpcExclusiveLock);
        } while (MyProc->errType == STATUS_NOT_FOUND);          /* sleep after deadlock
                                                                                                                 * check */
+       lockWaiting = false;
 
        /* ---------------
         * We were awoken before a timeout - now disable the timer
         * ---------------
         */
        timeval.it_value.tv_sec = 0;
+       timeval.it_value.tv_usec = 0;
        if (setitimer(ITIMER_REAL, &timeval, &dummy))
                elog(FATAL, "ProcSleep: Unable to diable timer for process wakeup");
 
@@ -606,7 +679,7 @@ ins:;
 
 rt:;
 
-#ifdef LOCK_MGR_DEBUG
+#ifdef LOCK_DEBUG
        /* Just to get meaningful debug messages from DumpLocks() */
        MyProc->waitLock = (LOCK *) NULL;
 #endif
@@ -654,7 +727,6 @@ ProcLockWakeup(PROC_QUEUE *queue, LOCKMETHOD lockmethod, LOCK *lock)
 {
        PROC       *proc;
        int                     count = 0;
-       int                     trace_flag;
        int                     last_locktype = 0;
        int                     queue_size = queue->size;
 
@@ -714,14 +786,13 @@ ProcLockWakeup(PROC_QUEUE *queue, LOCKMETHOD lockmethod, LOCK *lock)
        else
        {
                /* Something is still blocking us.      May have deadlocked. */
-               trace_flag = (lock->tag.lockmethod == USER_LOCKMETHOD) ? \
-                       TRACE_USERLOCKS : TRACE_LOCKS;
-               TPRINTF(trace_flag,
-                               "ProcLockWakeup: lock(%x) can't wake up any process",
-                               MAKE_OFFSET(lock));
-#ifdef DEADLOCK_DEBUG
-               if (pg_options[trace_flag] >= 2)
+#ifdef LOCK_DEBUG
+               if (lock->tag.lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
+               {
+                       elog(DEBUG, "ProcLockWakeup: lock(%lx) can't wake up any process", MAKE_OFFSET(lock));
+                       if (Debug_deadlocks)
                        DumpAllLocks();
+               }
 #endif
                return STATUS_NOT_FOUND;
        }
@@ -734,7 +805,7 @@ ProcAddLock(SHM_QUEUE *elem)
 }
 
 /* --------------------
- * We only get to this routine if we got SIGALRM after DEADLOCK_CHECK_TIMER
+ * We only get to this routine if we got SIGALRM after DeadlockTimeout
  * while waiting for a lock to be released by some other process.  If we have
  * a real deadlock, we must also indicate that I'm no longer waiting
  * on a lock so that other processes don't try to wake me up and screw
@@ -783,8 +854,9 @@ HandleDeadLock(SIGNAL_ARGS)
                return;
        }
 
-#ifdef DEADLOCK_DEBUG
-       DumpAllLocks();
+#ifdef LOCK_DEBUG
+    if (Debug_deadlocks)
+        DumpAllLocks();
 #endif
 
        MyProc->errType = STATUS_NOT_FOUND;
@@ -801,6 +873,7 @@ HandleDeadLock(SIGNAL_ARGS)
         * ------------------------
         */
        Assert(mywaitlock->waitProcs.size > 0);
+       lockWaiting = false;
        --mywaitlock->waitProcs.size;
        SHMQueueDelete(&(MyProc->links));
        SHMQueueElemInit(&(MyProc->links));