Implements MemoryPageCache.
MemoryPageCache impl | Implements MemoryPageCache. |
Copyright | This program is free software. |
Files | |
C-kern/ | Header file MemoryPageCache. |
C-kern/ | Implementation file MemoryPageCache impl. |
Types | |
struct freepage_t | Export type freepage_t into global namespace. |
pagecache_impl_it | |
struct staticpage_t | Export type staticpage_t into global namespace. |
staticpage_t | Header of last allocated static memory page. |
helper | |
INTERFACE_staticpagelist | Macro dlist_IMPLEMENT generates dlist interface for staticpage_t. |
alignedsize_staticpage | Returns sizeof(staticpage_t) aligned to KONFIG_MEMALIGN. |
lifetime | |
init_staticpage | Initializes a staticpage_t as head of page and returns a pointer to it. |
query | |
freepage_t | Header of free page located in pagecache_block_t.pageblock. |
helper | |
INTERFACE_freepagelist | Macro dlist_IMPLEMENT generates dlist interface for freepage_t. |
pagecache_block_t | Stores information about a block of memory pages. |
Variables | |
threadcontext | Thread which allocated the memory block. |
pageblock | System memory page where free pages are located. |
next_block | Used to store all allocated pagecache_block_t in a list. |
next_freeblock | Used to store pagecache_block_t in a free list if this block contains free pages. |
freepagelist | List of free pages. |
pagesize | Size of a single page stored in freepagelist. |
usedpagecount | Counts the number of allocated pages in use. |
freelistidx | Index into <pagecache_impl_t.freeblocklist>. |
pagecache_blockmap_t | |
lifetime | |
query | |
update | |
pagecache_block_t | |
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 | Returns an array index for an addr located in a pagecache_block_t.pageblock. |
lifetime | |
initpageblock_pagecacheblock | Allocates resources of pagecache_block_t stored in pagecache_block_t.pageblock. |
freepageblock_pagecacheblock | Frees resources of pagecache_block_t stored in pagecache_block_t.pageblock. |
new_pagecacheblock | Allocates a big block of memory and returns its description in pagecache_block_t. |
free_pagecacheblock | Frees pagecache_block_t.pageblock but keeps empty block structure. |
alloc | |
pagecache_impl_t | |
static variables | |
s_pagecacheimpl_interface | Stores single instance of interface pagecache_it. |
init | |
helper | |
findfreeblock_pagecacheimpl | Find empty <pageblock_block_t> on freelist and return it in freeblock. |
allocblock_pagecacheimpl | Allocate new <pageblock_block_t> and add it to freelist. |
freeblock_pagecacheimpl | Frees <pageblock_block_t> and removes it from freelist and blocklist. |
lifetime | |
query | |
alloc | |
cache | |
test |
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.
© 2013 Jörg Seebohn
Header file MemoryPageCache.
Implementation file MemoryPageCache impl.
typedef struct freepage_t freepage_t
Export type freepage_t into global namespace.
pagecache_it_DECLARE( pagecache_impl_it, pagecache_impl_t )
Defines interface pagecache_impl_it | see pagecache_it_DECLARE. The interface supports object type pagecache_impl_t and is compatible with pagecache_it. |
typedef struct staticpage_t staticpage_t
Export type staticpage_t into global namespace.
struct staticpage_t
Header of last allocated static memory page.
helper | |
INTERFACE_staticpagelist | Macro dlist_IMPLEMENT generates dlist interface for staticpage_t. |
alignedsize_staticpage | Returns sizeof(staticpage_t) aligned to KONFIG_MEMALIGN. |
lifetime | |
init_staticpage | Initializes a staticpage_t as head of page and returns a pointer to it. |
query |
Macro dlist_IMPLEMENT generates dlist interface for staticpage_t.
static inline size_t alignedsize_staticpage( void )
Returns sizeof(staticpage_t) aligned to KONFIG_MEMALIGN.
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.
struct freepage_t
Header of free page located in pagecache_block_t.pageblock.
helper | |
INTERFACE_freepagelist | Macro dlist_IMPLEMENT generates dlist interface for freepage_t. |
Macro dlist_IMPLEMENT generates dlist interface for freepage_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.
Variables | |
threadcontext | Thread which allocated the memory block. |
pageblock | System memory page where free pages are located. |
next_block | Used to store all allocated pagecache_block_t in a list. |
next_freeblock | Used to store pagecache_block_t in a free list if this block contains free pages. |
freepagelist | List of free pages. |
pagesize | Size of a single page stored in freepagelist. |
usedpagecount | Counts the number of allocated pages in use. |
freelistidx | Index into <pagecache_impl_t.freeblocklist>. |
vmpage_t pageblock
System memory page where free pages are located. See also freepagelist.
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. If this list is empty next_freeblock is not in use.
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 | Returns an array index for an addr located in a pagecache_block_t.pageblock. |
lifetime | |
initpageblock_pagecacheblock | Allocates resources of pagecache_block_t stored in pagecache_block_t.pageblock. |
freepageblock_pagecacheblock | Frees resources of pagecache_block_t stored in pagecache_block_t.pageblock. |
new_pagecacheblock | Allocates a big block of memory and returns its description in pagecache_block_t. |
free_pagecacheblock | Frees pagecache_block_t.pageblock but keeps empty block structure. |
alloc |
Macro generates slist interface FCT_blocklist for pagecache_block_t.
Macro generates slist interface FCT_freeblocklist for pagecache_block_t.
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.
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. The returned pagecache_block_t is allocated on the heap.
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.
static variables | |
s_pagecacheimpl_interface | Stores single instance of interface pagecache_it. |
init | |
helper | |
findfreeblock_pagecacheimpl | Find empty <pageblock_block_t> on freelist and return it in freeblock. |
allocblock_pagecacheimpl | Allocate new <pageblock_block_t> and add it to freelist. |
freeblock_pagecacheimpl | Frees <pageblock_block_t> and removes it from freelist and blocklist. |
lifetime | |
query | |
alloc | |
cache | |
test |
static pagecache_impl_it s_pagecacheimpl_interface
Stores single instance of interface pagecache_it.
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.
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.
Export type freepage_t into global namespace.
typedef struct freepage_t freepage_t
Header of free page located in pagecache_block_t.pageblock.
struct freepage_t
pagecache_it_DECLARE( pagecache_impl_it, pagecache_impl_t )
Export type staticpage_t into global namespace.
typedef struct staticpage_t staticpage_t
Header of last allocated static memory page.
struct staticpage_t
Implements dlist_t.dlist_IMPLEMENT.
#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 ; }
Returns sizeof(staticpage_t) aligned to KONFIG_MEMALIGN.
static inline size_t alignedsize_staticpage( void )
Alignment of allocated memory.
#define KONFIG_MEMALIGN 4
Initializes a staticpage_t as head of page and returns a pointer to it.
static inline void init_staticpage( staticpage_t ** staticpage, memblock_t * page )
System memory page where free pages are located.
vmpage_t pageblock
Stores information about a block of memory pages.
struct pagecache_block_t
Thread which allocated the memory block.
threadcontext_t * threadcontext
Used to store all allocated pagecache_block_t in a list.
dlist_node_t next_block
Used to store pagecache_block_t in a free list if this block contains free pages.
dlist_node_t next_freeblock
List of free pages.
dlist_t freepagelist
Size of a single page stored in freepagelist.
size_t pagesize
Counts the number of allocated pages in use.
uint16_t usedpagecount
Index into pagecache_impl_t.freeblocklist.
uint8_t freelistidx
Returns an array index for an addr located in a pagecache_block_t.pageblock.
static inline size_t arrayindex_pagecacheblock( const void * addr )
Allocates resources of pagecache_block_t stored in pagecache_block_t.pageblock.
static inline int initpageblock_pagecacheblock( vmpage_t * pageblock, size_t blocksize )
Frees resources of pagecache_block_t stored in pagecache_block_t.pageblock.
static inline int freepageblock_pagecacheblock( vmpage_t * pageblock )
Allocates a big block of memory and returns its description in pagecache_block_t.
static int new_pagecacheblock( out pagesize_e pgsize, pagecache_blockmap_t * blockmap )
Frees pagecache_block_t.pageblock but keeps empty block structure.
static int free_pagecacheblock( pagecache_block_t * block, pagecache_blockmap_t * blockmap )
Stores single instance of interface pagecache_it.
static pagecache_impl_it s_pagecacheimpl_interface
Interface which allows to allocate and relase pages of memory.
struct pagecache_it
Find empty pageblock_block_t on freelist and return it in freeblock.
static inline int findfreeblock_pagecacheimpl( pagecache_impl_t * pgcache, pagesize_e pgsize, pagecache_block_t ** freeblock )
Allocate new pageblock_block_t and add it to freelist.
static inline int allocblock_pagecacheimpl( pagecache_impl_t * pgcache, pagesize_e pgsize, /*out*/pagecache_block_t ** block )
Frees pageblock_block_t and removes it from freelist and blocklist.
static inline int freeblock_pagecacheimpl( pagecache_impl_t * pgcache, pagecache_block_t * block )
Implements pagecache_it.pagecache_it_DECLARE.
#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) ; } ;
A list of pagecache_block_t.
struct { struct dlist_node_t * last ; } blocklist