[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: fix and sanitize extent management

2015-08-13 Thread git repository hosting
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

2015-08-15 Thread git repository hosting
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)