1 /*-------------------------------------------------------------------------
2  *
3  * freepage.h
4  *	  Management of page-organized free memory.
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * src/include/utils/freepage.h
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #ifndef FREEPAGE_H
15 #define FREEPAGE_H
16 
17 #include "storage/lwlock.h"
18 #include "utils/relptr.h"
19 
20 /* Forward declarations. */
21 typedef struct FreePageSpanLeader FreePageSpanLeader;
22 typedef struct FreePageBtree FreePageBtree;
23 typedef struct FreePageManager FreePageManager;
24 
25 /*
26  * PostgreSQL normally uses 8kB pages for most things, but many common
27  * architecture/operating system pairings use a 4kB page size for memory
28  * allocation, so we do that here also.
29  */
30 #define FPM_PAGE_SIZE			4096
31 
32 /*
33  * Each freelist except for the last contains only spans of one particular
34  * size.  Everything larger goes on the last one.  In some sense this seems
35  * like a waste since most allocations are in a few common sizes, but it
36  * means that small allocations can simply pop the head of the relevant list
37  * without needing to worry about whether the object we find there is of
38  * precisely the correct size (because we know it must be).
39  */
40 #define FPM_NUM_FREELISTS		129
41 
42 /* Define relative pointer types. */
43 relptr_declare(FreePageBtree, RelptrFreePageBtree);
44 relptr_declare(FreePageManager, RelptrFreePageManager);
45 relptr_declare(FreePageSpanLeader, RelptrFreePageSpanLeader);
46 
47 /* Everything we need in order to manage free pages (see freepage.c) */
48 struct FreePageManager
49 {
50 	RelptrFreePageManager self;
51 	RelptrFreePageBtree btree_root;
52 	RelptrFreePageSpanLeader btree_recycle;
53 	unsigned	btree_depth;
54 	unsigned	btree_recycle_count;
55 	Size		singleton_first_page;
56 	Size		singleton_npages;
57 	Size		contiguous_pages;
58 	bool		contiguous_pages_dirty;
59 	RelptrFreePageSpanLeader freelist[FPM_NUM_FREELISTS];
60 #ifdef FPM_EXTRA_ASSERTS
61 	/* For debugging only, pages put minus pages gotten. */
62 	Size		free_pages;
63 #endif
64 };
65 
66 /* Macros to convert between page numbers (expressed as Size) and pointers. */
67 #define fpm_page_to_pointer(base, page) \
68 	(AssertVariableIsOfTypeMacro(page, Size), \
69 	 (base) + FPM_PAGE_SIZE * (page))
70 #define fpm_pointer_to_page(base, ptr)		\
71 	(((Size) (((char *) (ptr)) - (base))) / FPM_PAGE_SIZE)
72 
73 /* Macro to convert an allocation size to a number of pages. */
74 #define fpm_size_to_pages(sz) \
75 	(((sz) + FPM_PAGE_SIZE - 1) / FPM_PAGE_SIZE)
76 
77 /* Macros to check alignment of absolute and relative pointers. */
78 #define fpm_pointer_is_page_aligned(base, ptr)		\
79 	(((Size) (((char *) (ptr)) - (base))) % FPM_PAGE_SIZE == 0)
80 #define fpm_relptr_is_page_aligned(base, relptr)		\
81 	((relptr).relptr_off % FPM_PAGE_SIZE == 0)
82 
83 /* Macro to find base address of the segment containing a FreePageManager. */
84 #define fpm_segment_base(fpm)	\
85 	(((char *) fpm) - fpm->self.relptr_off)
86 
87 /* Macro to access a FreePageManager's largest consecutive run of pages. */
88 #define fpm_largest(fpm) \
89 	(fpm->contiguous_pages)
90 
91 /* Functions to manipulate the free page map. */
92 extern void FreePageManagerInitialize(FreePageManager *fpm, char *base);
93 extern bool FreePageManagerGet(FreePageManager *fpm, Size npages,
94 				   Size *first_page);
95 extern void FreePageManagerPut(FreePageManager *fpm, Size first_page,
96 				   Size npages);
97 extern char *FreePageManagerDump(FreePageManager *fpm);
98 
99 #endif							/* FREEPAGE_H */
100