*** a/src/backend/access/transam/twophase.c --- b/src/backend/access/transam/twophase.c *************** *** 122,128 **** typedef struct GlobalTransactionData typedef struct TwoPhaseStateData { /* Head of linked list of free GlobalTransactionData structs */ ! SHMEM_OFFSET freeGXacts; /* Number of valid prepXacts entries. */ int numPrepXacts; --- 122,128 ---- typedef struct TwoPhaseStateData { /* Head of linked list of free GlobalTransactionData structs */ ! void * freeGXacts; /* Number of valid prepXacts entries. */ int numPrepXacts; *************** *** 184,190 **** TwoPhaseShmemInit(void) int i; Assert(!found); ! TwoPhaseState->freeGXacts = INVALID_OFFSET; TwoPhaseState->numPrepXacts = 0; /* --- 184,190 ---- int i; Assert(!found); ! TwoPhaseState->freeGXacts = NULL; TwoPhaseState->numPrepXacts = 0; /* *************** *** 197,203 **** TwoPhaseShmemInit(void) for (i = 0; i < max_prepared_xacts; i++) { gxacts[i].proc.links.next = TwoPhaseState->freeGXacts; ! TwoPhaseState->freeGXacts = MAKE_OFFSET(&gxacts[i]); } } else --- 197,203 ---- for (i = 0; i < max_prepared_xacts; i++) { gxacts[i].proc.links.next = TwoPhaseState->freeGXacts; ! TwoPhaseState->freeGXacts = &gxacts[i]; } } else *************** *** 243,249 **** MarkAsPreparing(TransactionId xid, const char *gid, TwoPhaseState->prepXacts[i] = TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts]; /* and put it back in the freelist */ gxact->proc.links.next = TwoPhaseState->freeGXacts; ! TwoPhaseState->freeGXacts = MAKE_OFFSET(gxact); /* Back up index count too, so we don't miss scanning one */ i--; } --- 243,249 ---- TwoPhaseState->prepXacts[i] = TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts]; /* and put it back in the freelist */ gxact->proc.links.next = TwoPhaseState->freeGXacts; ! TwoPhaseState->freeGXacts = gxact; /* Back up index count too, so we don't miss scanning one */ i--; } *************** *** 263,275 **** MarkAsPreparing(TransactionId xid, const char *gid, } /* Get a free gxact from the freelist */ ! if (TwoPhaseState->freeGXacts == INVALID_OFFSET) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("maximum number of prepared transactions reached"), errhint("Increase max_prepared_transactions (currently %d).", max_prepared_xacts))); ! gxact = (GlobalTransaction) MAKE_PTR(TwoPhaseState->freeGXacts); TwoPhaseState->freeGXacts = gxact->proc.links.next; /* Initialize it */ --- 263,275 ---- } /* Get a free gxact from the freelist */ ! if (TwoPhaseState->freeGXacts == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("maximum number of prepared transactions reached"), errhint("Increase max_prepared_transactions (currently %d).", max_prepared_xacts))); ! gxact = (GlobalTransaction)TwoPhaseState->freeGXacts; TwoPhaseState->freeGXacts = gxact->proc.links.next; /* Initialize it */ *************** *** 452,458 **** RemoveGXact(GlobalTransaction gxact) /* and put it back in the freelist */ gxact->proc.links.next = TwoPhaseState->freeGXacts; ! TwoPhaseState->freeGXacts = MAKE_OFFSET(gxact); LWLockRelease(TwoPhaseStateLock); --- 452,458 ---- /* and put it back in the freelist */ gxact->proc.links.next = TwoPhaseState->freeGXacts; ! TwoPhaseState->freeGXacts = gxact; LWLockRelease(TwoPhaseStateLock); *** a/src/backend/postmaster/autovacuum.c --- b/src/backend/postmaster/autovacuum.c *************** *** 244,252 **** typedef struct { sig_atomic_t av_signal[AutoVacNumSignals]; pid_t av_launcherpid; ! SHMEM_OFFSET av_freeWorkers; SHM_QUEUE av_runningWorkers; ! SHMEM_OFFSET av_startingWorker; } AutoVacuumShmemStruct; static AutoVacuumShmemStruct *AutoVacuumShmem; --- 244,252 ---- { sig_atomic_t av_signal[AutoVacNumSignals]; pid_t av_launcherpid; ! WorkerInfo av_freeWorkers; SHM_QUEUE av_runningWorkers; ! WorkerInfo av_startingWorker; } AutoVacuumShmemStruct; static AutoVacuumShmemStruct *AutoVacuumShmem; *************** *** 557,563 **** AutoVacLauncherMain(int argc, char *argv[]) exit(1); launcher_determine_sleep(AutoVacuumShmem->av_freeWorkers != ! INVALID_OFFSET, false, &nap); /* * Sleep for a while according to schedule. --- 557,563 ---- exit(1); launcher_determine_sleep(AutoVacuumShmem->av_freeWorkers != ! NULL, false, &nap); /* * Sleep for a while according to schedule. *************** *** 662,674 **** AutoVacLauncherMain(int argc, char *argv[]) current_time = GetCurrentTimestamp(); LWLockAcquire(AutovacuumLock, LW_SHARED); ! can_launch = (AutoVacuumShmem->av_freeWorkers != INVALID_OFFSET); ! if (AutoVacuumShmem->av_startingWorker != INVALID_OFFSET) { int waittime; ! WorkerInfo worker = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker); /* * We can't launch another worker when another one is still --- 662,674 ---- current_time = GetCurrentTimestamp(); LWLockAcquire(AutovacuumLock, LW_SHARED); ! can_launch = (AutoVacuumShmem->av_freeWorkers != NULL); ! if (AutoVacuumShmem->av_startingWorker != NULL) { int waittime; ! WorkerInfo worker = AutoVacuumShmem->av_startingWorker; /* * We can't launch another worker when another one is still *************** *** 698,713 **** AutoVacLauncherMain(int argc, char *argv[]) * we assume it's the same one we saw above (so we don't * recheck the launch time). */ ! if (AutoVacuumShmem->av_startingWorker != INVALID_OFFSET) { ! worker = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker); worker->wi_dboid = InvalidOid; worker->wi_tableoid = InvalidOid; worker->wi_proc = NULL; worker->wi_launchtime = 0; worker->wi_links.next = AutoVacuumShmem->av_freeWorkers; ! AutoVacuumShmem->av_freeWorkers = MAKE_OFFSET(worker); ! AutoVacuumShmem->av_startingWorker = INVALID_OFFSET; elog(WARNING, "worker took too long to start; cancelled"); } } --- 698,713 ---- * we assume it's the same one we saw above (so we don't * recheck the launch time). */ ! if (AutoVacuumShmem->av_startingWorker != NULL) { ! worker = AutoVacuumShmem->av_startingWorker; worker->wi_dboid = InvalidOid; worker->wi_tableoid = InvalidOid; worker->wi_proc = NULL; worker->wi_launchtime = 0; worker->wi_links.next = AutoVacuumShmem->av_freeWorkers; ! AutoVacuumShmem->av_freeWorkers = worker; ! AutoVacuumShmem->av_startingWorker = NULL; elog(WARNING, "worker took too long to start; cancelled"); } } *************** *** 1061,1067 **** do_start_worker(void) /* return quickly when there are no free workers */ LWLockAcquire(AutovacuumLock, LW_SHARED); ! if (AutoVacuumShmem->av_freeWorkers == INVALID_OFFSET) { LWLockRelease(AutovacuumLock); return InvalidOid; --- 1061,1067 ---- /* return quickly when there are no free workers */ LWLockAcquire(AutovacuumLock, LW_SHARED); ! if (AutoVacuumShmem->av_freeWorkers == NULL) { LWLockRelease(AutovacuumLock); return InvalidOid; *************** *** 1192,1198 **** do_start_worker(void) if (avdb != NULL) { WorkerInfo worker; - SHMEM_OFFSET sworker; LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE); --- 1192,1197 ---- *************** *** 1201,1218 **** do_start_worker(void) * really should be a free slot -- complain very loudly if there * isn't. */ ! sworker = AutoVacuumShmem->av_freeWorkers; ! if (sworker == INVALID_OFFSET) elog(FATAL, "no free worker found"); - worker = (WorkerInfo) MAKE_PTR(sworker); AutoVacuumShmem->av_freeWorkers = worker->wi_links.next; worker->wi_dboid = avdb->adw_datid; worker->wi_proc = NULL; worker->wi_launchtime = GetCurrentTimestamp(); ! AutoVacuumShmem->av_startingWorker = sworker; LWLockRelease(AutovacuumLock); --- 1200,1216 ---- * really should be a free slot -- complain very loudly if there * isn't. */ ! worker = AutoVacuumShmem->av_freeWorkers; ! if (worker == NULL) elog(FATAL, "no free worker found"); AutoVacuumShmem->av_freeWorkers = worker->wi_links.next; worker->wi_dboid = avdb->adw_datid; worker->wi_proc = NULL; worker->wi_launchtime = GetCurrentTimestamp(); ! AutoVacuumShmem->av_startingWorker = worker; LWLockRelease(AutovacuumLock); *************** *** 1549,1557 **** AutoVacWorkerMain(int argc, char *argv[]) * launcher might have decided to remove it from the queue and start * again. */ ! if (AutoVacuumShmem->av_startingWorker != INVALID_OFFSET) { ! MyWorkerInfo = (WorkerInfo) MAKE_PTR(AutoVacuumShmem->av_startingWorker); dbid = MyWorkerInfo->wi_dboid; MyWorkerInfo->wi_proc = MyProc; --- 1547,1555 ---- * launcher might have decided to remove it from the queue and start * again. */ ! if (AutoVacuumShmem->av_startingWorker != NULL) { ! MyWorkerInfo = AutoVacuumShmem->av_startingWorker; dbid = MyWorkerInfo->wi_dboid; MyWorkerInfo->wi_proc = MyProc; *************** *** 1563,1569 **** AutoVacWorkerMain(int argc, char *argv[]) * remove from the "starting" pointer, so that the launcher can start * a new worker if required */ ! AutoVacuumShmem->av_startingWorker = INVALID_OFFSET; LWLockRelease(AutovacuumLock); on_shmem_exit(FreeWorkerInfo, 0); --- 1561,1567 ---- * remove from the "starting" pointer, so that the launcher can start * a new worker if required */ ! AutoVacuumShmem->av_startingWorker = NULL; LWLockRelease(AutovacuumLock); on_shmem_exit(FreeWorkerInfo, 0); *************** *** 1656,1662 **** FreeWorkerInfo(int code, Datum arg) MyWorkerInfo->wi_cost_delay = 0; MyWorkerInfo->wi_cost_limit = 0; MyWorkerInfo->wi_cost_limit_base = 0; ! AutoVacuumShmem->av_freeWorkers = MAKE_OFFSET(MyWorkerInfo); /* not mine anymore */ MyWorkerInfo = NULL; --- 1654,1660 ---- MyWorkerInfo->wi_cost_delay = 0; MyWorkerInfo->wi_cost_limit = 0; MyWorkerInfo->wi_cost_limit_base = 0; ! AutoVacuumShmem->av_freeWorkers = MyWorkerInfo; /* not mine anymore */ MyWorkerInfo = NULL; *************** *** 2793,2801 **** AutoVacuumShmemInit(void) Assert(!found); AutoVacuumShmem->av_launcherpid = 0; ! AutoVacuumShmem->av_freeWorkers = INVALID_OFFSET; SHMQueueInit(&AutoVacuumShmem->av_runningWorkers); ! AutoVacuumShmem->av_startingWorker = INVALID_OFFSET; worker = (WorkerInfo) ((char *) AutoVacuumShmem + MAXALIGN(sizeof(AutoVacuumShmemStruct))); --- 2791,2799 ---- Assert(!found); AutoVacuumShmem->av_launcherpid = 0; ! AutoVacuumShmem->av_freeWorkers = NULL; SHMQueueInit(&AutoVacuumShmem->av_runningWorkers); ! AutoVacuumShmem->av_startingWorker = NULL; worker = (WorkerInfo) ((char *) AutoVacuumShmem + MAXALIGN(sizeof(AutoVacuumShmemStruct))); *************** *** 2804,2810 **** AutoVacuumShmemInit(void) for (i = 0; i < autovacuum_max_workers; i++) { worker[i].wi_links.next = AutoVacuumShmem->av_freeWorkers; ! AutoVacuumShmem->av_freeWorkers = MAKE_OFFSET(&worker[i]); } } else --- 2802,2808 ---- for (i = 0; i < autovacuum_max_workers; i++) { worker[i].wi_links.next = AutoVacuumShmem->av_freeWorkers; ! AutoVacuumShmem->av_freeWorkers = &worker[i]; } } else *** a/src/backend/storage/ipc/shmem.c --- b/src/backend/storage/ipc/shmem.c *************** *** 77,85 **** static PGShmemHeader *ShmemSegHdr; /* shared mem segment header */ ! SHMEM_OFFSET ShmemBase; /* start address of shared memory */ ! static SHMEM_OFFSET ShmemEnd; /* end+1 address of shared memory */ slock_t *ShmemLock; /* spinlock for shared memory and LWLock * allocation */ --- 77,85 ---- static PGShmemHeader *ShmemSegHdr; /* shared mem segment header */ ! static void *ShmemBase; /* start address of shared memory */ ! static void *ShmemEnd; /* end+1 address of shared memory */ slock_t *ShmemLock; /* spinlock for shared memory and LWLock * allocation */ *************** *** 99,106 **** InitShmemAccess(void *seghdr) PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; ShmemSegHdr = shmhdr; ! ShmemBase = (SHMEM_OFFSET) shmhdr; ! ShmemEnd = ShmemBase + shmhdr->totalsize; } /* --- 99,106 ---- PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; ShmemSegHdr = shmhdr; ! ShmemBase = shmhdr; ! ShmemEnd = (char *)ShmemBase + shmhdr->totalsize; } /* *************** *** 127,133 **** InitShmemAllocation(void) SpinLockInit(ShmemLock); /* ShmemIndex can't be set up yet (need LWLocks first) */ ! shmhdr->indexoffset = 0; ShmemIndex = (HTAB *) NULL; /* --- 127,133 ---- SpinLockInit(ShmemLock); /* ShmemIndex can't be set up yet (need LWLocks first) */ ! shmhdr->index = NULL; ShmemIndex = (HTAB *) NULL; /* *************** *** 176,182 **** ShmemAlloc(Size size) newFree = newStart + size; if (newFree <= shmemseghdr->totalsize) { ! newSpace = (void *) MAKE_PTR(newStart); shmemseghdr->freeoffset = newFree; } else --- 176,182 ---- newFree = newStart + size; if (newFree <= shmemseghdr->totalsize) { ! newSpace = (void *) ((char *)ShmemBase + newStart); shmemseghdr->freeoffset = newFree; } else *************** *** 198,204 **** ShmemAlloc(Size size) * Returns TRUE if the pointer is valid. */ bool ! ShmemIsValid(unsigned long addr) { return (addr < ShmemEnd) && (addr >= ShmemBase); } --- 198,204 ---- * Returns TRUE if the pointer is valid. */ bool ! ShmemIsValid(void *addr) { return (addr < ShmemEnd) && (addr >= ShmemBase); } *************** *** 324,331 **** ShmemInitStruct(const char *name, Size size, bool *foundPtr) if (IsUnderPostmaster) { /* Must be initializing a (non-standalone) backend */ ! Assert(shmemseghdr->indexoffset != 0); ! structPtr = (void *) MAKE_PTR(shmemseghdr->indexoffset); *foundPtr = TRUE; } else --- 324,331 ---- if (IsUnderPostmaster) { /* Must be initializing a (non-standalone) backend */ ! Assert(shmemseghdr->index != NULL); ! structPtr = shmemseghdr->index; *foundPtr = TRUE; } else *************** *** 338,346 **** ShmemInitStruct(const char *name, Size size, bool *foundPtr) * index has been initialized. This should be OK because no other * process can be accessing shared memory yet. */ ! Assert(shmemseghdr->indexoffset == 0); structPtr = ShmemAlloc(size); ! shmemseghdr->indexoffset = MAKE_OFFSET(structPtr); *foundPtr = FALSE; } LWLockRelease(ShmemIndexLock); --- 338,346 ---- * index has been initialized. This should be OK because no other * process can be accessing shared memory yet. */ ! Assert(shmemseghdr->index == NULL); structPtr = ShmemAlloc(size); ! shmemseghdr->index = structPtr; *foundPtr = FALSE; } LWLockRelease(ShmemIndexLock); *************** *** 374,380 **** ShmemInitStruct(const char *name, Size size, bool *foundPtr) /* let caller print its message too */ return NULL; } ! structPtr = (void *) MAKE_PTR(result->location); } else { --- 374,380 ---- /* let caller print its message too */ return NULL; } ! structPtr = result->location; } else { *************** *** 395,403 **** ShmemInitStruct(const char *name, Size size, bool *foundPtr) return NULL; } result->size = size; ! result->location = MAKE_OFFSET(structPtr); } ! Assert(ShmemIsValid((unsigned long) structPtr)); LWLockRelease(ShmemIndexLock); return structPtr; --- 395,403 ---- return NULL; } result->size = size; ! result->location = structPtr; } ! Assert(ShmemIsValid(structPtr)); LWLockRelease(ShmemIndexLock); return structPtr; *** a/src/backend/storage/ipc/shmqueue.c --- b/src/backend/storage/ipc/shmqueue.c *************** *** 41,48 **** static void dumpQ(SHM_QUEUE *q, char *s); void SHMQueueInit(SHM_QUEUE *queue) { ! Assert(SHM_PTR_VALID(queue)); ! (queue)->prev = (queue)->next = MAKE_OFFSET(queue); } /* --- 41,48 ---- void SHMQueueInit(SHM_QUEUE *queue) { ! Assert(ShmemIsValid(queue)); ! (queue)->prev = (queue)->next = (queue); } /* *************** *** 53,60 **** SHMQueueInit(SHM_QUEUE *queue) bool SHMQueueIsDetached(SHM_QUEUE *queue) { ! Assert(SHM_PTR_VALID(queue)); ! return (queue)->prev == INVALID_OFFSET; } #endif --- 53,60 ---- bool SHMQueueIsDetached(SHM_QUEUE *queue) { ! Assert(ShmemIsValid(queue)); ! return (queue)->prev == NULL; } #endif *************** *** 64,71 **** SHMQueueIsDetached(SHM_QUEUE *queue) void SHMQueueElemInit(SHM_QUEUE *queue) { ! Assert(SHM_PTR_VALID(queue)); ! (queue)->prev = (queue)->next = INVALID_OFFSET; } /* --- 64,71 ---- void SHMQueueElemInit(SHM_QUEUE *queue) { ! Assert(ShmemIsValid(queue)); ! (queue)->prev = (queue)->next = NULL; } /* *************** *** 75,86 **** SHMQueueElemInit(SHM_QUEUE *queue) void SHMQueueDelete(SHM_QUEUE *queue) { ! SHM_QUEUE *nextElem = (SHM_QUEUE *) MAKE_PTR((queue)->next); ! SHM_QUEUE *prevElem = (SHM_QUEUE *) MAKE_PTR((queue)->prev); ! Assert(SHM_PTR_VALID(queue)); ! Assert(SHM_PTR_VALID(nextElem)); ! Assert(SHM_PTR_VALID(prevElem)); #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueDelete: begin"); --- 75,86 ---- void SHMQueueDelete(SHM_QUEUE *queue) { ! SHM_QUEUE *nextElem = (SHM_QUEUE *) (queue)->next; ! SHM_QUEUE *prevElem = (SHM_QUEUE *) (queue)->prev; ! Assert(ShmemIsValid(queue)); ! Assert(ShmemIsValid(nextElem)); ! Assert(ShmemIsValid(prevElem)); #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueDelete: begin"); *************** *** 89,95 **** SHMQueueDelete(SHM_QUEUE *queue) prevElem->next = (queue)->next; nextElem->prev = (queue)->prev; ! (queue)->prev = (queue)->next = INVALID_OFFSET; } /* --- 89,95 ---- prevElem->next = (queue)->next; nextElem->prev = (queue)->prev; ! (queue)->prev = (queue)->next = NULL; } /* *************** *** 100,119 **** SHMQueueDelete(SHM_QUEUE *queue) void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem) { ! SHM_QUEUE *prevPtr = (SHM_QUEUE *) MAKE_PTR((queue)->prev); ! SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem); ! Assert(SHM_PTR_VALID(queue)); ! Assert(SHM_PTR_VALID(elem)); #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueInsertBefore: begin"); #endif (elem)->next = prevPtr->next; ! (elem)->prev = queue->prev; ! (queue)->prev = elemOffset; ! prevPtr->next = elemOffset; #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueInsertBefore: end"); --- 100,118 ---- void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem) { ! SHM_QUEUE *prevPtr = (SHM_QUEUE *) (queue)->prev; ! Assert(ShmemIsValid(queue)); ! Assert(ShmemIsValid(elem)); #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueInsertBefore: begin"); #endif (elem)->next = prevPtr->next; ! (elem)->prev = (queue)->prev; ! (queue)->prev = (elem); ! prevPtr->next = (elem); #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueInsertBefore: end"); *************** *** 129,148 **** SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem) void SHMQueueInsertAfter(SHM_QUEUE *queue, SHM_QUEUE *elem) { ! SHM_QUEUE *nextPtr = (SHM_QUEUE *) MAKE_PTR((queue)->next); ! SHMEM_OFFSET elemOffset = MAKE_OFFSET(elem); ! Assert(SHM_PTR_VALID(queue)); ! Assert(SHM_PTR_VALID(elem)); #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueInsertAfter: begin"); #endif (elem)->prev = nextPtr->prev; ! (elem)->next = queue->next; ! (queue)->next = elemOffset; ! nextPtr->prev = elemOffset; #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueInsertAfter: end"); --- 128,146 ---- void SHMQueueInsertAfter(SHM_QUEUE *queue, SHM_QUEUE *elem) { ! SHM_QUEUE *nextPtr = (SHM_QUEUE *) (queue)->next; ! Assert(ShmemIsValid(queue)); ! Assert(ShmemIsValid(elem)); #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueInsertAfter: begin"); #endif (elem)->prev = nextPtr->prev; ! (elem)->next = (queue)->next; ! (queue)->next = (elem); ! nextPtr->prev = (elem); #ifdef SHMQUEUE_DEBUG dumpQ(queue, "in SHMQueueInsertAfter: end"); *************** *** 176,184 **** SHMQueueInsertAfter(SHM_QUEUE *queue, SHM_QUEUE *elem) Pointer SHMQueueNext(SHM_QUEUE *queue, SHM_QUEUE *curElem, Size linkOffset) { ! SHM_QUEUE *elemPtr = (SHM_QUEUE *) MAKE_PTR((curElem)->next); ! Assert(SHM_PTR_VALID(curElem)); if (elemPtr == queue) /* back to the queue head? */ return NULL; --- 174,182 ---- Pointer SHMQueueNext(SHM_QUEUE *queue, SHM_QUEUE *curElem, Size linkOffset) { ! SHM_QUEUE *elemPtr = (SHM_QUEUE *) (curElem)->next; ! Assert(ShmemIsValid(curElem)); if (elemPtr == queue) /* back to the queue head? */ return NULL; *************** *** 192,202 **** SHMQueueNext(SHM_QUEUE *queue, SHM_QUEUE *curElem, Size linkOffset) bool SHMQueueEmpty(SHM_QUEUE *queue) { ! Assert(SHM_PTR_VALID(queue)); ! if (queue->prev == MAKE_OFFSET(queue)) { ! Assert(queue->next = MAKE_OFFSET(queue)); return TRUE; } return FALSE; --- 190,200 ---- bool SHMQueueEmpty(SHM_QUEUE *queue) { ! Assert(ShmemIsValid(queue)); ! if (queue->prev == queue) { ! Assert(queue->next = queue); return TRUE; } return FALSE; *************** *** 212,225 **** dumpQ(SHM_QUEUE *q, char *s) SHM_QUEUE *start = q; int count = 0; ! snprintf(buf, sizeof(buf), "q prevs: %lx", MAKE_OFFSET(q)); ! q = (SHM_QUEUE *) MAKE_PTR(q->prev); while (q != start) { ! snprintf(elem, sizeof(elem), "--->%lx", MAKE_OFFSET(q)); strcat(buf, elem); ! q = (SHM_QUEUE *) MAKE_PTR(q->prev); ! if (q->prev == MAKE_OFFSET(q)) break; if (count++ > 40) { --- 210,223 ---- SHM_QUEUE *start = q; int count = 0; ! snprintf(buf, sizeof(buf), "q prevs: %lx", q); ! q = (SHM_QUEUE *) q->prev; while (q != start) { ! snprintf(elem, sizeof(elem), "--->%lx", q); strcat(buf, elem); ! q = (SHM_QUEUE *) q->prev; ! if (q->prev == q) break; if (count++ > 40) { *************** *** 227,245 **** dumpQ(SHM_QUEUE *q, char *s) break; } } ! snprintf(elem, sizeof(elem), "--->%lx", MAKE_OFFSET(q)); strcat(buf, elem); elog(DEBUG2, "%s: %s", s, buf); ! snprintf(buf, sizeof(buf), "q nexts: %lx", MAKE_OFFSET(q)); count = 0; ! q = (SHM_QUEUE *) MAKE_PTR(q->next); while (q != start) { ! snprintf(elem, sizeof(elem), "--->%lx", MAKE_OFFSET(q)); strcat(buf, elem); ! q = (SHM_QUEUE *) MAKE_PTR(q->next); ! if (q->next == MAKE_OFFSET(q)) break; if (count++ > 10) { --- 225,243 ---- break; } } ! snprintf(elem, sizeof(elem), "--->%lx", q); strcat(buf, elem); elog(DEBUG2, "%s: %s", s, buf); ! snprintf(buf, sizeof(buf), "q nexts: %lx", q); count = 0; ! q = (SHM_QUEUE *) q->next; while (q != start) { ! snprintf(elem, sizeof(elem), "--->%lx", q); strcat(buf, elem); ! q = (SHM_QUEUE *) q->next; ! if (q->next == q) break; if (count++ > 10) { *************** *** 247,253 **** dumpQ(SHM_QUEUE *q, char *s) break; } } ! snprintf(elem, sizeof(elem), "--->%lx", MAKE_OFFSET(q)); strcat(buf, elem); elog(DEBUG2, "%s: %s", s, buf); } --- 245,251 ---- break; } } ! snprintf(elem, sizeof(elem), "--->%lx", q); strcat(buf, elem); elog(DEBUG2, "%s: %s", s, buf); } *** a/src/backend/storage/lmgr/deadlock.c --- b/src/backend/storage/lmgr/deadlock.c *************** *** 495,501 **** FindLockCycleRecurse(PGPROC *checkProc, /* * If the proc is not waiting, we have no outgoing waits-for edges. */ ! if (checkProc->links.next == INVALID_OFFSET) return false; lock = checkProc->waitLock; if (lock == NULL) --- 495,501 ---- /* * If the proc is not waiting, we have no outgoing waits-for edges. */ ! if (checkProc->links.next == NULL) return false; lock = checkProc->waitLock; if (lock == NULL) *************** *** 629,635 **** FindLockCycleRecurse(PGPROC *checkProc, waitQueue = &(lock->waitProcs); queue_size = waitQueue->size; ! proc = (PGPROC *) MAKE_PTR(waitQueue->links.next); while (queue_size-- > 0) { --- 629,635 ---- waitQueue = &(lock->waitProcs); queue_size = waitQueue->size; ! proc = (PGPROC *) waitQueue->links.next; while (queue_size-- > 0) { *************** *** 662,668 **** FindLockCycleRecurse(PGPROC *checkProc, } } ! proc = (PGPROC *) MAKE_PTR(proc->links.next); } } --- 662,668 ---- } } ! proc = (PGPROC *) proc->links.next; } } *************** *** 772,782 **** TopoSort(LOCK *lock, last; /* First, fill topoProcs[] array with the procs in their current order */ ! proc = (PGPROC *) MAKE_PTR(waitQueue->links.next); for (i = 0; i < queue_size; i++) { topoProcs[i] = proc; ! proc = (PGPROC *) MAKE_PTR(proc->links.next); } /* --- 772,782 ---- last; /* First, fill topoProcs[] array with the procs in their current order */ ! proc = (PGPROC *) waitQueue->links.next; for (i = 0; i < queue_size; i++) { topoProcs[i] = proc; ! proc = (PGPROC *) proc->links.next; } /* *************** *** 864,875 **** PrintLockQueue(LOCK *lock, const char *info) PGPROC *proc; int i; ! printf("%s lock %lx queue ", info, MAKE_OFFSET(lock)); ! proc = (PGPROC *) MAKE_PTR(waitQueue->links.next); for (i = 0; i < queue_size; i++) { printf(" %d", proc->pid); ! proc = (PGPROC *) MAKE_PTR(proc->links.next); } printf("\n"); fflush(stdout); --- 864,875 ---- PGPROC *proc; int i; ! printf("%s lock %lx queue ", info, lock); ! proc = (PGPROC *) waitQueue->links.next; for (i = 0; i < queue_size; i++) { printf(" %d", proc->pid); ! proc = (PGPROC *) proc->links.next; } printf("\n"); fflush(stdout); *** a/src/backend/storage/lmgr/lock.c --- b/src/backend/storage/lmgr/lock.c *************** *** 1214,1220 **** RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode) /* Make sure proc is waiting */ Assert(proc->waitStatus == STATUS_WAITING); ! Assert(proc->links.next != INVALID_OFFSET); Assert(waitLock); Assert(waitLock->waitProcs.size > 0); Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods)); --- 1214,1220 ---- /* Make sure proc is waiting */ Assert(proc->waitStatus == STATUS_WAITING); ! Assert(proc->links.next != NULL); Assert(waitLock); Assert(waitLock->waitProcs.size > 0); Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods)); *** a/src/backend/storage/lmgr/proc.c --- b/src/backend/storage/lmgr/proc.c *************** *** 170,177 **** InitProcGlobal(void) /* * Initialize the data structures. */ ! ProcGlobal->freeProcs = INVALID_OFFSET; ! ProcGlobal->autovacFreeProcs = INVALID_OFFSET; ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY; --- 170,177 ---- /* * Initialize the data structures. */ ! ProcGlobal->freeProcs = NULL; ! ProcGlobal->autovacFreeProcs = NULL; ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY; *************** *** 188,194 **** InitProcGlobal(void) { PGSemaphoreCreate(&(procs[i].sem)); procs[i].links.next = ProcGlobal->freeProcs; ! ProcGlobal->freeProcs = MAKE_OFFSET(&procs[i]); } procs = (PGPROC *) ShmemAlloc((autovacuum_max_workers) * sizeof(PGPROC)); --- 188,194 ---- { PGSemaphoreCreate(&(procs[i].sem)); procs[i].links.next = ProcGlobal->freeProcs; ! ProcGlobal->freeProcs = &procs[i]; } procs = (PGPROC *) ShmemAlloc((autovacuum_max_workers) * sizeof(PGPROC)); *************** *** 201,207 **** InitProcGlobal(void) { PGSemaphoreCreate(&(procs[i].sem)); procs[i].links.next = ProcGlobal->autovacFreeProcs; ! ProcGlobal->autovacFreeProcs = MAKE_OFFSET(&procs[i]); } MemSet(AuxiliaryProcs, 0, NUM_AUXILIARY_PROCS * sizeof(PGPROC)); --- 201,207 ---- { PGSemaphoreCreate(&(procs[i].sem)); procs[i].links.next = ProcGlobal->autovacFreeProcs; ! ProcGlobal->autovacFreeProcs = &procs[i]; } MemSet(AuxiliaryProcs, 0, NUM_AUXILIARY_PROCS * sizeof(PGPROC)); *************** *** 224,230 **** InitProcess(void) { /* use volatile pointer to prevent code rearrangement */ volatile PROC_HDR *procglobal = ProcGlobal; - SHMEM_OFFSET myOffset; int i; /* --- 224,229 ---- *************** *** 249,261 **** InitProcess(void) set_spins_per_delay(procglobal->spins_per_delay); if (IsAutoVacuumWorkerProcess()) ! myOffset = procglobal->autovacFreeProcs; else ! myOffset = procglobal->freeProcs; ! if (myOffset != INVALID_OFFSET) { - MyProc = (PGPROC *) MAKE_PTR(myOffset); if (IsAutoVacuumWorkerProcess()) procglobal->autovacFreeProcs = MyProc->links.next; else --- 248,259 ---- set_spins_per_delay(procglobal->spins_per_delay); if (IsAutoVacuumWorkerProcess()) ! MyProc = procglobal->autovacFreeProcs; else ! MyProc = procglobal->freeProcs; ! if (MyProc != NULL) { if (IsAutoVacuumWorkerProcess()) procglobal->autovacFreeProcs = MyProc->links.next; else *************** *** 461,467 **** InitAuxiliaryProcess(void) bool HaveNFreeProcs(int n) { - SHMEM_OFFSET offset; PGPROC *proc; /* use volatile pointer to prevent code rearrangement */ --- 459,464 ---- *************** *** 469,480 **** HaveNFreeProcs(int n) SpinLockAcquire(ProcStructLock); ! offset = procglobal->freeProcs; ! while (n > 0 && offset != INVALID_OFFSET) { ! proc = (PGPROC *) MAKE_PTR(offset); ! offset = proc->links.next; n--; } --- 466,476 ---- SpinLockAcquire(ProcStructLock); ! proc = procglobal->freeProcs; ! while (n > 0 && proc != NULL) { ! proc = (PGPROC *) proc->links.next; n--; } *************** *** 506,512 **** LockWaitCancel(void) partitionLock = LockHashPartitionLock(lockAwaited->hashcode); LWLockAcquire(partitionLock, LW_EXCLUSIVE); ! if (MyProc->links.next != INVALID_OFFSET) { /* We could not have been granted the lock yet */ RemoveFromWaitQueue(MyProc, lockAwaited->hashcode); --- 502,508 ---- partitionLock = LockHashPartitionLock(lockAwaited->hashcode); LWLockAcquire(partitionLock, LW_EXCLUSIVE); ! if (MyProc->links.next != NULL) { /* We could not have been granted the lock yet */ RemoveFromWaitQueue(MyProc, lockAwaited->hashcode); *************** *** 602,613 **** ProcKill(int code, Datum arg) if (IsAutoVacuumWorkerProcess()) { MyProc->links.next = procglobal->autovacFreeProcs; ! procglobal->autovacFreeProcs = MAKE_OFFSET(MyProc); } else { MyProc->links.next = procglobal->freeProcs; ! procglobal->freeProcs = MAKE_OFFSET(MyProc); } /* PGPROC struct isn't mine anymore */ --- 598,609 ---- if (IsAutoVacuumWorkerProcess()) { MyProc->links.next = procglobal->autovacFreeProcs; ! procglobal->autovacFreeProcs = MyProc; } else { MyProc->links.next = procglobal->freeProcs; ! procglobal->freeProcs = MyProc; } /* PGPROC struct isn't mine anymore */ *************** *** 752,758 **** ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) { LOCKMASK aheadRequests = 0; ! proc = (PGPROC *) MAKE_PTR(waitQueue->links.next); for (i = 0; i < waitQueue->size; i++) { /* Must he wait for me? */ --- 748,754 ---- { LOCKMASK aheadRequests = 0; ! proc = (PGPROC *) waitQueue->links.next; for (i = 0; i < waitQueue->size; i++) { /* Must he wait for me? */ *************** *** 790,796 **** ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) } /* Nope, so advance to next waiter */ aheadRequests |= LOCKBIT_ON(proc->waitLockMode); ! proc = (PGPROC *) MAKE_PTR(proc->links.next); } /* --- 786,792 ---- } /* Nope, so advance to next waiter */ aheadRequests |= LOCKBIT_ON(proc->waitLockMode); ! proc = (PGPROC *) proc->links.next; } /* *************** *** 1054,1066 **** ProcWakeup(PGPROC *proc, int waitStatus) PGPROC *retProc; /* Proc should be sleeping ... */ ! if (proc->links.prev == INVALID_OFFSET || ! proc->links.next == INVALID_OFFSET) return NULL; Assert(proc->waitStatus == STATUS_WAITING); /* Save next process before we zap the list link */ ! retProc = (PGPROC *) MAKE_PTR(proc->links.next); /* Remove process from wait queue */ SHMQueueDelete(&(proc->links)); --- 1050,1062 ---- PGPROC *retProc; /* Proc should be sleeping ... */ ! if (proc->links.prev == NULL || ! proc->links.next == NULL) return NULL; Assert(proc->waitStatus == STATUS_WAITING); /* Save next process before we zap the list link */ ! retProc = (PGPROC *) proc->links.next; /* Remove process from wait queue */ SHMQueueDelete(&(proc->links)); *************** *** 1097,1103 **** ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock) if (queue_size == 0) return; ! proc = (PGPROC *) MAKE_PTR(waitQueue->links.next); while (queue_size-- > 0) { --- 1093,1099 ---- if (queue_size == 0) return; ! proc = (PGPROC *) waitQueue->links.next; while (queue_size-- > 0) { *************** *** 1130,1136 **** ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock) * Cannot wake this guy. Remember his request for later checks. */ aheadRequests |= LOCKBIT_ON(lockmode); ! proc = (PGPROC *) MAKE_PTR(proc->links.next); } } --- 1126,1132 ---- * Cannot wake this guy. Remember his request for later checks. */ aheadRequests |= LOCKBIT_ON(lockmode); ! proc = (PGPROC *) proc->links.next; } } *************** *** 1179,1186 **** CheckDeadLock(void) * This is quicker than checking our semaphore's state, since no kernel * call is needed, and it is safe because we hold the lock partition lock. */ ! if (MyProc->links.prev == INVALID_OFFSET || ! MyProc->links.next == INVALID_OFFSET) goto check_done; #ifdef LOCK_DEBUG --- 1175,1182 ---- * This is quicker than checking our semaphore's state, since no kernel * call is needed, and it is safe because we hold the lock partition lock. */ ! if (MyProc->links.prev == NULL || ! MyProc->links.next == NULL) goto check_done; #ifdef LOCK_DEBUG *** a/src/include/storage/pg_shmem.h --- b/src/include/storage/pg_shmem.h *************** *** 31,37 **** typedef struct PGShmemHeader /* standard header for all Postgres shmem */ pid_t creatorPID; /* PID of creating process */ Size totalsize; /* total size of segment */ Size freeoffset; /* offset to first free space */ ! Size indexoffset; /* offset to ShmemIndex table */ #ifndef WIN32 /* Windows doesn't have useful inode#s */ dev_t device; /* device data directory is on */ ino_t inode; /* inode number of data directory */ --- 31,37 ---- pid_t creatorPID; /* PID of creating process */ Size totalsize; /* total size of segment */ Size freeoffset; /* offset to first free space */ ! void *index; /* pointer to ShmemIndex table */ #ifndef WIN32 /* Windows doesn't have useful inode#s */ dev_t device; /* device data directory is on */ ino_t inode; /* inode number of data directory */ *** a/src/include/storage/proc.h --- b/src/include/storage/proc.h *************** *** 128,136 **** extern PGDLLIMPORT PGPROC *MyProc; typedef struct PROC_HDR { /* Head of list of free PGPROC structures */ ! SHMEM_OFFSET freeProcs; /* Head of list of autovacuum's free PGPROC structures */ ! SHMEM_OFFSET autovacFreeProcs; /* Current shared estimate of appropriate spins_per_delay value */ int spins_per_delay; } PROC_HDR; --- 128,136 ---- typedef struct PROC_HDR { /* Head of list of free PGPROC structures */ ! PGPROC *freeProcs; /* Head of list of autovacuum's free PGPROC structures */ ! PGPROC *autovacFreeProcs; /* Current shared estimate of appropriate spins_per_delay value */ int spins_per_delay; } PROC_HDR; *** a/src/include/storage/shmem.h --- b/src/include/storage/shmem.h *************** *** 18,69 **** /* ! * The shared memory region can start at a different address ! * in every process. Shared memory "pointers" are actually ! * offsets relative to the start of the shared memory region(s). ! * ! * In current usage, this is not actually a problem, but we keep ! * the code that used to handle it... ! */ ! typedef unsigned long SHMEM_OFFSET; ! ! #define INVALID_OFFSET (-1) ! ! /* ! * Start of the primary shared memory region, in this process' address space. ! * The macros in this header file can only cope with offsets into this ! * shared memory region! */ - extern PGDLLIMPORT SHMEM_OFFSET ShmemBase; - - - /* coerce an offset into a pointer in this process's address space */ - #define MAKE_PTR(xx_offs)\ - (ShmemBase+((unsigned long)(xx_offs))) - - /* coerce a pointer into a shmem offset */ - #define MAKE_OFFSET(xx_ptr)\ - ((SHMEM_OFFSET) (((unsigned long)(xx_ptr))-ShmemBase)) - - #define SHM_PTR_VALID(xx_ptr)\ - (((unsigned long)(xx_ptr)) > ShmemBase) - - /* cannot have an offset to ShmemFreeStart (offset 0) */ - #define SHM_OFFSET_VALID(xx_offs)\ - (((xx_offs) != 0) && ((xx_offs) != INVALID_OFFSET)) /* shmqueue.c */ typedef struct SHM_QUEUE { ! SHMEM_OFFSET prev; ! SHMEM_OFFSET next; } SHM_QUEUE; /* shmem.c */ extern void InitShmemAccess(void *seghdr); extern void InitShmemAllocation(void); extern void *ShmemAlloc(Size size); ! extern bool ShmemIsValid(unsigned long addr); extern void InitShmemIndex(void); extern HTAB *ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags); --- 18,44 ---- /* ! * In previous incarnations, the shared memory region was allowed to ! * be mapped into a different address for each process and shared memory ! * "pointers" were passed around as offsets relative to the start of the ! * shared memory region. This is no longer the case as each process ! * must map the shared memory region to the same address. Therefore ! * shared memory "pointers" can be passed around directly between different ! * processes. */ /* shmqueue.c */ typedef struct SHM_QUEUE { ! void *prev; ! void *next; } SHM_QUEUE; /* shmem.c */ extern void InitShmemAccess(void *seghdr); extern void InitShmemAllocation(void); extern void *ShmemAlloc(Size size); ! extern bool ShmemIsValid(void *addr); extern void InitShmemIndex(void); extern HTAB *ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags); *************** *** 84,90 **** extern void RequestAddinShmemSpace(Size size); typedef struct { char key[SHMEM_INDEX_KEYSIZE]; /* string name */ ! unsigned long location; /* location in shared mem */ unsigned long size; /* numbytes allocated for the structure */ } ShmemIndexEnt; --- 59,65 ---- typedef struct { char key[SHMEM_INDEX_KEYSIZE]; /* string name */ ! void *location; /* location in shared mem */ unsigned long size; /* numbytes allocated for the structure */ } ShmemIndexEnt;