1/*-------------------------------------------------------------------------
2 *
3 * freepage.h
4 * Management of page-organized free memory.
5 *
6 * Portions Copyright (c) 1996-2019, 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. */
21typedef struct FreePageSpanLeader FreePageSpanLeader;
22typedef struct FreePageBtree FreePageBtree;
23typedef 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. */
43relptr_declare(FreePageBtree, RelptrFreePageBtree);
44relptr_declare(FreePageManager, RelptrFreePageManager);
45relptr_declare(FreePageSpanLeader, RelptrFreePageSpanLeader);
46
47/* Everything we need in order to manage free pages (see freepage.c) */
48struct 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. */
92extern void FreePageManagerInitialize(FreePageManager *fpm, char *base);
93extern bool FreePageManagerGet(FreePageManager *fpm, Size npages,
94 Size *first_page);
95extern void FreePageManagerPut(FreePageManager *fpm, Size first_page,
96 Size npages);
97extern char *FreePageManagerDump(FreePageManager *fpm);
98
99#endif /* FREEPAGE_H */
100