[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: fix and sanitize extent management
Module: xenomai-3 Branch: next Commit: 65f16f4a3f0d4de3be221bea6b4545b2b4d74321 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=65f16f4a3f0d4de3be221bea6b4545b2b4d74321 Author: Philippe Gerum Date: Wed Aug 12 18:27:22 2015 +0200 copperplate/heapobj-pshared: fix and sanitize extent management --- lib/copperplate/heapobj-pshared.c | 278 + lib/copperplate/internal.h|3 - 2 files changed, 159 insertions(+), 122 deletions(-) diff --git a/lib/copperplate/heapobj-pshared.c b/lib/copperplate/heapobj-pshared.c index 5fe899a..0df08c3 100644 --- a/lib/copperplate/heapobj-pshared.c +++ b/lib/copperplate/heapobj-pshared.c @@ -57,17 +57,17 @@ enum { page_list =2 }; -struct page_map { +struct page_entry { unsigned int type : 8;/* free, cont, list or log2 */ unsigned int bcount : 24; /* Number of active blocks. */ }; struct shared_extent { struct holder link; - memoff_t membase; /* Base address of the page array */ - memoff_t memlim;/* Memory limit of page array */ - memoff_t freelist; /* Head of the free page list */ - struct page_map pagemap[1]; /* Start of page map */ + memoff_t membase; /* Base offset of page array */ + memoff_t memlim;/* Offset limit of page array */ + memoff_t freelist; /* Head of free page list */ + struct page_entry pagemap[1]; /* Start of page map */ }; /* @@ -75,7 +75,7 @@ struct shared_extent { * additional session-wide information. */ struct session_heap { - struct shared_heap base; + struct shared_heap heap; int cpid; memoff_t maplen; struct hash_table catalog; @@ -91,6 +91,12 @@ struct session_heap { */ void *__main_heap; #define main_heap (*(struct session_heap *)__main_heap) +/* + * Base address for offset-based addressing, which is the start of + * the session heap since all memory objects are allocated from it, + * including other (sub-)heaps. + */ +#define main_base __main_heap /* A table of shared clusters for the session. */ struct hash_table *__main_catalog; @@ -100,10 +106,10 @@ struct sysgroup *__main_sysgroup; static struct heapobj main_pool; -#define __shoff(h, p) ((caddr_t)(p) - (caddr_t)(h)) -#define __shoff_check(h, p)((p) ? __shoff(h, p) : 0) -#define __shref(h, o) ((void *)((caddr_t)(h) + (o))) -#define __shref_check(h, o)((o) ? __shref(h, o) : NULL) +#define __shoff(b, p) ((caddr_t)(p) - (caddr_t)(b)) +#define __shoff_check(b, p)((p) ? __shoff(b, p) : 0) +#define __shref(b, o) ((void *)((caddr_t)(b) + (o))) +#define __shref_check(b, o)((o) ? __shref(b, o) : NULL) static inline size_t __align_to(size_t size, size_t al) { @@ -111,33 +117,39 @@ static inline size_t __align_to(size_t size, size_t al) return ((size+al-1)&(~(al-1))); } -static inline size_t internal_overhead(size_t hsize) +static inline size_t get_pagemap_size(size_t h) { - /* o = (h - o) * m / p + e - o * p = (h - o) * m + e * p - o * (p + m) = h * m + e * p - o = (h * m + e *p) / (p + m) - */ - return __align_to((sizeof(struct shared_extent) * HOBJ_PAGE_SIZE - + sizeof(struct page_map) * hsize) - / (HOBJ_PAGE_SIZE + sizeof(struct page_map)), HOBJ_PAGE_SIZE); + /* +* Return the size of the meta data required to map 'h' bytes +* of user memory in pages of HOBJ_PAGE_SIZE bytes. The meta +* data includes the length of the extent descriptor, plus the +* length of the page mapping array. 'h' must be a multiple of +* HOBJ_PAGE_SIZE on entry. +*/ + assert((h & ~HOBJ_PAGE_MASK) == 0); + return __align_to((h >> HOBJ_PAGE_SHIFT) * sizeof(struct page_entry) + + sizeof(struct shared_extent), HOBJ_PAGE_SIZE); } -static void init_extent(struct shared_heap *heap, struct shared_extent *extent) +static void init_extent(void *base, struct shared_extent *extent) { caddr_t freepage; int n, lastpgnum; - __holder_init_nocheck(heap, &extent->link); + __holder_init_nocheck(base, &extent->link); - /* The initial extent starts right after the header. */ - extent->membase = __shoff(heap, extent) + heap->hdrsize; - lastpgnum = heap->npages - 1; + lastpgnum = ((extent->memlim - extent->membase) >> HOBJ_PAGE_SHIFT) - 1; + /* +* An extent must contain at least two addressable pages to +* cope with allocation sizes between PAGESIZE and 2 * +* PAGESIZE. +*/ + assert(lastpgnum >= 1); /* Mark each page as free in the page map. */ - for (n = 0, freepage = __shref(heap, extent->membase); + for (n = 0, freepage = __shref(base, extent->membase); n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: fix and sanitize extent management
Module: xenomai-3 Branch: master Commit: 65f16f4a3f0d4de3be221bea6b4545b2b4d74321 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=65f16f4a3f0d4de3be221bea6b4545b2b4d74321 Author: Philippe Gerum Date: Wed Aug 12 18:27:22 2015 +0200 copperplate/heapobj-pshared: fix and sanitize extent management --- lib/copperplate/heapobj-pshared.c | 278 + lib/copperplate/internal.h|3 - 2 files changed, 159 insertions(+), 122 deletions(-) diff --git a/lib/copperplate/heapobj-pshared.c b/lib/copperplate/heapobj-pshared.c index 5fe899a..0df08c3 100644 --- a/lib/copperplate/heapobj-pshared.c +++ b/lib/copperplate/heapobj-pshared.c @@ -57,17 +57,17 @@ enum { page_list =2 }; -struct page_map { +struct page_entry { unsigned int type : 8;/* free, cont, list or log2 */ unsigned int bcount : 24; /* Number of active blocks. */ }; struct shared_extent { struct holder link; - memoff_t membase; /* Base address of the page array */ - memoff_t memlim;/* Memory limit of page array */ - memoff_t freelist; /* Head of the free page list */ - struct page_map pagemap[1]; /* Start of page map */ + memoff_t membase; /* Base offset of page array */ + memoff_t memlim;/* Offset limit of page array */ + memoff_t freelist; /* Head of free page list */ + struct page_entry pagemap[1]; /* Start of page map */ }; /* @@ -75,7 +75,7 @@ struct shared_extent { * additional session-wide information. */ struct session_heap { - struct shared_heap base; + struct shared_heap heap; int cpid; memoff_t maplen; struct hash_table catalog; @@ -91,6 +91,12 @@ struct session_heap { */ void *__main_heap; #define main_heap (*(struct session_heap *)__main_heap) +/* + * Base address for offset-based addressing, which is the start of + * the session heap since all memory objects are allocated from it, + * including other (sub-)heaps. + */ +#define main_base __main_heap /* A table of shared clusters for the session. */ struct hash_table *__main_catalog; @@ -100,10 +106,10 @@ struct sysgroup *__main_sysgroup; static struct heapobj main_pool; -#define __shoff(h, p) ((caddr_t)(p) - (caddr_t)(h)) -#define __shoff_check(h, p)((p) ? __shoff(h, p) : 0) -#define __shref(h, o) ((void *)((caddr_t)(h) + (o))) -#define __shref_check(h, o)((o) ? __shref(h, o) : NULL) +#define __shoff(b, p) ((caddr_t)(p) - (caddr_t)(b)) +#define __shoff_check(b, p)((p) ? __shoff(b, p) : 0) +#define __shref(b, o) ((void *)((caddr_t)(b) + (o))) +#define __shref_check(b, o)((o) ? __shref(b, o) : NULL) static inline size_t __align_to(size_t size, size_t al) { @@ -111,33 +117,39 @@ static inline size_t __align_to(size_t size, size_t al) return ((size+al-1)&(~(al-1))); } -static inline size_t internal_overhead(size_t hsize) +static inline size_t get_pagemap_size(size_t h) { - /* o = (h - o) * m / p + e - o * p = (h - o) * m + e * p - o * (p + m) = h * m + e * p - o = (h * m + e *p) / (p + m) - */ - return __align_to((sizeof(struct shared_extent) * HOBJ_PAGE_SIZE - + sizeof(struct page_map) * hsize) - / (HOBJ_PAGE_SIZE + sizeof(struct page_map)), HOBJ_PAGE_SIZE); + /* +* Return the size of the meta data required to map 'h' bytes +* of user memory in pages of HOBJ_PAGE_SIZE bytes. The meta +* data includes the length of the extent descriptor, plus the +* length of the page mapping array. 'h' must be a multiple of +* HOBJ_PAGE_SIZE on entry. +*/ + assert((h & ~HOBJ_PAGE_MASK) == 0); + return __align_to((h >> HOBJ_PAGE_SHIFT) * sizeof(struct page_entry) + + sizeof(struct shared_extent), HOBJ_PAGE_SIZE); } -static void init_extent(struct shared_heap *heap, struct shared_extent *extent) +static void init_extent(void *base, struct shared_extent *extent) { caddr_t freepage; int n, lastpgnum; - __holder_init_nocheck(heap, &extent->link); + __holder_init_nocheck(base, &extent->link); - /* The initial extent starts right after the header. */ - extent->membase = __shoff(heap, extent) + heap->hdrsize; - lastpgnum = heap->npages - 1; + lastpgnum = ((extent->memlim - extent->membase) >> HOBJ_PAGE_SHIFT) - 1; + /* +* An extent must contain at least two addressable pages to +* cope with allocation sizes between PAGESIZE and 2 * +* PAGESIZE. +*/ + assert(lastpgnum >= 1); /* Mark each page as free in the page map. */ - for (n = 0, freepage = __shref(heap, extent->membase); + for (n = 0, freepage = __shref(base, extent->membase); n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE)