MemoryPageCache

Cache for virtual memory pages.

Virtual memory pages are allocated in big chunks with help of init_vmpage.  This component makes calling into the operating system unnecessary every time you need a new page or want ot free one.

It offers pages of size 4096 bytes no matter of the page size of the operating system.

Other page sizes could be added supported if necessary.

Summary
MemoryPageCacheCache for virtual memory pages.
CopyrightThis program is free software.
Files
C-kern/api/memory/pagecache_impl.hHeader file MemoryPageCache.
C-kern/memory/pagecache_impl.cImplementation file MemoryPageCache impl.
Types
struct pagecache_impl_tExport pagecache_impl_t into global namespace.
struct pagecache_block_tExport opaque type pagecache_block_t into global namespace.
struct pagecache_blockmap_tExport type pagecache_blockmap_t into global namespace.
Functions
test
unittest_memory_pagecacheimplTest pagecache_impl_t functionality.
pagecache_impl_tAllocates and frees virtual memory pages and caches them.
blocklistA list of pagecache_block_t.
freelistAn array of list of allocated blocks which contain free pages.
staticpagelistA list of static memory blocks.
sizeallocatedNumber of allocated bytes.
sizestaticNumber of allocated bytes from static memory.
init
initthread_pagecacheimplCalls init_pagecacheimpl and adds interface pagecache_it to object.
freethread_pagecacheimplCalls free_pagecacheimpl with for object pointer in pagecache_t.
lifetime
pagecache_impl_FREEStatic initializer.
init_pagecacheimplPreallocates at least 1MB of memory and initializes pgcache.
free_pagecacheimplFrees all allocated memory pages even if they are in use.
query
sizeallocated_pagecacheimplReturns the sum of the size of all allocated pages.
sizestatic_pagecacheimplReturns wize of memory allocated with <allocstatic>.
isfree_pagecacheimplReturns true if pgcache equals pagecache_impl_FREE.
alloc
allocpage_pagecacheimplAllocates a single memory page of size pgsize.
releasepage_pagecacheimplReleases a single memory page.
allocstatic_pagecacheimplAllocates static memory which should live as long as pgcache.
freestatic_pagecacheimplFrees static memory.
cache
emptycache_pagecacheimplReleases all unused memory blocks back to the operating system.
pagecache_blockmap_tA simple shared hash map which maps an index pagecache_block_t.
config
pagecache_blockmap_ARRAYSIZEStatic configuration of number of bytes used for the hash table.
lifetime
pagecache_blockmap_FREEStatic initializer.
init_pagecacheblockmapAllocates a shared hash table of size pagecache_blockmap_FREE.
free_pagecacheblockmapFrees allocated hash table.

Copyright

This program is free software.  You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

Author

© 2013 Jörg Seebohn

Files

C-kern/api/memory/pagecache_impl.h

Header file MemoryPageCache.

C-kern/memory/pagecache_impl.c

Implementation file MemoryPageCache impl.

Types

struct pagecache_impl_t

typedef struct pagecache_impl_t pagecache_impl_t

Export pagecache_impl_t into global namespace.

struct pagecache_block_t

typedef struct pagecache_block_t pagecache_block_t

Export opaque type pagecache_block_t into global namespace.  This type stores information about a large block of memory of at least 1MB.

struct pagecache_blockmap_t

typedef struct pagecache_blockmap_t pagecache_blockmap_t

Export type pagecache_blockmap_t into global namespace.  It serves as hashtable for a set of pagecache_block_t.  The hashtable is shared between all pagecache_impl_t.

Functions

test

unittest_memory_pagecacheimpl

int unittest_memory_pagecacheimpl(void)

Test pagecache_impl_t functionality.

pagecache_impl_t

struct pagecache_impl_t

Allocates and frees virtual memory pages and caches them.  The pagecache_impl_t allocates always blocks of memory pages pagecache_block_t.  Every pagecache_block_t maintains a list of free pages of the same size.  For every pagesize a new pagecache_block_t is allocated.  If several pagecache_block_t are allocated and one of them is not used at all it is returned to the operating system.

TODO: To prevent fragmentation of large blocks introduce page lifetime (long, short lifetime, ...).  This helps to place longer living pages on one big block and short living pages on another.  Blocks with pages with short lifetime can be reclaimed faster.

Summary
blocklistA list of pagecache_block_t.
freelistAn array of list of allocated blocks which contain free pages.
staticpagelistA list of static memory blocks.
sizeallocatedNumber of allocated bytes.
sizestaticNumber of allocated bytes from static memory.
init
initthread_pagecacheimplCalls init_pagecacheimpl and adds interface pagecache_it to object.
freethread_pagecacheimplCalls free_pagecacheimpl with for object pointer in pagecache_t.
lifetime
pagecache_impl_FREEStatic initializer.
init_pagecacheimplPreallocates at least 1MB of memory and initializes pgcache.
free_pagecacheimplFrees all allocated memory pages even if they are in use.
query
sizeallocated_pagecacheimplReturns the sum of the size of all allocated pages.
sizestatic_pagecacheimplReturns wize of memory allocated with <allocstatic>.
isfree_pagecacheimplReturns true if pgcache equals pagecache_impl_FREE.
alloc
allocpage_pagecacheimplAllocates a single memory page of size pgsize.
releasepage_pagecacheimplReleases a single memory page.
allocstatic_pagecacheimplAllocates static memory which should live as long as pgcache.
freestatic_pagecacheimplFrees static memory.
cache
emptycache_pagecacheimplReleases all unused memory blocks back to the operating system.

blocklist

struct { struct dlist_node_t * last ; } blocklist

A list of pagecache_block_t.  This list contains all allocated blocks and serves to free all allocated blocks.  Objects of type pagecache_block_t are managed on the memory heap and are not part of the block of the allocated pages.

freelist

An array of list of allocated blocks which contain free pages.  A single large block contains only pages of one size.  Different blocks serve different sizes.  Therefore every page size has its own free list.  This my be changed for example by using the the “buddy memory allocation” technique.

staticpagelist

struct { struct dlist_node_t * last ; } staticpagelist

A list of static memory blocks.  Functions allocstatic_pagecacheimpl and freestatic_pagecacheimpl could change this list.

sizeallocated

size_t sizeallocated

Number of allocated bytes.  This number is incremented by every call to allocpage_pagecacheimpl and decremented by every call to releasepage_pagecacheimpl.

sizestatic

size_t sizestatic

Number of allocated bytes from static memory.  Value is incremented by every call to allocstatic_pagecacheimpl and decremented by every call to freestatic_pagecacheimpl.

init

initthread_pagecacheimpl

int initthread_pagecacheimpl(/*out*/struct pagecache_t *pagecache)

Calls init_pagecacheimpl and adds interface pagecache_it to object.  This function is called from <init_threadcontext>.

freethread_pagecacheimpl

int freethread_pagecacheimpl(struct pagecache_t *pagecache)

Calls free_pagecacheimpl with for object pointer in pagecache_t.  This function is called from <free_threadcontext>.

lifetime

pagecache_impl_FREE

#define pagecache_impl_FREE { { 0 }, { { 0 } }, { 0 }, 0, 0 }

Static initializer.

init_pagecacheimpl

int init_pagecacheimpl(/*out*/pagecache_impl_t *pgcache)

Preallocates at least 1MB of memory and initializes pgcache.

free_pagecacheimpl

int free_pagecacheimpl(pagecache_impl_t *pgcache)

Frees all allocated memory pages even if they are in use.  All allocated memory pages are returned to the operating system.  Make sure that every component has called releasepage_pagecacheimpl before this function is called.  Or that allocated pages are never used after calling this function.  In not all memory has been freed the error ENOTEMPTY is returned but memory is freed nevertheless.

query

sizeallocated_pagecacheimpl

size_t sizeallocated_pagecacheimpl(const pagecache_impl_t *pgcache)

Returns the sum of the size of all allocated pages.  Static memory is also allocated with help of allocpage_pagecacheimpl.

sizestatic_pagecacheimpl

size_t sizestatic_pagecacheimpl(const pagecache_impl_t *pgcache)

Returns wize of memory allocated with <allocstatic>.

isfree_pagecacheimpl

bool isfree_pagecacheimpl(const pagecache_impl_t *pgcache)

Returns true if pgcache equals pagecache_impl_FREE.

alloc

allocpage_pagecacheimpl

int allocpage_pagecacheimpl(pagecache_impl_t *pgcache,
uint8_t pgsize,
/*out*/struct memblock_t *page)

Allocates a single memory page of size pgsize.  The page is aligned to its own size.

releasepage_pagecacheimpl

int releasepage_pagecacheimpl(pagecache_impl_t *pgcache,
struct memblock_t *page)

Releases a single memory page.  It is kept in the cache and only returned to the operating system if a big chunk of memory is not in use.  After return page is set to <memblock_FREE>.  Calling this function with page set to <memblock_FREE> does nothing.

allocstatic_pagecacheimpl

int allocstatic_pagecacheimpl(pagecache_impl_t *pgcache,
size_t bytesize,
/*out*/struct memblock_t *memblock)

Allocates static memory which should live as long as pgcache.  These blocks can only be freed in the reverse order they hae been allocated.  The size of memory is set in bytes with parameter bytesize.  The allocated memory block (aligned to KONFIG_MEMALIGN) is returned in memblock.  In case of no memory ENOMEM is returned.  The size of the block if restricted to 128 bytes.  Calling this function increases sizeallocated_pagecacheimpl or not if bytesize bytes fits on a previously allocated page.

freestatic_pagecacheimpl

int freestatic_pagecacheimpl(pagecache_impl_t *pgcache,
struct memblock_t *memblock)

Frees static memory.  If this function is not called in the reverse order of the call sequence of allocstatic_pagecacheimpl the value EINVAL is returned and nothing is done.  After return memblock is set to <memblock_FREE>.  Calling this function with memblock set to <memblock_FREE> does nothing.

cache

emptycache_pagecacheimpl

int emptycache_pagecacheimpl(pagecache_impl_t *pgcache)

Releases all unused memory blocks back to the operating system.

pagecache_blockmap_t

struct pagecache_blockmap_t

A simple shared hash map which maps an index pagecache_block_t.  The array size (table size) is static which allows for efficient access without rwlock_t or any other type of locks.  Atomic operations to read and write pagecache_block_t.threadcontext ensure that an entry is used by only one thread.

Use pagecache_blockmap_ARRAYSIZE to configure the static size of the array.

Summary
config
pagecache_blockmap_ARRAYSIZEStatic configuration of number of bytes used for the hash table.
lifetime
pagecache_blockmap_FREEStatic initializer.
init_pagecacheblockmapAllocates a shared hash table of size pagecache_blockmap_FREE.
free_pagecacheblockmapFrees allocated hash table.

config

pagecache_blockmap_ARRAYSIZE

#define pagecache_blockmap_ARRAYSIZE (2*1024*1024)

Static configuration of number of bytes used for the hash table.  The number of supported pagecache_block_t is fixed cause only one entry per hash bucket is supported with no overflow handling. pagecache_blockmap_t is considered to be implemented in hardware.

lifetime

pagecache_blockmap_FREE

#define pagecache_blockmap_FREE { 0, 0, 0, 0 }

Static initializer.

init_pagecacheblockmap

int init_pagecacheblockmap(/*out*/pagecache_blockmap_t *blockmap)

Allocates a shared hash table of size pagecache_blockmap_FREE.

free_pagecacheblockmap

int free_pagecacheblockmap(pagecache_blockmap_t *blockmap)

Frees allocated hash table.  Make sure that no pagecache_block_t is in use.

Cache for virtual memory pages.
Implements MemoryPageCache.
typedef struct pagecache_impl_t pagecache_impl_t
Export pagecache_impl_t into global namespace.
struct pagecache_impl_t
Allocates and frees virtual memory pages and caches them.
typedef struct pagecache_block_t pagecache_block_t
Export opaque type pagecache_block_t into global namespace.
struct pagecache_block_t
Stores information about a block of memory pages.
typedef struct pagecache_blockmap_t pagecache_blockmap_t
Export type pagecache_blockmap_t into global namespace.
struct pagecache_blockmap_t
A simple shared hash map which maps an index pagecache_block_t.
int unittest_memory_pagecacheimpl(void)
Test pagecache_impl_t functionality.
struct { struct dlist_node_t * last ; } blocklist
A list of pagecache_block_t.
struct { struct dlist_node_t * last ; } staticpagelist
A list of static memory blocks.
size_t sizeallocated
Number of allocated bytes.
size_t sizestatic
Number of allocated bytes from static memory.
int initthread_pagecacheimpl(/*out*/struct pagecache_t *pagecache)
Calls init_pagecacheimpl and adds interface pagecache_it to object.
int init_pagecacheimpl(/*out*/pagecache_impl_t *pgcache)
Preallocates at least 1MB of memory and initializes pgcache.
struct pagecache_it
Interface which allows to allocate and relase pages of memory.
int freethread_pagecacheimpl(struct pagecache_t *pagecache)
Calls free_pagecacheimpl with for object pointer in pagecache_t.
int free_pagecacheimpl(pagecache_impl_t *pgcache)
Frees all allocated memory pages even if they are in use.
iobj_DECLARE(pagecache_t,
pagecache)
Uses iobj_DECLARE to declare interfaceable object.
#define pagecache_impl_FREE { { 0 }, { { 0 } }, { 0 }, 0, 0 }
Static initializer.
size_t sizeallocated_pagecacheimpl(const pagecache_impl_t *pgcache)
Returns the sum of the size of all allocated pages.
size_t sizestatic_pagecacheimpl(const pagecache_impl_t *pgcache)
Returns wize of memory allocated with allocstatic.
bool isfree_pagecacheimpl(const pagecache_impl_t *pgcache)
Returns true if pgcache equals pagecache_impl_FREE.
int allocpage_pagecacheimpl(pagecache_impl_t *pgcache,
uint8_t pgsize,
/*out*/struct memblock_t *page)
Allocates a single memory page of size pgsize.
int releasepage_pagecacheimpl(pagecache_impl_t *pgcache,
struct memblock_t *page)
Releases a single memory page.
int allocstatic_pagecacheimpl(pagecache_impl_t *pgcache,
size_t bytesize,
/*out*/struct memblock_t *memblock)
Allocates static memory which should live as long as pgcache.
int freestatic_pagecacheimpl(pagecache_impl_t *pgcache,
struct memblock_t *memblock)
Frees static memory.
int emptycache_pagecacheimpl(pagecache_impl_t *pgcache)
Releases all unused memory blocks back to the operating system.
#define pagecache_blockmap_ARRAYSIZE (2*1024*1024)
Static configuration of number of bytes used for the hash table.
#define pagecache_blockmap_FREE { 0, 0, 0, 0 }
Static initializer.
int init_pagecacheblockmap(/*out*/pagecache_blockmap_t *blockmap)
Allocates a shared hash table of size pagecache_blockmap_FREE.
int free_pagecacheblockmap(pagecache_blockmap_t *blockmap)
Frees allocated hash table.
#define init_vmpage(
   vmpage,
   size_in_bytes
) (init2_vmpage((vmpage), (size_in_bytes), accessmode_RDWR|accessmode_PRIVATE))
Implements vmpage_t.init_vmpage.
#define KONFIG_MEMALIGN 4
Alignment of allocated memory.
threadcontext_t * threadcontext
Thread which allocated the memory block.
Close