1 /*-------------------------------------------------------------------------
4 * buffer manager initialization routines
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
13 *-------------------------------------------------------------------------
17 #include "storage/bufmgr.h"
18 #include "storage/buf_internals.h"
21 BufferDesc
*BufferDescriptors
;
23 int32
*PrivateRefCount
;
25 /* statistics counters */
26 long int ReadBufferCount
;
27 long int ReadLocalBufferCount
;
28 long int BufferHitCount
;
29 long int LocalBufferHitCount
;
30 long int BufferFlushCount
;
31 long int LocalBufferFlushCount
;
32 long int BufFileReadCount
;
33 long int BufFileWriteCount
;
38 * buffers live in a freelist and a lookup data structure.
42 * Two important notes. First, the buffer has to be
43 * available for lookup BEFORE an IO begins. Otherwise
44 * a second process trying to read the buffer will
45 * allocate its own copy and the buffer pool will
46 * become inconsistent.
49 * see freelist.c. A buffer cannot be replaced while in
50 * use either by data manager or during IO.
53 * Synchronization/Locking:
55 * IO_IN_PROGRESS -- this is a flag in the buffer descriptor.
56 * It must be set when an IO is initiated and cleared at
57 * the end of the IO. It is there to make sure that one
58 * process doesn't start to use a buffer while another is
59 * faulting it in. see WaitIO and related routines.
61 * refcount -- Counts the number of processes holding pins on a buffer.
62 * A buffer is pinned during IO and immediately after a BufferAlloc().
63 * Pins must be released before end of transaction.
65 * PrivateRefCount -- Each buffer also has a private refcount that keeps
66 * track of the number of times the buffer is pinned in the current
67 * process. This is used for two purposes: first, if we pin a
68 * a buffer more than once, we only need to change the shared refcount
69 * once, thus only lock the shared state once; second, when a transaction
70 * aborts, it should only unpin the buffers exactly the number of times it
71 * has pinned them, so that it will not blow away buffers of another
77 * Initialize shared buffer pool
79 * This is called once during shared-memory initialization (either in the
80 * postmaster, or in a standalone backend).
88 BufferDescriptors
= (BufferDesc
*)
89 ShmemInitStruct("Buffer Descriptors",
90 NBuffers
* sizeof(BufferDesc
), &foundDescs
);
92 BufferBlocks
= (char *)
93 ShmemInitStruct("Buffer Blocks",
94 NBuffers
* (Size
) BLCKSZ
, &foundBufs
);
96 if (foundDescs
|| foundBufs
)
98 /* both should be present or neither */
99 Assert(foundDescs
&& foundBufs
);
100 /* note: this path is only taken in EXEC_BACKEND case */
107 buf
= BufferDescriptors
;
110 * Initialize all the buffer headers.
112 for (i
= 0; i
< NBuffers
; buf
++, i
++)
114 CLEAR_BUFFERTAG(buf
->tag
);
116 buf
->usage_count
= 0;
118 buf
->wait_backend_pid
= 0;
120 SpinLockInit(&buf
->buf_hdr_lock
);
125 * Initially link all the buffers together as unused. Subsequent
126 * management of this list is done by freelist.c.
128 buf
->freeNext
= i
+ 1;
130 buf
->io_in_progress_lock
= LWLockAssign();
131 buf
->content_lock
= LWLockAssign();
134 /* Correct last entry of linked list */
135 BufferDescriptors
[NBuffers
- 1].freeNext
= FREENEXT_END_OF_LIST
;
138 /* Init other shared buffer-management stuff */
139 StrategyInitialize(!foundDescs
);
143 * Initialize access to shared buffer pool
145 * This is called during backend startup (whether standalone or under the
146 * postmaster). It sets up for this backend's access to the already-existing
149 * NB: this is called before InitProcess(), so we do not have a PGPROC and
150 * cannot do LWLockAcquire; hence we can't actually access stuff in
151 * shared memory yet. We are only initializing local data here.
152 * (See also InitBufferPoolBackend, over in bufmgr.c.)
155 InitBufferPoolAccess(void)
158 * Allocate and zero local arrays of per-buffer info.
160 PrivateRefCount
= (int32
*) calloc(NBuffers
, sizeof(int32
));
161 if (!PrivateRefCount
)
163 (errcode(ERRCODE_OUT_OF_MEMORY
),
164 errmsg("out of memory")));
170 * compute the size of shared memory for the buffer pool including
171 * data pages, buffer descriptors, hash tables, etc.
174 BufferShmemSize(void)
178 /* size of buffer descriptors */
179 size
= add_size(size
, mul_size(NBuffers
, sizeof(BufferDesc
)));
181 /* size of data pages */
182 size
= add_size(size
, mul_size(NBuffers
, BLCKSZ
));
184 /* size of stuff controlled by freelist.c */
185 size
= add_size(size
, StrategyShmemSize());