Management of free memory pages.

This is intended as infrastructure for a full-fledged allocator for
dynamic shared memory.  The interface looks a bit like a real
allocator, but only supports allocating and freeing memory in
multiples of the 4kB page size.  Further, to free memory, you must
know the size of the span you wish to free, in pages.  While these are
make it unsuitable as an allocator in and of itself, it still serves
as very useful scaffolding for a full-fledged allocator.

Robert Haas and Thomas Munro.  This code is mostly the same as my 2014
submission, but Thomas fixed quite a few bugs and made some changes to
the interface.

Discussion: CA+TgmobkeWptGwiNa+SGFWsTLzTzD-CeLz0KcE-y6LFgoUus4A@mail.gmail.com
Discussion: CAEepm=1z5WLuNoJ80PaCvz6EtG9dN0j-KuHcHtU6QEfcPP5-qA@mail.gmail.com
This commit is contained in:
Robert Haas 2016-12-02 12:03:30 -05:00
parent fbc1c12a94
commit 13e14a78ea
4 changed files with 1993 additions and 1 deletions

View File

@ -12,6 +12,6 @@ subdir = src/backend/utils/mmgr
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
OBJS = aset.o mcxt.o portalmem.o
OBJS = aset.o freepage.o mcxt.o portalmem.o
include $(top_srcdir)/src/backend/common.mk

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
/*-------------------------------------------------------------------------
*
* freepage.h
* Management of page-organized free memory.
*
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/utils/freepage.h
*
*-------------------------------------------------------------------------
*/
#ifndef FREEPAGE_H
#define FREEPAGE_H
#include "storage/lwlock.h"
#include "utils/relptr.h"
/* Forward declarations. */
typedef struct FreePageSpanLeader FreePageSpanLeader;
typedef struct FreePageBtree FreePageBtree;
typedef struct FreePageManager FreePageManager;
/*
* PostgreSQL normally uses 8kB pages for most things, but many common
* architecture/operating system pairings use a 4kB page size for memory
* allocation, so we do that here also.
*/
#define FPM_PAGE_SIZE 4096
/*
* Each freelist except for the last contains only spans of one particular
* size. Everything larger goes on the last one. In some sense this seems
* like a waste since most allocations are in a few common sizes, but it
* means that small allocations can simply pop the head of the relevant list
* without needing to worry about whether the object we find there is of
* precisely the correct size (because we know it must be).
*/
#define FPM_NUM_FREELISTS 129
/* Define relative pointer types. */
relptr_declare(FreePageBtree, RelptrFreePageBtree);
relptr_declare(FreePageManager, RelptrFreePageManager);
relptr_declare(FreePageSpanLeader, RelptrFreePageSpanLeader);
/* Everything we need in order to manage free pages (see freepage.c) */
struct FreePageManager
{
RelptrFreePageManager self;
RelptrFreePageBtree btree_root;
RelptrFreePageSpanLeader btree_recycle;
unsigned btree_depth;
unsigned btree_recycle_count;
Size singleton_first_page;
Size singleton_npages;
Size contiguous_pages;
bool contiguous_pages_dirty;
RelptrFreePageSpanLeader freelist[FPM_NUM_FREELISTS];
#ifdef FPM_EXTRA_ASSERTS
/* For debugging only, pages put minus pages gotten. */
Size free_pages;
#endif
};
/* Macros to convert between page numbers (expressed as Size) and pointers. */
#define fpm_page_to_pointer(base, page) \
(AssertVariableIsOfTypeMacro(page, Size), \
(base) + FPM_PAGE_SIZE * (page))
#define fpm_pointer_to_page(base, ptr) \
(((Size) (((char *) (ptr)) - (base))) / FPM_PAGE_SIZE)
/* Macro to convert an allocation size to a number of pages. */
#define fpm_size_to_pages(sz) \
(((sz) + FPM_PAGE_SIZE - 1) / FPM_PAGE_SIZE)
/* Macros to check alignment of absolute and relative pointers. */
#define fpm_pointer_is_page_aligned(base, ptr) \
(((Size) (((char *) (ptr)) - (base))) % FPM_PAGE_SIZE == 0)
#define fpm_relptr_is_page_aligned(base, relptr) \
((relptr).relptr_off % FPM_PAGE_SIZE == 0)
/* Macro to find base address of the segment containing a FreePageManager. */
#define fpm_segment_base(fpm) \
(((char *) fpm) - fpm->self.relptr_off)
/* Macro to access a FreePageManager's largest consecutive run of pages. */
#define fpm_largest(fpm) \
(fpm->contiguous_pages)
/* Functions to manipulate the free page map. */
extern void FreePageManagerInitialize(FreePageManager *fpm, char *base);
extern bool FreePageManagerGet(FreePageManager *fpm, Size npages,
Size *first_page);
extern void FreePageManagerPut(FreePageManager *fpm, Size first_page,
Size npages);
extern char *FreePageManagerDump(FreePageManager *fpm);
#endif /* FREEPAGE_H */

View File

@ -726,6 +726,13 @@ Form_pg_user_mapping
FormatNode
FreeBlockNumberArray
FreeListData
FreePageBtree
FreePageBtreeHeader
FreePageBtreeInternalKey
FreePageBtreeLeafKey
FreePageBtreeSearchResult
FreePageManager
FreePageSpanLeader
FromCharDateMode
FromExpr
FuncCall