PostgreSQL Source Code git master
Loading...
Searching...
No Matches
freelist.c File Reference
#include "postgres.h"
#include "pgstat.h"
#include "port/atomics.h"
#include "storage/buf_internals.h"
#include "storage/bufmgr.h"
#include "storage/proc.h"
#include "storage/shmem.h"
#include "storage/subsystems.h"
Include dependency graph for freelist.c:

Go to the source code of this file.

Data Structures

struct  BufferStrategyControl
 
struct  BufferAccessStrategyData
 

Macros

#define INT_ACCESS_ONCE(var)   ((int)(*((volatile int *)&(var))))
 

Typedefs

typedef struct BufferAccessStrategyData BufferAccessStrategyData
 

Functions

static void StrategyCtlShmemRequest (void *arg)
 
static void StrategyCtlShmemInit (void *arg)
 
static BufferDescGetBufferFromRing (BufferAccessStrategy strategy, uint64 *buf_state)
 
static void AddBufferToRing (BufferAccessStrategy strategy, BufferDesc *buf)
 
static uint32 ClockSweepTick (void)
 
BufferDescStrategyGetBuffer (BufferAccessStrategy strategy, uint64 *buf_state, bool *from_ring)
 
int StrategySyncStart (uint32 *complete_passes, uint32 *num_buf_alloc)
 
void StrategyNotifyBgWriter (int bgwprocno)
 
BufferAccessStrategy GetAccessStrategy (BufferAccessStrategyType btype)
 
BufferAccessStrategy GetAccessStrategyWithSize (BufferAccessStrategyType btype, int ring_size_kb)
 
int GetAccessStrategyBufferCount (BufferAccessStrategy strategy)
 
int GetAccessStrategyPinLimit (BufferAccessStrategy strategy)
 
void FreeAccessStrategy (BufferAccessStrategy strategy)
 
IOContext IOContextForStrategy (BufferAccessStrategy strategy)
 
bool StrategyRejectBuffer (BufferAccessStrategy strategy, BufferDesc *buf, bool from_ring)
 

Variables

static BufferStrategyControlStrategyControl = NULL
 
const ShmemCallbacks StrategyCtlShmemCallbacks
 

Macro Definition Documentation

◆ INT_ACCESS_ONCE

#define INT_ACCESS_ONCE (   var)    ((int)(*((volatile int *)&(var))))

Definition at line 26 of file freelist.c.

Typedef Documentation

◆ BufferAccessStrategyData

Function Documentation

◆ AddBufferToRing()

static void AddBufferToRing ( BufferAccessStrategy  strategy,
BufferDesc buf 
)
static

Definition at line 702 of file freelist.c.

703{
704 strategy->buffers[strategy->current] = BufferDescriptorGetBuffer(buf);
705}
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
static char buf[DEFAULT_XLOG_SEG_SIZE]
Buffer buffers[FLEXIBLE_ARRAY_MEMBER]
Definition freelist.c:93

References buf, BufferDescriptorGetBuffer(), BufferAccessStrategyData::buffers, and BufferAccessStrategyData::current.

Referenced by StrategyGetBuffer().

◆ ClockSweepTick()

static uint32 ClockSweepTick ( void  )
inlinestatic

Definition at line 110 of file freelist.c.

111{
113
114 /*
115 * Atomically move hand ahead one buffer - if there's several processes
116 * doing this, this can lead to buffers being returned slightly out of
117 * apparent order.
118 */
119 victim =
121
122 if (victim >= NBuffers)
123 {
125
126 /* always wrap what we look up in BufferDescriptors */
128
129 /*
130 * If we're the one that just caused a wraparound, force
131 * completePasses to be incremented while holding the spinlock. We
132 * need the spinlock so StrategySyncStart() can return a consistent
133 * value consisting of nextVictimBuffer and completePasses.
134 */
135 if (victim == 0)
136 {
139 bool success = false;
140
142
143 while (!success)
144 {
145 /*
146 * Acquire the spinlock while increasing completePasses. That
147 * allows other readers to read nextVictimBuffer and
148 * completePasses in a consistent manner which is required for
149 * StrategySyncStart(). In theory delaying the increment
150 * could lead to an overflow of nextVictimBuffers, but that's
151 * highly unlikely and wouldn't be particularly harmful.
152 */
154
156
158 &expected, wrapped);
159 if (success)
162 }
163 }
164 }
165 return victim;
166}
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition atomics.h:349
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition atomics.h:366
uint32_t uint32
Definition c.h:624
static BufferStrategyControl * StrategyControl
Definition freelist.c:59
int NBuffers
Definition globals.c:144
static bool success
Definition initdb.c:188
static int fb(int x)
static void SpinLockRelease(volatile slock_t *lock)
Definition spin.h:62
static void SpinLockAcquire(volatile slock_t *lock)
Definition spin.h:56
pg_atomic_uint32 nextVictimBuffer
Definition freelist.c:42
slock_t buffer_strategy_lock
Definition freelist.c:35

References BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::completePasses, fb(), NBuffers, BufferStrategyControl::nextVictimBuffer, pg_atomic_compare_exchange_u32(), pg_atomic_fetch_add_u32(), SpinLockAcquire(), SpinLockRelease(), StrategyControl, and success.

Referenced by StrategyGetBuffer().

◆ FreeAccessStrategy()

void FreeAccessStrategy ( BufferAccessStrategy  strategy)

Definition at line 608 of file freelist.c.

609{
610 /* don't crash if called on a "default" strategy */
611 if (strategy != NULL)
612 pfree(strategy);
613}
void pfree(void *pointer)
Definition mcxt.c:1616

References fb(), and pfree().

Referenced by blgetbitmap(), FreeBulkInsertState(), heap_endscan(), initscan(), parallel_vacuum_main(), and RelationCopyStorageUsingBuffer().

◆ GetAccessStrategy()

BufferAccessStrategy GetAccessStrategy ( BufferAccessStrategyType  btype)

Definition at line 426 of file freelist.c.

427{
428 int ring_size_kb;
429
430 /*
431 * Select ring size to use. See buffer/README for rationales.
432 *
433 * Note: if you change the ring size for BAS_BULKREAD, see also
434 * SYNC_SCAN_REPORT_INTERVAL in access/heap/syncscan.c.
435 */
436 switch (btype)
437 {
438 case BAS_NORMAL:
439 /* if someone asks for NORMAL, just give 'em a "default" object */
440 return NULL;
441
442 case BAS_BULKREAD:
443 {
444 int ring_max_kb;
445
446 /*
447 * The ring always needs to be large enough to allow some
448 * separation in time between providing a buffer to the user
449 * of the strategy and that buffer being reused. Otherwise the
450 * user's pin will prevent reuse of the buffer, even without
451 * concurrent activity.
452 *
453 * We also need to ensure the ring always is large enough for
454 * SYNC_SCAN_REPORT_INTERVAL, as noted above.
455 *
456 * Thus we start out a minimal size and increase the size
457 * further if appropriate.
458 */
459 ring_size_kb = 256;
460
461 /*
462 * There's no point in a larger ring if we won't be allowed to
463 * pin sufficiently many buffers. But we never limit to less
464 * than the minimal size above.
465 */
466 ring_max_kb = GetPinLimit() * (BLCKSZ / 1024);
468
469 /*
470 * We would like the ring to additionally have space for the
471 * configured degree of IO concurrency. While being read in,
472 * buffers can obviously not yet be reused.
473 *
474 * Each IO can be up to io_combine_limit blocks large, and we
475 * want to start up to effective_io_concurrency IOs.
476 *
477 * Note that effective_io_concurrency may be 0, which disables
478 * AIO.
479 */
480 ring_size_kb += (BLCKSZ / 1024) *
482
485 break;
486 }
487 case BAS_BULKWRITE:
488 ring_size_kb = 16 * 1024;
489 break;
490 case BAS_VACUUM:
491 ring_size_kb = 2048;
492 break;
493
494 default:
495 elog(ERROR, "unrecognized buffer access strategy: %d",
496 (int) btype);
497 return NULL; /* keep compiler quiet */
498 }
499
501}
int effective_io_concurrency
Definition bufmgr.c:200
int io_combine_limit
Definition bufmgr.c:215
uint32 GetPinLimit(void)
Definition bufmgr.c:2686
@ BAS_BULKREAD
Definition bufmgr.h:37
@ BAS_NORMAL
Definition bufmgr.h:36
@ BAS_VACUUM
Definition bufmgr.h:40
@ BAS_BULKWRITE
Definition bufmgr.h:39
#define Max(x, y)
Definition c.h:1085
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype, int ring_size_kb)
Definition freelist.c:511

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, effective_io_concurrency, elog, ERROR, fb(), GetAccessStrategyWithSize(), GetPinLimit(), io_combine_limit, and Max.

Referenced by blgetbitmap(), bt_check_every_level(), collect_corrupt_items(), collect_visibility_data(), DataChecksumsWorkerMain(), GetBulkInsertState(), gin_check_parent_keys_consistency(), gin_check_posting_tree_parent_keys_consistency(), initscan(), pgstat_index(), pgstathashindex(), pgstatindex_impl(), RelationCopyStorageUsingBuffer(), ScanSourceDatabasePgClass(), statapprox_heap(), and verify_heapam().

◆ GetAccessStrategyBufferCount()

int GetAccessStrategyBufferCount ( BufferAccessStrategy  strategy)

Definition at line 551 of file freelist.c.

552{
553 if (strategy == NULL)
554 return 0;
555
556 return strategy->nbuffers;
557}

References fb(), and BufferAccessStrategyData::nbuffers.

Referenced by parallel_vacuum_init().

◆ GetAccessStrategyPinLimit()

int GetAccessStrategyPinLimit ( BufferAccessStrategy  strategy)

Definition at line 574 of file freelist.c.

575{
576 if (strategy == NULL)
577 return NBuffers;
578
579 switch (strategy->btype)
580 {
581 case BAS_BULKREAD:
582
583 /*
584 * Since BAS_BULKREAD uses StrategyRejectBuffer(), dirty buffers
585 * shouldn't be a problem and the caller is free to pin up to the
586 * entire ring at once.
587 */
588 return strategy->nbuffers;
589
590 default:
591
592 /*
593 * Tell caller not to pin more than half the buffers in the ring.
594 * This is a trade-off between look ahead distance and deferring
595 * writeback and associated WAL traffic.
596 */
597 return strategy->nbuffers / 2;
598 }
599}
BufferAccessStrategyType btype
Definition freelist.c:77

References BAS_BULKREAD, BufferAccessStrategyData::btype, fb(), BufferAccessStrategyData::nbuffers, and NBuffers.

Referenced by read_stream_begin_impl().

◆ GetAccessStrategyWithSize()

BufferAccessStrategy GetAccessStrategyWithSize ( BufferAccessStrategyType  btype,
int  ring_size_kb 
)

Definition at line 511 of file freelist.c.

512{
513 int ring_buffers;
514 BufferAccessStrategy strategy;
515
516 Assert(ring_size_kb >= 0);
517
518 /* Figure out how many buffers ring_size_kb is */
519 ring_buffers = ring_size_kb / (BLCKSZ / 1024);
520
521 /* 0 means unlimited, so no BufferAccessStrategy required */
522 if (ring_buffers == 0)
523 return NULL;
524
525 /* Cap to 1/8th of shared_buffers */
527
528 /* NBuffers should never be less than 16, so this shouldn't happen */
529 Assert(ring_buffers > 0);
530
531 /* Allocate the object and initialize all elements to zeroes */
532 strategy = (BufferAccessStrategy)
534 ring_buffers * sizeof(Buffer));
535
536 /* Set fields that don't start out zero */
537 strategy->btype = btype;
538 strategy->nbuffers = ring_buffers;
539
540 return strategy;
541}
int Buffer
Definition buf.h:23
struct BufferAccessStrategyData * BufferAccessStrategy
Definition buf.h:44
#define Min(x, y)
Definition c.h:1091
#define Assert(condition)
Definition c.h:943
void * palloc0(Size size)
Definition mcxt.c:1417

References Assert, BufferAccessStrategyData::btype, fb(), Min, BufferAccessStrategyData::nbuffers, NBuffers, and palloc0().

Referenced by do_autovacuum(), ExecVacuum(), GetAccessStrategy(), and parallel_vacuum_main().

◆ GetBufferFromRing()

static BufferDesc * GetBufferFromRing ( BufferAccessStrategy  strategy,
uint64 buf_state 
)
static

Definition at line 623 of file freelist.c.

624{
628 uint64 local_buf_state; /* to avoid repeated (de-)referencing */
629
630
631 /* Advance to next ring slot */
632 if (++strategy->current >= strategy->nbuffers)
633 strategy->current = 0;
634
635 /*
636 * If the slot hasn't been filled yet, tell the caller to allocate a new
637 * buffer with the normal allocation strategy. He will then fill this
638 * slot by calling AddBufferToRing with the new buffer.
639 */
640 bufnum = strategy->buffers[strategy->current];
641 if (bufnum == InvalidBuffer)
642 return NULL;
643
645
646 /*
647 * Check whether the buffer can be used and pin it if so. Do this using a
648 * CAS loop, to avoid having to lock the buffer header.
649 */
651 for (;;)
652 {
654
655 /*
656 * If the buffer is pinned we cannot use it under any circumstances.
657 *
658 * If usage_count is 0 or 1 then the buffer is fair game (we expect 1,
659 * since our own previous usage of the ring element would have left it
660 * there, but it might've been decremented by clock-sweep since then).
661 * A higher usage_count indicates someone else has touched the buffer,
662 * so we shouldn't re-use it.
663 */
666 break;
667
668 /* See equivalent code in PinBuffer() */
670 {
672 continue;
673 }
674
675 /* pin the buffer if the CAS succeeds */
677
680 {
682
684 return buf;
685 }
686 }
687
688 /*
689 * Tell caller to allocate a new buffer with the normal allocation
690 * strategy. He'll then replace this ring element via AddBufferToRing.
691 */
692 return NULL;
693}
static bool pg_atomic_compare_exchange_u64(volatile pg_atomic_uint64 *ptr, uint64 *expected, uint64 newval)
Definition atomics.h:522
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition atomics.h:467
#define InvalidBuffer
Definition buf.h:25
#define BUF_REFCOUNT_ONE
#define BM_LOCKED
#define BUF_STATE_GET_USAGECOUNT(state)
#define BUF_STATE_GET_REFCOUNT(state)
static BufferDesc * GetBufferDescriptor(uint32 id)
pg_noinline uint64 WaitBufHdrUnlocked(BufferDesc *buf)
Definition bufmgr.c:7566
void TrackNewBufferPin(Buffer buf)
Definition bufmgr.c:3512
uint64_t uint64
Definition c.h:625
#define unlikely(x)
Definition c.h:438

References BM_LOCKED, buf, BUF_REFCOUNT_ONE, BUF_STATE_GET_REFCOUNT, BUF_STATE_GET_USAGECOUNT, BufferDescriptorGetBuffer(), BufferAccessStrategyData::buffers, BufferAccessStrategyData::current, fb(), GetBufferDescriptor(), InvalidBuffer, BufferAccessStrategyData::nbuffers, pg_atomic_compare_exchange_u64(), pg_atomic_read_u64(), TrackNewBufferPin(), unlikely, and WaitBufHdrUnlocked().

Referenced by StrategyGetBuffer().

◆ IOContextForStrategy()

IOContext IOContextForStrategy ( BufferAccessStrategy  strategy)

Definition at line 712 of file freelist.c.

713{
714 if (!strategy)
715 return IOCONTEXT_NORMAL;
716
717 switch (strategy->btype)
718 {
719 case BAS_NORMAL:
720
721 /*
722 * Currently, GetAccessStrategy() returns NULL for
723 * BufferAccessStrategyType BAS_NORMAL, so this case is
724 * unreachable.
725 */
727 return IOCONTEXT_NORMAL;
728 case BAS_BULKREAD:
729 return IOCONTEXT_BULKREAD;
730 case BAS_BULKWRITE:
731 return IOCONTEXT_BULKWRITE;
732 case BAS_VACUUM:
733 return IOCONTEXT_VACUUM;
734 }
735
736 elog(ERROR, "unrecognized BufferAccessStrategyType: %d", strategy->btype);
738}
#define pg_unreachable()
Definition c.h:367
@ IOCONTEXT_NORMAL
Definition pgstat.h:293
@ IOCONTEXT_VACUUM
Definition pgstat.h:294
@ IOCONTEXT_BULKREAD
Definition pgstat.h:290
@ IOCONTEXT_BULKWRITE
Definition pgstat.h:291

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, BufferAccessStrategyData::btype, elog, ERROR, IOCONTEXT_BULKREAD, IOCONTEXT_BULKWRITE, IOCONTEXT_NORMAL, IOCONTEXT_VACUUM, and pg_unreachable.

Referenced by AsyncReadBuffers(), ExtendBufferedRelShared(), ReadBuffer_common(), StartReadBuffersImpl(), and WaitReadBuffers().

◆ StrategyCtlShmemInit()

static void StrategyCtlShmemInit ( void arg)
static

Definition at line 398 of file freelist.c.

399{
401
402 /* Initialize the clock-sweep pointer */
404
405 /* Clear statistics */
408
409 /* No pending notification */
411}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:219
static void SpinLockInit(volatile slock_t *lock)
Definition spin.h:50
pg_atomic_uint32 numBufferAllocs
Definition freelist.c:49

References BufferStrategyControl::bgwprocno, BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::completePasses, BufferStrategyControl::nextVictimBuffer, BufferStrategyControl::numBufferAllocs, pg_atomic_init_u32(), SpinLockInit(), and StrategyControl.

◆ StrategyCtlShmemRequest()

static void StrategyCtlShmemRequest ( void arg)
static

Definition at line 386 of file freelist.c.

387{
388 ShmemRequestStruct(.name = "Buffer Strategy Status",
389 .size = sizeof(BufferStrategyControl),
390 .ptr = (void **) &StrategyControl
391 );
392}
#define ShmemRequestStruct(...)
Definition shmem.h:176
const char * name

References name, ShmemRequestStruct, and StrategyControl.

◆ StrategyGetBuffer()

BufferDesc * StrategyGetBuffer ( BufferAccessStrategy  strategy,
uint64 buf_state,
bool from_ring 
)

Definition at line 184 of file freelist.c.

185{
187 int bgwprocno;
188 int trycounter;
189
190 *from_ring = false;
191
192 /*
193 * If given a strategy object, see whether it can select a buffer. We
194 * assume strategy objects don't need buffer_strategy_lock.
195 */
196 if (strategy != NULL)
197 {
198 buf = GetBufferFromRing(strategy, buf_state);
199 if (buf != NULL)
200 {
201 *from_ring = true;
202 return buf;
203 }
204 }
205
206 /*
207 * If asked, we need to waken the bgwriter. Since we don't want to rely on
208 * a spinlock for this we force a read from shared memory once, and then
209 * set the latch based on that value. We need to go through that length
210 * because otherwise bgwprocno might be reset while/after we check because
211 * the compiler might just reread from memory.
212 *
213 * This can possibly set the latch of the wrong process if the bgwriter
214 * dies in the wrong moment. But since PGPROC->procLatch is never
215 * deallocated the worst consequence of that is that we set the latch of
216 * some arbitrary process.
217 */
219 if (bgwprocno != -1)
220 {
221 /* reset bgwprocno first, before setting the latch */
223
224 /*
225 * Not acquiring ProcArrayLock here which is slightly icky. It's
226 * actually fine because procLatch isn't ever freed, so we just can
227 * potentially set the wrong process' (or no process') latch.
228 */
229 SetLatch(&GetPGProcByNumber(bgwprocno)->procLatch);
230 }
231
232 /*
233 * We count buffer allocation requests so that the bgwriter can estimate
234 * the rate of buffer consumption. Note that buffers recycled by a
235 * strategy object are intentionally not counted here.
236 */
238
239 /* Use the "clock sweep" algorithm to find a free buffer */
241 for (;;)
242 {
245
247
248 /*
249 * Check whether the buffer can be used and pin it if so. Do this
250 * using a CAS loop, to avoid having to lock the buffer header.
251 */
253 for (;;)
254 {
256
257 /*
258 * If the buffer is pinned or has a nonzero usage_count, we cannot
259 * use it; decrement the usage_count (unless pinned) and keep
260 * scanning.
261 */
262
264 {
265 if (--trycounter == 0)
266 {
267 /*
268 * We've scanned all the buffers without making any state
269 * changes, so all the buffers are pinned (or were when we
270 * looked at them). We could hope that someone will free
271 * one eventually, but it's probably better to fail than
272 * to risk getting stuck in an infinite loop.
273 */
274 elog(ERROR, "no unpinned buffers available");
275 }
276 break;
277 }
278
279 /* See equivalent code in PinBuffer() */
281 {
283 continue;
284 }
285
287 {
289
292 {
294 break;
295 }
296 }
297 else
298 {
299 /* pin the buffer if the CAS succeeds */
301
304 {
305 /* Found a usable buffer */
306 if (strategy != NULL)
307 AddBufferToRing(strategy, buf);
309
311
312 return buf;
313 }
314 }
315 }
316 }
317}
#define BUF_USAGECOUNT_ONE
static uint32 ClockSweepTick(void)
Definition freelist.c:110
static void AddBufferToRing(BufferAccessStrategy strategy, BufferDesc *buf)
Definition freelist.c:702
#define INT_ACCESS_ONCE(var)
Definition freelist.c:26
static BufferDesc * GetBufferFromRing(BufferAccessStrategy strategy, uint64 *buf_state)
Definition freelist.c:623
void SetLatch(Latch *latch)
Definition latch.c:290
#define GetPGProcByNumber(n)
Definition proc.h:504

References AddBufferToRing(), BufferStrategyControl::bgwprocno, BM_LOCKED, buf, BUF_REFCOUNT_ONE, BUF_STATE_GET_REFCOUNT, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_ONE, BufferDescriptorGetBuffer(), ClockSweepTick(), elog, ERROR, fb(), GetBufferDescriptor(), GetBufferFromRing(), GetPGProcByNumber, INT_ACCESS_ONCE, NBuffers, BufferStrategyControl::numBufferAllocs, pg_atomic_compare_exchange_u64(), pg_atomic_fetch_add_u32(), pg_atomic_read_u64(), SetLatch(), StrategyControl, TrackNewBufferPin(), unlikely, and WaitBufHdrUnlocked().

Referenced by GetVictimBuffer().

◆ StrategyNotifyBgWriter()

void StrategyNotifyBgWriter ( int  bgwprocno)

Definition at line 368 of file freelist.c.

369{
370 /*
371 * We acquire buffer_strategy_lock just to ensure that the store appears
372 * atomic to StrategyGetBuffer. The bgwriter should call this rather
373 * infrequently, so there's no performance penalty from being safe.
374 */
376 StrategyControl->bgwprocno = bgwprocno;
378}

References BufferStrategyControl::bgwprocno, BufferStrategyControl::buffer_strategy_lock, SpinLockAcquire(), SpinLockRelease(), and StrategyControl.

Referenced by BackgroundWriterMain().

◆ StrategyRejectBuffer()

bool StrategyRejectBuffer ( BufferAccessStrategy  strategy,
BufferDesc buf,
bool  from_ring 
)

Definition at line 752 of file freelist.c.

753{
754 /* We only do this in bulkread mode */
755 if (strategy->btype != BAS_BULKREAD)
756 return false;
757
758 /* Don't muck with behavior of normal buffer-replacement strategy */
759 if (!from_ring ||
760 strategy->buffers[strategy->current] != BufferDescriptorGetBuffer(buf))
761 return false;
762
763 /*
764 * Remove the dirty buffer from the ring; necessary to prevent infinite
765 * loop if all ring members are dirty.
766 */
767 strategy->buffers[strategy->current] = InvalidBuffer;
768
769 return true;
770}

References BAS_BULKREAD, BufferAccessStrategyData::btype, buf, BufferDescriptorGetBuffer(), BufferAccessStrategyData::buffers, BufferAccessStrategyData::current, fb(), and InvalidBuffer.

Referenced by GetVictimBuffer().

◆ StrategySyncStart()

int StrategySyncStart ( uint32 complete_passes,
uint32 num_buf_alloc 
)

Definition at line 331 of file freelist.c.

332{
333 uint32 nextVictimBuffer;
334 int result;
335
338 result = nextVictimBuffer % NBuffers;
339
340 if (complete_passes)
341 {
343
344 /*
345 * Additionally add the number of wraparounds that happened before
346 * completePasses could be incremented. C.f. ClockSweepTick().
347 */
348 *complete_passes += nextVictimBuffer / NBuffers;
349 }
350
351 if (num_buf_alloc)
352 {
354 }
356 return result;
357}
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition atomics.h:237
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition atomics.h:330
uint32 result

References BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::completePasses, fb(), NBuffers, BufferStrategyControl::nextVictimBuffer, BufferStrategyControl::numBufferAllocs, pg_atomic_exchange_u32(), pg_atomic_read_u32(), result, SpinLockAcquire(), SpinLockRelease(), and StrategyControl.

Referenced by BgBufferSync().

Variable Documentation

◆ StrategyControl

◆ StrategyCtlShmemCallbacks

const ShmemCallbacks StrategyCtlShmemCallbacks
Initial value:
= {
.request_fn = StrategyCtlShmemRequest,
}
static void StrategyCtlShmemRequest(void *arg)
Definition freelist.c:386
static void StrategyCtlShmemInit(void *arg)
Definition freelist.c:398

Definition at line 64 of file freelist.c.

64 {
65 .request_fn = StrategyCtlShmemRequest,
66 .init_fn = StrategyCtlShmemInit,
67};