aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-02-07 09:38:25 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-02-07 10:11:54 +0200
commit15ad6f1510f8979a39e4c39078c742b5fdb121ce (patch)
tree8dbe561e53e047c8e279aa74e8a2e009cf67efcd
parent442231d7f71764b8c628044e7ce2225f9aa43b67 (diff)
downloadpostgresql-15ad6f1510f8979a39e4c39078c742b5fdb121ce.tar.gz
postgresql-15ad6f1510f8979a39e4c39078c742b5fdb121ce.zip
When building with LWLOCK_STATS, initialize the stats in LWLockWaitUntilFree.
If LWLockWaitUntilFree was called before the first LWLockAcquire call, you would either crash because of access to uninitialized array or account the acquisition incorrectly. LWLockConditionalAcquire doesn't have this problem because it doesn't update the lwlock stats. In practice, this never happens because there is no codepath where you would call LWLockWaitUntilfree before LWLockAcquire after a new process is launched. But that's just accidental, there's no guarantee that that's always going to be true in the future. Spotted by Jeff Janes.
-rw-r--r--src/backend/storage/lmgr/lwlock.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 6511faf985d..5d2873100de 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -123,6 +123,22 @@ LOG_LWDEBUG(const char *where, LWLockId lockid, const char *msg)
#ifdef LWLOCK_STATS
+static void init_lwlock_stats(void);
+static void print_lwlock_stats(int code, Datum arg);
+
+static void
+init_lwlock_stats(void)
+{
+ int *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
+ int numLocks = LWLockCounter[1];
+
+ sh_acquire_counts = calloc(numLocks, sizeof(int));
+ ex_acquire_counts = calloc(numLocks, sizeof(int));
+ block_counts = calloc(numLocks, sizeof(int));
+ counts_for_pid = MyProcPid;
+ on_shmem_exit(print_lwlock_stats, 0);
+}
+
static void
print_lwlock_stats(int code, Datum arg)
{
@@ -332,16 +348,7 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode)
#ifdef LWLOCK_STATS
/* Set up local count state first time through in a given process */
if (counts_for_pid != MyProcPid)
- {
- int *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
- int numLocks = LWLockCounter[1];
-
- sh_acquire_counts = calloc(numLocks, sizeof(int));
- ex_acquire_counts = calloc(numLocks, sizeof(int));
- block_counts = calloc(numLocks, sizeof(int));
- counts_for_pid = MyProcPid;
- on_shmem_exit(print_lwlock_stats, 0);
- }
+ init_lwlock_stats();
/* Count lock acquisition attempts */
if (mode == LW_EXCLUSIVE)
ex_acquire_counts[lockid]++;
@@ -588,6 +595,12 @@ LWLockWaitUntilFree(LWLockId lockid, LWLockMode mode)
PRINT_LWDEBUG("LWLockWaitUntilFree", lockid, lock);
+#ifdef LWLOCK_STATS
+ /* Set up local count state first time through in a given process */
+ if (counts_for_pid != MyProcPid)
+ init_lwlock_stats();
+#endif
+
/* Ensure we will have room to remember the lock */
if (num_held_lwlocks >= MAX_SIMUL_LWLOCKS)
elog(ERROR, "too many LWLocks taken");