diff options
Diffstat (limited to 'src/backend/storage')
-rw-r--r-- | src/backend/storage/ipc/ipci.c | 16 | ||||
-rw-r--r-- | src/backend/storage/ipc/shmem.c | 121 | ||||
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 219 |
3 files changed, 203 insertions, 153 deletions
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index bfe8d52af30..e878462100e 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.80 2005/12/09 01:22:03 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.81 2006/01/04 21:06:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,10 +57,9 @@ void CreateSharedMemoryAndSemaphores(bool makePrivate, int port) { - PGShmemHeader *seghdr = NULL; - if (!IsUnderPostmaster) { + PGShmemHeader *seghdr; Size size; int numSemas; @@ -104,6 +103,8 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port) */ seghdr = PGSharedMemoryCreate(size, makePrivate, port); + InitShmemAccess(seghdr); + /* * Create semaphores */ @@ -120,18 +121,16 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port) */ #ifdef EXEC_BACKEND Assert(!makePrivate); - Assert(UsedShmemSegAddr != NULL); - seghdr = UsedShmemSegAddr; #else elog(PANIC, "should be attached to shared memory already"); #endif } - /* * Set up shared memory allocation mechanism */ - InitShmemAllocation(seghdr, !IsUnderPostmaster); + if (!IsUnderPostmaster) + InitShmemAllocation(); /* * Now initialize LWLocks, which do shared memory allocation and are @@ -163,7 +162,8 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port) /* * Set up process table */ - InitProcGlobal(); + if (!IsUnderPostmaster) + InitProcGlobal(); CreateSharedProcArray(); /* diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index e6865563b39..21d136d6cf0 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -8,25 +8,26 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.89 2005/12/29 18:08:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.90 2006/01/04 21:06:31 tgl Exp $ * *------------------------------------------------------------------------- */ /* * POSTGRES processes share one or more regions of shared memory. * The shared memory is created by a postmaster and is inherited - * by each backend via fork(). The routines in this file are used for - * allocating and binding to shared memory data structures. + * by each backend via fork() (or, in some ports, via other OS-specific + * methods). The routines in this file are used for allocating and + * binding to shared memory data structures. * * NOTES: * (a) There are three kinds of shared memory data structures * available to POSTGRES: fixed-size structures, queues and hash * tables. Fixed-size structures contain things like global variables - * for a module and should never be allocated after the process + * for a module and should never be allocated after the shared memory * initialization phase. Hash tables have a fixed maximum size, but * their actual size can vary dynamically. When entries are added * to the table, more space is allocated. Queues link data structures - * that have been allocated either as fixed size structures or as hash + * that have been allocated either within fixed-size structures or as hash * buckets. Each shared data structure has a string name to identify * it (assigned in the module that declares it). * @@ -46,7 +47,14 @@ * of shared memory in a lot of different places (and changing * things during development), this is important. * - * (c) memory allocation model: shared memory can never be + * (c) In standard Unix-ish environments, individual backends do not + * need to re-establish their local pointers into shared memory, because + * they inherit correct values of those variables via fork() from the + * postmaster. However, this does not work in the EXEC_BACKEND case. + * In ports using EXEC_BACKEND, new backends have to set up their local + * pointers using the method described in (b) above. + + * (d) memory allocation model: shared memory can never be * freed, once allocated. Each hash table has its own free list, * so hash buckets can be reused when an item is deleted. However, * if one hash table grows very large and then shrinks, its space @@ -75,58 +83,59 @@ static SHMEM_OFFSET ShmemEnd; /* end+1 address of shared memory */ slock_t *ShmemLock; /* spinlock for shared memory and LWLock * allocation */ -NON_EXEC_STATIC slock_t *ShmemIndexLock; /* spinlock for ShmemIndex */ - -NON_EXEC_STATIC void *ShmemIndexAlloc = NULL; /* Memory actually allocated - * for ShmemIndex */ - static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */ /* - * InitShmemAllocation() --- set up shared-memory allocation. + * InitShmemAccess() --- set up basic pointers to shared memory. * * Note: the argument should be declared "PGShmemHeader *seghdr", * but we use void to avoid having to include ipc.h in shmem.h. */ void -InitShmemAllocation(void *seghdr, bool init) +InitShmemAccess(void *seghdr) { PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; - /* Set up basic pointers to shared memory */ ShmemSegHdr = shmhdr; ShmemBase = (SHMEM_OFFSET) shmhdr; ShmemEnd = ShmemBase + shmhdr->totalsize; +} - if (init) - { - /* - * Initialize the spinlocks used by ShmemAlloc/ShmemInitStruct. We - * have to do the space allocation the hard way, since ShmemAlloc - * can't be called yet. - */ - ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); - shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); - Assert(shmhdr->freeoffset <= shmhdr->totalsize); +/* + * InitShmemAllocation() --- set up shared-memory space allocation. + * + * This should be called only in the postmaster or a standalone backend. + */ +void +InitShmemAllocation(void) +{ + PGShmemHeader *shmhdr = ShmemSegHdr; - ShmemIndexLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); - shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); - Assert(shmhdr->freeoffset <= shmhdr->totalsize); + Assert(shmhdr != NULL); - SpinLockInit(ShmemLock); - SpinLockInit(ShmemIndexLock); + /* + * Initialize the spinlock used by ShmemAlloc. We have to do the + * space allocation the hard way, since obviously ShmemAlloc can't + * be called yet. + */ + ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); + shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); + Assert(shmhdr->freeoffset <= shmhdr->totalsize); - /* ShmemIndex can't be set up yet (need LWLocks first) */ - ShmemIndex = (HTAB *) NULL; + SpinLockInit(ShmemLock); - /* - * Initialize ShmemVariableCache for transaction manager. - */ - ShmemVariableCache = (VariableCache) - ShmemAlloc(sizeof(*ShmemVariableCache)); - memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache)); - } + /* ShmemIndex can't be set up yet (need LWLocks first) */ + shmhdr->indexoffset = 0; + ShmemIndex = (HTAB *) NULL; + + /* + * Initialize ShmemVariableCache for transaction manager. + * (This doesn't really belong here, but not worth moving.) + */ + ShmemVariableCache = (VariableCache) + ShmemAlloc(sizeof(*ShmemVariableCache)); + memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache)); } /* @@ -194,7 +203,7 @@ ShmemIsValid(unsigned long addr) } /* - * InitShmemIndex() --- set up shmem index table. + * InitShmemIndex() --- set up or attach to shmem index table. */ void InitShmemIndex(void) @@ -239,15 +248,14 @@ InitShmemIndex(void) result->location = MAKE_OFFSET(ShmemIndex->hctl); result->size = SHMEM_INDEX_SIZE; - } /* now release the lock acquired in ShmemInitStruct */ - SpinLockRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); } /* - * ShmemInitHash -- Create/Attach to and initialize + * ShmemInitHash -- Create and initialize, or attach to, a * shared memory hash table. * * We assume caller is doing some kind of synchronization @@ -290,8 +298,8 @@ ShmemInitHash(const char *name, /* table string name for shmem index */ &found); /* - * shmem index is corrupted. Let someone else give the error message - * since they have more information + * If fail, shmem index is corrupted. Let caller give the error message + * since it has more information */ if (location == NULL) return NULL; @@ -315,8 +323,8 @@ ShmemInitHash(const char *name, /* table string name for shmem index */ * memory. * * This is called during initialization to find or allocate - * a data structure in shared memory. If no other processes - * have created the structure, this routine allocates space + * a data structure in shared memory. If no other process + * has created the structure, this routine allocates space * for it. If it exists already, a pointer to the existing * table is returned. * @@ -334,15 +342,18 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) strncpy(item.key, name, SHMEM_INDEX_KEYSIZE); item.location = BAD_LOCATION; - SpinLockAcquire(ShmemIndexLock); + LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE); if (!ShmemIndex) { + PGShmemHeader *shmemseghdr = ShmemSegHdr; + Assert(strcmp(name, "ShmemIndex") == 0); if (IsUnderPostmaster) { /* Must be initializing a (non-standalone) backend */ - Assert(ShmemIndexAlloc); + Assert(shmemseghdr->indexoffset != 0); + structPtr = (void *) MAKE_PTR(shmemseghdr->indexoffset); *foundPtr = TRUE; } else @@ -354,10 +365,12 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) * Notice that the ShmemIndexLock is held until the shmem index * has been completely initialized. */ + Assert(shmemseghdr->indexoffset == 0); + structPtr = ShmemAlloc(size); + shmemseghdr->indexoffset = MAKE_OFFSET(structPtr); *foundPtr = FALSE; - ShmemIndexAlloc = ShmemAlloc(size); } - return ShmemIndexAlloc; + return structPtr; } /* look it up in the shmem index */ @@ -366,7 +379,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) if (!result) { - SpinLockRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); @@ -381,7 +394,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) */ if (result->size != size) { - SpinLockRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); elog(WARNING, "ShmemIndex entry size is wrong"); /* let caller print its message too */ @@ -398,7 +411,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) /* out of memory */ Assert(ShmemIndex); hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, NULL); - SpinLockRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); ereport(WARNING, (errcode(ERRCODE_OUT_OF_MEMORY), @@ -411,7 +424,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) } Assert(ShmemIsValid((unsigned long) structPtr)); - SpinLockRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); return structPtr; } diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 34d80bfceea..605f8b5e68b 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.170 2005/12/11 21:02:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.171 2006/01/04 21:06:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,8 +61,8 @@ PGPROC *MyProc = NULL; NON_EXEC_STATIC slock_t *ProcStructLock = NULL; /* Pointers to shared-memory structures */ -static PROC_HDR *ProcGlobal = NULL; -static PGPROC *DummyProcs = NULL; +NON_EXEC_STATIC PROC_HDR *ProcGlobal = NULL; +NON_EXEC_STATIC PGPROC *DummyProcs = NULL; /* If we are waiting for a lock, this points to the associated LOCALLOCK */ static LOCALLOCK *lockAwaited = NULL; @@ -76,6 +76,7 @@ volatile bool cancel_from_timeout = false; static struct timeval statement_fin_time; +static void RemoveProcFromArray(int code, Datum arg); static void ProcKill(int code, Datum arg); static void DummyProcKill(int code, Datum arg); static bool CheckStatementTimeout(void); @@ -113,7 +114,8 @@ ProcGlobalSemas(void) /* * InitProcGlobal - - * Initialize the global process table during postmaster startup. + * Initialize the global process table during postmaster or standalone + * backend startup. * * We also create all the per-process semaphores we will need to support * the requested number of backends. We used to allocate semaphores @@ -129,69 +131,65 @@ ProcGlobalSemas(void) * Another reason for creating semaphores here is that the semaphore * implementation typically requires us to create semaphores in the * postmaster, not in backends. + * + * Note: this is NOT called by individual backends under a postmaster, + * not even in the EXEC_BACKEND case. The ProcGlobal and DummyProcs + * pointers must be propagated specially for EXEC_BACKEND operation. */ void InitProcGlobal(void) { - bool foundProcGlobal, - foundDummy; + PGPROC *procs; + int i; + bool found; - /* Create or attach to the ProcGlobal shared structure */ + /* Create the ProcGlobal shared structure */ ProcGlobal = (PROC_HDR *) - ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &foundProcGlobal); + ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found); + Assert(!found); /* - * Create or attach to the PGPROC structures for dummy (bgwriter) - * processes, too. These do not get linked into the freeProcs list. + * Create the PGPROC structures for dummy (bgwriter) processes, too. + * These do not get linked into the freeProcs list. */ DummyProcs = (PGPROC *) ShmemInitStruct("DummyProcs", NUM_DUMMY_PROCS * sizeof(PGPROC), - &foundDummy); - - if (foundProcGlobal || foundDummy) - { - /* both should be present or neither */ - Assert(foundProcGlobal && foundDummy); - } - else - { - /* - * We're the first - initialize. - */ - PGPROC *procs; - int i; - - ProcGlobal->freeProcs = INVALID_OFFSET; + &found); + Assert(!found); - ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY; + /* + * Initialize the data structures. + */ + ProcGlobal->freeProcs = INVALID_OFFSET; - /* - * Pre-create the PGPROC structures and create a semaphore for each. - */ - procs = (PGPROC *) ShmemAlloc(MaxBackends * sizeof(PGPROC)); - if (!procs) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of shared memory"))); - MemSet(procs, 0, MaxBackends * sizeof(PGPROC)); - for (i = 0; i < MaxBackends; i++) - { - PGSemaphoreCreate(&(procs[i].sem)); - procs[i].links.next = ProcGlobal->freeProcs; - ProcGlobal->freeProcs = MAKE_OFFSET(&procs[i]); - } + ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY; - MemSet(DummyProcs, 0, NUM_DUMMY_PROCS * sizeof(PGPROC)); - for (i = 0; i < NUM_DUMMY_PROCS; i++) - { - DummyProcs[i].pid = 0; /* marks dummy proc as not in use */ - PGSemaphoreCreate(&(DummyProcs[i].sem)); - } + /* + * Pre-create the PGPROC structures and create a semaphore for each. + */ + procs = (PGPROC *) ShmemAlloc(MaxBackends * sizeof(PGPROC)); + if (!procs) + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of shared memory"))); + MemSet(procs, 0, MaxBackends * sizeof(PGPROC)); + for (i = 0; i < MaxBackends; i++) + { + PGSemaphoreCreate(&(procs[i].sem)); + procs[i].links.next = ProcGlobal->freeProcs; + ProcGlobal->freeProcs = MAKE_OFFSET(&procs[i]); + } - /* Create ProcStructLock spinlock, too */ - ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t)); - SpinLockInit(ProcStructLock); + MemSet(DummyProcs, 0, NUM_DUMMY_PROCS * sizeof(PGPROC)); + for (i = 0; i < NUM_DUMMY_PROCS; i++) + { + DummyProcs[i].pid = 0; /* marks dummy proc as not in use */ + PGSemaphoreCreate(&(DummyProcs[i].sem)); } + + /* Create ProcStructLock spinlock, too */ + ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t)); + SpinLockInit(ProcStructLock); } /* @@ -206,8 +204,8 @@ InitProcess(void) int i; /* - * ProcGlobal should be set by a previous call to InitProcGlobal (if we - * are a backend, we inherit this by fork() from the postmaster). + * ProcGlobal should be set up already (if we are a backend, we inherit + * this by fork() or EXEC_BACKEND mechanism from the postmaster). */ if (procglobal == NULL) elog(PANIC, "proc header uninitialized"); @@ -256,8 +254,8 @@ InitProcess(void) MyProc->xid = InvalidTransactionId; MyProc->xmin = InvalidTransactionId; MyProc->pid = MyProcPid; - MyProc->databaseId = MyDatabaseId; - /* Will be set properly after the session role id is determined */ + /* databaseId and roleId will be filled in later */ + MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->lwWaiting = false; MyProc->lwExclusive = false; @@ -268,9 +266,10 @@ InitProcess(void) SHMQueueInit(&(MyProc->myProcLocks[i])); /* - * Add our PGPROC to the PGPROC array in shared memory. + * We might be reusing a semaphore that belonged to a failed process. So + * be careful and reinitialize its value here. */ - ProcArrayAdd(MyProc); + PGSemaphoreReset(&MyProc->sem); /* * Arrange to clean up at backend exit. @@ -278,12 +277,6 @@ InitProcess(void) on_shmem_exit(ProcKill, 0); /* - * We might be reusing a semaphore that belonged to a failed process. So - * be careful and reinitialize its value here. - */ - PGSemaphoreReset(&MyProc->sem); - - /* * Now that we have a PGPROC, we could try to acquire locks, so initialize * the deadlock checker. */ @@ -291,25 +284,58 @@ InitProcess(void) } /* + * InitProcessPhase2 -- make MyProc visible in the shared ProcArray. + * + * This is separate from InitProcess because we can't acquire LWLocks until + * we've created a PGPROC, but in the EXEC_BACKEND case there is a good deal + * of stuff to be done before this step that will require LWLock access. + */ +void +InitProcessPhase2(void) +{ + Assert(MyProc != NULL); + + /* + * We should now know what database we're in, so advertise that. (We + * need not do any locking here, since no other backend can yet see + * our PGPROC.) + */ + Assert(OidIsValid(MyDatabaseId)); + MyProc->databaseId = MyDatabaseId; + + /* + * Add our PGPROC to the PGPROC array in shared memory. + */ + ProcArrayAdd(MyProc); + + /* + * Arrange to clean that up at backend exit. + */ + on_shmem_exit(RemoveProcFromArray, 0); +} + +/* * InitDummyProcess -- create a dummy per-process data structure * * This is called by bgwriter and similar processes so that they will have a * MyProc value that's real enough to let them wait for LWLocks. The PGPROC - * and sema that are assigned are the extra ones created during + * and sema that are assigned are one of the extra ones created during * InitProcGlobal. * * Dummy processes are presently not expected to wait for real (lockmgr) - * locks, nor to participate in sinval messaging. + * locks, so we need not set up the deadlock checker. They are never added + * to the ProcArray or the sinval messaging mechanism, either. */ void -InitDummyProcess(int proctype) +InitDummyProcess(void) { PGPROC *dummyproc; + int proctype; int i; /* - * ProcGlobal should be set by a previous call to InitProcGlobal (we - * inherit this by fork() from the postmaster). + * ProcGlobal should be set up already (if we are a backend, we inherit + * this by fork() or EXEC_BACKEND mechanism from the postmaster). */ if (ProcGlobal == NULL || DummyProcs == NULL) elog(PANIC, "proc header uninitialized"); @@ -317,11 +343,9 @@ InitDummyProcess(int proctype) if (MyProc != NULL) elog(ERROR, "you already exist"); - Assert(proctype >= 0 && proctype < NUM_DUMMY_PROCS); - /* - * Just for paranoia's sake, we use the ProcStructLock to protect - * assignment and releasing of DummyProcs entries. + * We use the ProcStructLock to protect assignment and releasing of + * DummyProcs entries. * * While we are holding the ProcStructLock, also copy the current shared * estimate of spins_per_delay to local storage. @@ -330,32 +354,38 @@ InitDummyProcess(int proctype) set_spins_per_delay(ProcGlobal->spins_per_delay); - dummyproc = &DummyProcs[proctype]; - /* - * dummyproc should not presently be in use by anyone else + * Find a free dummyproc ... *big* trouble if there isn't one ... */ - if (dummyproc->pid != 0) + for (proctype = 0; proctype < NUM_DUMMY_PROCS; proctype++) + { + dummyproc = &DummyProcs[proctype]; + if (dummyproc->pid == 0) + break; + } + if (proctype >= NUM_DUMMY_PROCS) { SpinLockRelease(ProcStructLock); - elog(FATAL, "DummyProc[%d] is in use by PID %d", - proctype, dummyproc->pid); + elog(FATAL, "all DummyProcs are in use"); } - MyProc = dummyproc; - MyProc->pid = MyProcPid; /* marks dummy proc as in use by me */ + /* Mark dummy proc as in use by me */ + /* use volatile pointer to prevent code rearrangement */ + ((volatile PGPROC *) dummyproc)->pid = MyProcPid; + + MyProc = dummyproc; SpinLockRelease(ProcStructLock); /* - * Initialize all fields of MyProc, except MyProc->sem which was set up by - * InitProcGlobal. + * Initialize all fields of MyProc, except for the semaphore which was + * prepared for us by InitProcGlobal. */ SHMQueueElemInit(&(MyProc->links)); MyProc->waitStatus = STATUS_OK; MyProc->xid = InvalidTransactionId; MyProc->xmin = InvalidTransactionId; - MyProc->databaseId = MyDatabaseId; + MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->lwWaiting = false; MyProc->lwExclusive = false; @@ -366,15 +396,15 @@ InitDummyProcess(int proctype) SHMQueueInit(&(MyProc->myProcLocks[i])); /* - * Arrange to clean up at process exit. - */ - on_shmem_exit(DummyProcKill, Int32GetDatum(proctype)); - - /* * We might be reusing a semaphore that belonged to a failed process. So * be careful and reinitialize its value here. */ PGSemaphoreReset(&MyProc->sem); + + /* + * Arrange to clean up at process exit. + */ + on_shmem_exit(DummyProcKill, Int32GetDatum(proctype)); } /* @@ -502,6 +532,16 @@ ProcReleaseLocks(bool isCommit) /* + * RemoveProcFromArray() -- Remove this process from the shared ProcArray. + */ +static void +RemoveProcFromArray(int code, Datum arg) +{ + Assert(MyProc != NULL); + ProcArrayRemove(MyProc); +} + +/* * ProcKill() -- Destroy the per-proc data structure for * this process. Release any of its held LW locks. */ @@ -520,9 +560,6 @@ ProcKill(int code, Datum arg) */ LWLockReleaseAll(); - /* Remove our PGPROC from the PGPROC array in shared memory */ - ProcArrayRemove(MyProc); - SpinLockAcquire(ProcStructLock); /* Return PGPROC structure (and semaphore) to freelist */ |