17
17
* per-buffer LWLocks that synchronize I/O for each buffer. The control lock
18
18
* must be held to examine or modify any shared state. A process that is
19
19
* reading in or writing out a page buffer does not hold the control lock,
20
- * only the per-buffer lock for the buffer it is working on.
20
+ * only the per-buffer lock for the buffer it is working on. One exception
21
+ * is latest_page_number, which is read and written using atomic ops.
21
22
*
22
23
* "Holding the control lock" means exclusive lock in all cases except for
23
24
* SimpleLruReadPage_ReadOnly(); see comments for SlruRecentlyUsed() for
@@ -239,8 +240,7 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
239
240
shared -> lsn_groups_per_page = nlsns ;
240
241
241
242
shared -> cur_lru_count = 0 ;
242
-
243
- /* shared->latest_page_number will be set later */
243
+ pg_atomic_write_u64 (& shared -> latest_page_number , 0 );
244
244
245
245
shared -> slru_stats_idx = pgstat_get_slru_index (name );
246
246
@@ -329,8 +329,15 @@ SimpleLruZeroPage(SlruCtl ctl, int64 pageno)
329
329
/* Set the LSNs for this new page to zero */
330
330
SimpleLruZeroLSNs (ctl , slotno );
331
331
332
- /* Assume this page is now the latest active page */
333
- shared -> latest_page_number = pageno ;
332
+ /*
333
+ * Assume this page is now the latest active page.
334
+ *
335
+ * Note that because both this routine and SlruSelectLRUPage run with
336
+ * ControlLock held, it is not possible for this to be zeroing a page that
337
+ * SlruSelectLRUPage is going to evict simultaneously. Therefore, there's
338
+ * no memory barrier here.
339
+ */
340
+ pg_atomic_write_u64 (& shared -> latest_page_number , pageno );
334
341
335
342
/* update the stats counter of zeroed pages */
336
343
pgstat_count_slru_page_zeroed (shared -> slru_stats_idx );
@@ -1113,9 +1120,17 @@ SlruSelectLRUPage(SlruCtl ctl, int64 pageno)
1113
1120
shared -> page_lru_count [slotno ] = cur_count ;
1114
1121
this_delta = 0 ;
1115
1122
}
1123
+
1124
+ /*
1125
+ * If this page is the one most recently zeroed, don't consider it
1126
+ * an eviction candidate. See comments in SimpleLruZeroPage for an
1127
+ * explanation about the lack of a memory barrier here.
1128
+ */
1116
1129
this_page_number = shared -> page_number [slotno ];
1117
- if (this_page_number == shared -> latest_page_number )
1130
+ if (this_page_number ==
1131
+ pg_atomic_read_u64 (& shared -> latest_page_number ))
1118
1132
continue ;
1133
+
1119
1134
if (shared -> page_status [slotno ] == SLRU_PAGE_VALID )
1120
1135
{
1121
1136
if (this_delta > best_valid_delta ||
@@ -1254,7 +1269,6 @@ void
1254
1269
SimpleLruTruncate (SlruCtl ctl , int64 cutoffPage )
1255
1270
{
1256
1271
SlruShared shared = ctl -> shared ;
1257
- int slotno ;
1258
1272
1259
1273
/* update the stats counter of truncates */
1260
1274
pgstat_count_slru_truncate (shared -> slru_stats_idx );
@@ -1270,10 +1284,13 @@ SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
1270
1284
restart :
1271
1285
1272
1286
/*
1273
- * While we are holding the lock, make an important safety check: the
1274
- * current endpoint page must not be eligible for removal.
1287
+ * An important safety check: the current endpoint page must not be
1288
+ * eligible for removal. This check is just a backstop against wraparound
1289
+ * bugs elsewhere in SLRU handling, so we don't care if we read a slightly
1290
+ * outdated value; therefore we don't add a memory barrier.
1275
1291
*/
1276
- if (ctl -> PagePrecedes (shared -> latest_page_number , cutoffPage ))
1292
+ if (ctl -> PagePrecedes (pg_atomic_read_u64 (& shared -> latest_page_number ),
1293
+ cutoffPage ))
1277
1294
{
1278
1295
LWLockRelease (shared -> ControlLock );
1279
1296
ereport (LOG ,
@@ -1282,7 +1299,7 @@ SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
1282
1299
return ;
1283
1300
}
1284
1301
1285
- for (slotno = 0 ; slotno < shared -> num_slots ; slotno ++ )
1302
+ for (int slotno = 0 ; slotno < shared -> num_slots ; slotno ++ )
1286
1303
{
1287
1304
if (shared -> page_status [slotno ] == SLRU_PAGE_EMPTY )
1288
1305
continue ;
0 commit comments