MemoryPageCache impl

Implements MemoryPageCache.

Summary
MemoryPageCache implImplements MemoryPageCache.
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 freepage_tExport type freepage_t into global namespace.
pagecache_impl_it
struct staticpage_tExport type staticpage_t into global namespace.
staticpage_tHeader of last allocated static memory page.
helper
INTERFACE_staticpagelistMacro dlist_IMPLEMENT generates dlist interface for staticpage_t.
alignedsize_staticpageReturns sizeof(staticpage_t) aligned to KONFIG_MEMALIGN.
lifetime
init_staticpageInitializes a staticpage_t as head of page and returns a pointer to it.
query
freepage_tHeader of free page located in pagecache_block_t.pageblock.
helper
INTERFACE_freepagelistMacro dlist_IMPLEMENT generates dlist interface for freepage_t.
pagecache_block_tStores information about a block of memory pages.
Variables
threadcontextThread which allocated the memory block.
pageblockSystem memory page where free pages are located.
next_blockUsed to store all allocated pagecache_block_t in a list.
next_freeblockUsed to store pagecache_block_t in a free list if this block contains free pages.
freepagelistList of free pages.
pagesizeSize of a single page stored in freepagelist.
usedpagecountCounts the number of allocated pages in use.
freelistidxIndex into <pagecache_impl_t.freeblocklist>.
pagecache_blockmap_t
lifetime
query
update
pagecache_block_t
static variables
constants
helper
slist_IMPLEMENT _blocklistMacro generates slist interface FCT_blocklist for pagecache_block_t.
slist_IMPLEMENT _freeblocklistMacro generates slist interface FCT_freeblocklist for pagecache_block_t.
arrayindex_pagecacheblockReturns an array index for an addr located in a pagecache_block_t.pageblock.
lifetime
initpageblock_pagecacheblockAllocates resources of pagecache_block_t stored in pagecache_block_t.pageblock.
freepageblock_pagecacheblockFrees resources of pagecache_block_t stored in pagecache_block_t.pageblock.
new_pagecacheblockAllocates a big block of memory and returns its description in pagecache_block_t.
free_pagecacheblockFrees pagecache_block_t.pageblock but keeps empty block structure.
alloc
pagecache_impl_t
static variables
s_pagecacheimpl_interfaceStores single instance of interface pagecache_it.
init
helper
findfreeblock_pagecacheimplFind empty <pageblock_block_t> on freelist and return it in freeblock.
allocblock_pagecacheimplAllocate new <pageblock_block_t> and add it to freelist.
freeblock_pagecacheimplFrees <pageblock_block_t> and removes it from freelist and blocklist.
lifetime
query
alloc
cache
test

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 freepage_t

typedef struct freepage_t freepage_t

Export type freepage_t into global namespace.

pagecache_impl_it

pagecache_it_DECLARE(pagecache_impl_it,
pagecache_impl_t)
Defines interface pagecache_impl_itsee pagecache_it_DECLARE.  The interface supports object type pagecache_impl_t and is compatible with pagecache_it.

struct staticpage_t

typedef struct staticpage_t staticpage_t

Export type staticpage_t into global namespace.

staticpage_t

struct staticpage_t

Header of last allocated static memory page.

Summary
helper
INTERFACE_staticpagelistMacro dlist_IMPLEMENT generates dlist interface for staticpage_t.
alignedsize_staticpageReturns sizeof(staticpage_t) aligned to KONFIG_MEMALIGN.
lifetime
init_staticpageInitializes a staticpage_t as head of page and returns a pointer to it.
query

helper

INTERFACE_staticpagelist

Macro dlist_IMPLEMENT generates dlist interface for staticpage_t.

alignedsize_staticpage

static inline size_t alignedsize_staticpage(void)

Returns sizeof(staticpage_t) aligned to KONFIG_MEMALIGN.

lifetime

init_staticpage

static inline void init_staticpage(staticpage_t **staticpage,
memblock_t *page)

Initializes a staticpage_t as head of page and returns a pointer to it.

(Unchecked) Precondition

  • page.size > sizeof(staticpage_t)

query

freepage_t

struct freepage_t

Header of free page located in pagecache_block_t.pageblock.

Summary
helper
INTERFACE_freepagelistMacro dlist_IMPLEMENT generates dlist interface for freepage_t.

helper

INTERFACE_freepagelist

Macro dlist_IMPLEMENT generates dlist interface for freepage_t.

pagecache_block_t

struct pagecache_block_t

Stores information about a block of memory pages.  This type allocates and frees such a block of contiguous memory pages.  It stores a reference to the first page and the size of all pages together.  It also manages allocation and releasing of pages cut out from the big memory block.

Summary
Variables
threadcontextThread which allocated the memory block.
pageblockSystem memory page where free pages are located.
next_blockUsed to store all allocated pagecache_block_t in a list.
next_freeblockUsed to store pagecache_block_t in a free list if this block contains free pages.
freepagelistList of free pages.
pagesizeSize of a single page stored in freepagelist.
usedpagecountCounts the number of allocated pages in use.
freelistidxIndex into <pagecache_impl_t.freeblocklist>.

Variables

threadcontext

threadcontext_t * threadcontext

Thread which allocated the memory block.

pageblock

vmpage_t pageblock

System memory page where free pages are located.  See also freepagelist.

next_block

dlist_node_t next_block

Used to store all allocated pagecache_block_t in a list.

next_freeblock

dlist_node_t next_freeblock

Used to store pagecache_block_t in a free list if this block contains free pages.

freepagelist

dlist_t freepagelist

List of free pages.  If this list is empty next_freeblock is not in use.

pagesize

size_t pagesize

Size of a single page stored in freepagelist.

usedpagecount

uint16_t usedpagecount

Counts the number of allocated pages in use.  If this value is 0 the whole block could be freed.

freelistidx

uint8_t freelistidx

Index into <pagecache_impl_t.freeblocklist>.

pagecache_blockmap_t

lifetime

query

update

pagecache_block_t

Summary
static variables
constants
helper
slist_IMPLEMENT _blocklistMacro generates slist interface FCT_blocklist for pagecache_block_t.
slist_IMPLEMENT _freeblocklistMacro generates slist interface FCT_freeblocklist for pagecache_block_t.
arrayindex_pagecacheblockReturns an array index for an addr located in a pagecache_block_t.pageblock.
lifetime
initpageblock_pagecacheblockAllocates resources of pagecache_block_t stored in pagecache_block_t.pageblock.
freepageblock_pagecacheblockFrees resources of pagecache_block_t stored in pagecache_block_t.pageblock.
new_pagecacheblockAllocates a big block of memory and returns its description in pagecache_block_t.
free_pagecacheblockFrees pagecache_block_t.pageblock but keeps empty block structure.
alloc

static variables

constants

helper

slist_IMPLEMENT _blocklist

Macro generates slist interface FCT_blocklist for pagecache_block_t.

slist_IMPLEMENT _freeblocklist

Macro generates slist interface FCT_freeblocklist for pagecache_block_t.

arrayindex_pagecacheblock

static inline size_t arrayindex_pagecacheblock(const void *addr)

Returns an array index for an addr located in a pagecache_block_t.pageblock.  It is used to access pagecache_blockmap_t.

lifetime

initpageblock_pagecacheblock

static inline int initpageblock_pagecacheblock(vmpage_t *pageblock,
size_t blocksize)

Allocates resources of pagecache_block_t stored in pagecache_block_t.pageblock.

freepageblock_pagecacheblock

static inline int freepageblock_pagecacheblock(vmpage_t *pageblock)

Frees resources of pagecache_block_t stored in pagecache_block_t.pageblock.

new_pagecacheblock

static int new_pagecacheblock(out pagesize_e pgsize,
pagecache_blockmap_t *blockmap)

Allocates a big block of memory and returns its description in pagecache_block_t.  The returned pagecache_block_t is allocated on the heap.

free_pagecacheblock

static int free_pagecacheblock(pagecache_block_t *block,
pagecache_blockmap_t *blockmap)

Frees pagecache_block_t.pageblock but keeps empty block structure.  Another call to new_pagecacheblock will reuse it.

alloc

pagecache_impl_t

Summary
static variables
s_pagecacheimpl_interfaceStores single instance of interface pagecache_it.
init
helper
findfreeblock_pagecacheimplFind empty <pageblock_block_t> on freelist and return it in freeblock.
allocblock_pagecacheimplAllocate new <pageblock_block_t> and add it to freelist.
freeblock_pagecacheimplFrees <pageblock_block_t> and removes it from freelist and blocklist.
lifetime
query
alloc
cache
test

static variables

s_pagecacheimpl_interface

static pagecache_impl_it s_pagecacheimpl_interface

Stores single instance of interface pagecache_it.

init

helper

findfreeblock_pagecacheimpl

static inline int findfreeblock_pagecacheimpl(pagecache_impl_t *pgcache,
pagesize_e pgsize,
pagecache_block_t **freeblock)

Find empty <pageblock_block_t> on freelist and return it in freeblock.  The freelist <pagecache_impl_t.freeblocklist> at index pgsize is searched.  All encountered <pageblock_block_t> which are empty are removed from the list.  If there is no empty block for the corresponding pgsize the error ESRCH is returned.

allocblock_pagecacheimpl

static inline int allocblock_pagecacheimpl(pagecache_impl_t *pgcache,
pagesize_e pgsize,
/*out*/pagecache_block_t **block)

Allocate new <pageblock_block_t> and add it to freelist.  The new block is returned in block if this value is not NULL.  The allocated block is inserted in freelist <pagecache_impl_t.freeblocklist> at index pgsize.  The allocated block is also inserted into list pagecache_impl_t.blocklist.  In case of error ENOMEM is returned.

freeblock_pagecacheimpl

static inline int freeblock_pagecacheimpl(pagecache_impl_t *pgcache,
pagecache_block_t *block)

Frees <pageblock_block_t> and removes it from freelist and blocklist.

lifetime

query

alloc

cache

test

Cache for virtual memory pages.
Implements MemoryPageCache.
typedef struct freepage_t freepage_t
Export type freepage_t into global namespace.
struct freepage_t
Header of free page located in pagecache_block_t.pageblock.
pagecache_it_DECLARE(pagecache_impl_it,
pagecache_impl_t)
typedef struct staticpage_t staticpage_t
Export type staticpage_t into global namespace.
struct staticpage_t
Header of last allocated static memory page.
#define dlist_IMPLEMENT(
   _fsuffix,
   object_t,
   nodeprefix
) typedef dlist_iterator_t iteratortype##_fsuffix ; typedef object_t * iteratedtype##_fsuffix ; static inline int initfirst##_fsuffix##iterator(dlist_iterator_t * iter, dlist_t * list) __attribute__ ((always_inline)) ; static inline int initlast##_fsuffix##iterator(dlist_iterator_t * iter, dlist_t * list) __attribute__ ((always_inline)) ; static inline int free##_fsuffix##iterator(dlist_iterator_t * iter) __attribute__ ((always_inline)) ; static inline bool next##_fsuffix##iterator(dlist_iterator_t * iter, object_t ** node) __attribute__ ((always_inline)) ; static inline bool prev##_fsuffix##iterator(dlist_iterator_t * iter, object_t ** node) __attribute__ ((always_inline)) ; static inline void init##_fsuffix(dlist_t * list) __attribute__ ((always_inline)) ; static inline int free##_fsuffix(dlist_t * list, struct typeadapt_t * typeadp) __attribute__ ((always_inline)) ; static inline int isempty##_fsuffix(const dlist_t * list) __attribute__ ((always_inline)) ; static inline object_t * first##_fsuffix(const dlist_t * list) __attribute__ ((always_inline)) ; static inline object_t * last##_fsuffix(const dlist_t * list) __attribute__ ((always_inline)) ; static inline object_t * next##_fsuffix(object_t * node) __attribute__ ((always_inline)) ; static inline object_t * prev##_fsuffix(object_t * node) __attribute__ ((always_inline)) ; static inline bool isinlist##_fsuffix(object_t * node) __attribute__ ((always_inline)) ; static inline void insertfirst##_fsuffix(dlist_t * list, object_t * new_node) __attribute__ ((always_inline)) ; static inline void insertlast##_fsuffix(dlist_t * list, object_t * new_node) __attribute__ ((always_inline)) ; static inline void insertafter##_fsuffix(dlist_t * list, object_t * prev_node, object_t * new_node) __attribute__ ((always_inline)) ; static inline void insertbefore##_fsuffix(object_t* next_node, object_t * new_node) __attribute__ ((always_inline)) ; static inline int removefirst##_fsuffix(dlist_t * list, object_t ** removed_node) __attribute__ ((always_inline)) ; static inline int removelast##_fsuffix(dlist_t * list, object_t ** removed_node) __attribute__ ((always_inline)) ; static inline int remove##_fsuffix(dlist_t * list, object_t * node) __attribute__ ((always_inline)) ; static inline void replacenode##_fsuffix(dlist_t * list, object_t * newnode, object_t * oldnode) __attribute__ ((always_inline)) ; static inline int removeall##_fsuffix(dlist_t * list, struct typeadapt_t * typeadp) __attribute__ ((always_inline)) ; static inline void transfer##_fsuffix(dlist_t * tolist, dlist_t * fromlist) __attribute__ ((always_inline)) ; static inline uint16_t nodeoffset##_fsuffix(void) __attribute__ ((always_inline)) ; static inline uint16_t nodeoffset##_fsuffix(void) { static_assert(UINT16_MAX > (uintptr_t) & (((object_t*)0)->nodeprefix next), "offset fits in uint16_t") ; return (uint16_t) (uintptr_t) & (((object_t*)0)->nodeprefix next) ; } static inline dlist_node_t * asnode##_fsuffix(object_t * object) { static_assert(&(((object_t*)0)->nodeprefix next) == (dlist_node_t**)((uintptr_t)nodeoffset##_fsuffix()), "correct type") ; static_assert(&(((object_t*)0)->nodeprefix prev) == (dlist_node_t**)(nodeoffset##_fsuffix() + sizeof(dlist_node_t*)), "correct type and offset") ; return (dlist_node_t *) ((uintptr_t)object + nodeoffset##_fsuffix()) ; } static inline object_t * asobject##_fsuffix(dlist_node_t * node) { return (object_t *) ((uintptr_t)node - nodeoffset##_fsuffix()) ; } static inline object_t * asobjectnull##_fsuffix(dlist_node_t * node) { return node ? (object_t *) ((uintptr_t)node - nodeoffset##_fsuffix()) : 0 ; } static inline void init##_fsuffix(dlist_t * list) { init_dlist(list) ; } static inline int free##_fsuffix(dlist_t * list, struct typeadapt_t * typeadp) { return free_dlist(list, nodeoffset##_fsuffix(), typeadp) ; } static inline int isempty##_fsuffix(const dlist_t * list) { return isempty_dlist(list) ; } static inline object_t * first##_fsuffix(const dlist_t * list) { return asobjectnull##_fsuffix(first_dlist(list)) ; } static inline object_t * last##_fsuffix(const dlist_t * list) { return asobjectnull##_fsuffix(last_dlist(list)) ; } static inline object_t * next##_fsuffix(object_t * node) { return asobject##_fsuffix(next_dlist(asnode##_fsuffix(node))) ; } static inline object_t * prev##_fsuffix(object_t * node) { return asobject##_fsuffix(prev_dlist(asnode##_fsuffix(node))) ; } static inline bool isinlist##_fsuffix(object_t * node) { return isinlist_dlist(asnode##_fsuffix(node)) ; } static inline void insertfirst##_fsuffix(dlist_t * list, object_t * new_node) { insertfirst_dlist(list, asnode##_fsuffix(new_node)) ; } static inline void insertlast##_fsuffix(dlist_t * list, object_t * new_node) { insertlast_dlist(list, asnode##_fsuffix(new_node)) ; } static inline void insertafter##_fsuffix(dlist_t * list, object_t * prev_node, object_t * new_node) { insertafter_dlist(list, asnode##_fsuffix(prev_node), asnode##_fsuffix(new_node)) ; } static inline void insertbefore##_fsuffix(object_t * next_node, object_t * new_node) { insertbefore_dlist(asnode##_fsuffix(next_node), asnode##_fsuffix(new_node)) ; } static inline int removefirst##_fsuffix(dlist_t * list, object_t ** removed_node) { int err = removefirst_dlist(list, (dlist_node_t**)removed_node) ; if (!err) *removed_node = asobject##_fsuffix(*(dlist_node_t**)removed_node) ; return err ; } static inline int removelast##_fsuffix(dlist_t * list, object_t ** removed_node) { int err = removelast_dlist(list, (dlist_node_t**)removed_node) ; if (!err) *removed_node = asobject##_fsuffix(*(dlist_node_t**)removed_node) ; return err ; } static inline int remove##_fsuffix(dlist_t * list, object_t * node) { return remove_dlist(list, asnode##_fsuffix(node)) ; } static inline void replacenode##_fsuffix(dlist_t * list, object_t * newnode, object_t * oldnode) { replacenode_dlist(list, asnode##_fsuffix(newnode), asnode##_fsuffix(oldnode)) ; } static inline int removeall##_fsuffix(dlist_t * list, struct typeadapt_t * typeadp) { return removeall_dlist(list, nodeoffset##_fsuffix(), typeadp) ; } static inline void transfer##_fsuffix(dlist_t * tolist, dlist_t * fromlist) { transfer_dlist(tolist, fromlist) ; } static inline int initfirst##_fsuffix##iterator(dlist_iterator_t * iter, dlist_t * list) { return initfirst_dlistiterator(iter, list) ; } static inline int initlast##_fsuffix##iterator(dlist_iterator_t * iter, dlist_t * list) { return initlast_dlistiterator(iter, list) ; } static inline int free##_fsuffix##iterator(dlist_iterator_t * iter) { return free_dlistiterator(iter) ; } static inline bool next##_fsuffix##iterator(dlist_iterator_t * iter, object_t ** node) { bool isNext = next_dlistiterator(iter, (dlist_node_t**)node) ; if (isNext) *node = asobject##_fsuffix(*(dlist_node_t**)node) ; return isNext ; } static inline bool prev##_fsuffix##iterator(dlist_iterator_t * iter, object_t ** node) { bool isNext = prev_dlistiterator(iter, (dlist_node_t**)node) ; if (isNext) *node = asobject##_fsuffix(*(dlist_node_t**)node) ; return isNext ; }
Implements dlist_t.dlist_IMPLEMENT.
static inline size_t alignedsize_staticpage(void)
Returns sizeof(staticpage_t) aligned to KONFIG_MEMALIGN.
#define KONFIG_MEMALIGN 4
Alignment of allocated memory.
static inline void init_staticpage(staticpage_t **staticpage,
memblock_t *page)
Initializes a staticpage_t as head of page and returns a pointer to it.
vmpage_t pageblock
System memory page where free pages are located.
struct pagecache_block_t
Stores information about a block of memory pages.
threadcontext_t * threadcontext
Thread which allocated the memory block.
dlist_node_t next_block
Used to store all allocated pagecache_block_t in a list.
dlist_node_t next_freeblock
Used to store pagecache_block_t in a free list if this block contains free pages.
dlist_t freepagelist
List of free pages.
size_t pagesize
Size of a single page stored in freepagelist.
uint16_t usedpagecount
Counts the number of allocated pages in use.
uint8_t freelistidx
Index into pagecache_impl_t.freeblocklist.
static inline size_t arrayindex_pagecacheblock(const void *addr)
Returns an array index for an addr located in a pagecache_block_t.pageblock.
static inline int initpageblock_pagecacheblock(vmpage_t *pageblock,
size_t blocksize)
Allocates resources of pagecache_block_t stored in pagecache_block_t.pageblock.
static inline int freepageblock_pagecacheblock(vmpage_t *pageblock)
Frees resources of pagecache_block_t stored in pagecache_block_t.pageblock.
static int new_pagecacheblock(out pagesize_e pgsize,
pagecache_blockmap_t *blockmap)
Allocates a big block of memory and returns its description in pagecache_block_t.
static int free_pagecacheblock(pagecache_block_t *block,
pagecache_blockmap_t *blockmap)
Frees pagecache_block_t.pageblock but keeps empty block structure.
static pagecache_impl_it s_pagecacheimpl_interface
Stores single instance of interface pagecache_it.
struct pagecache_it
Interface which allows to allocate and relase pages of memory.
static inline int findfreeblock_pagecacheimpl(pagecache_impl_t *pgcache,
pagesize_e pgsize,
pagecache_block_t **freeblock)
Find empty pageblock_block_t on freelist and return it in freeblock.
static inline int allocblock_pagecacheimpl(pagecache_impl_t *pgcache,
pagesize_e pgsize,
/*out*/pagecache_block_t **block)
Allocate new pageblock_block_t and add it to freelist.
static inline int freeblock_pagecacheimpl(pagecache_impl_t *pgcache,
pagecache_block_t *block)
Frees pageblock_block_t and removes it from freelist and blocklist.
#define pagecache_it_DECLARE(
   declared_it,
   pagecache_t
) typedef struct declared_it declared_it ; struct declared_it { int (*allocpage) (pagecache_t * pgcache, uint8_t pgsize, /*out*/struct memblock_t * page) ; int (*releasepage) (pagecache_t * pgcache, struct memblock_t * page) ; size_t (*sizeallocated) (const pagecache_t * pgcache) ; int (*allocstatic) (pagecache_t * pgcache, size_t bytesize, /*out*/struct memblock_t * memblock) ; int (*freestatic) (pagecache_t * pgcache, struct memblock_t * memblock) ; size_t (*sizestatic) (const pagecache_t * pgcache) ; int (*emptycache) (pagecache_t * pgcache) ; } ;
Implements pagecache_it.pagecache_it_DECLARE.
struct { struct dlist_node_t * last ; } blocklist
A list of pagecache_block_t.
Close