Since we require every process to map the shared memory region to the same
address, we don't need the MAKE_PTR/OFFSET code that was needed when that
was not the case. This patch makes shared memory pointers just like
regular pointers.
http://archives.postgresql.org/pgsql-general/2007-08/msg01510.php
Kris Jurka
*** 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;
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers