[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-28 Thread git repository hosting
Module: xenomai-3
Branch: wip/dovetail
Commit: 497af95d240458e758685d940d4eec6a5a9a4388
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=497af95d240458e758685d940d4eec6a5a9a4388

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list for maintaining pages leads to pathological
execution times when releasing blocks obtained from huge heaps
(i.e. hundreds of megabytes). Rework the core to use an allocation
bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  424 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 259 insertions(+), 183 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..bd9ea47 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
-   int n, lastpgnum;
+   int lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -146,20 +154,18 @@ static void init_extent(void *base, struct shared_extent 
*extent)
 */
assert(lastpgnum >= 1);
 
-   /* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
-   extent->pagemap[n].type = page_free;
-   extent->pagemap[n].bcount = 0;
-   }
-
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
+   /* Mark all pages as free in the page map. */
+   memset(extent->pagemap, 0, lastpgnum * sizeof(struct page_entry));
 
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to align

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-08 Thread git repository hosting
Module: xenomai-3
Branch: wip/gpio
Commit: 75558b54e4efe3cc73b0cb040e489dd8615fb730
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=75558b54e4efe3cc73b0cb040e489dd8615fb730

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list for maintaining pages leads to pathological
execution times when releasing blocks obtained from huge heaps
(i.e. hundreds of megabytes). Rework the core to use an allocation
bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  424 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 259 insertions(+), 183 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..bd9ea47 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
-   int n, lastpgnum;
+   int lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -146,20 +154,18 @@ static void init_extent(void *base, struct shared_extent 
*extent)
 */
assert(lastpgnum >= 1);
 
-   /* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
-   extent->pagemap[n].type = page_free;
-   extent->pagemap[n].bcount = 0;
-   }
-
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
+   /* Mark all pages as free in the page map. */
+   memset(extent->pagemap, 0, lastpgnum * sizeof(struct page_entry));
 
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to alignment

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-08 Thread git repository hosting
Module: xenomai-3
Branch: stable-3.0.x
Commit: 75558b54e4efe3cc73b0cb040e489dd8615fb730
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=75558b54e4efe3cc73b0cb040e489dd8615fb730

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list for maintaining pages leads to pathological
execution times when releasing blocks obtained from huge heaps
(i.e. hundreds of megabytes). Rework the core to use an allocation
bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  424 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 259 insertions(+), 183 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..bd9ea47 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
-   int n, lastpgnum;
+   int lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -146,20 +154,18 @@ static void init_extent(void *base, struct shared_extent 
*extent)
 */
assert(lastpgnum >= 1);
 
-   /* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
-   extent->pagemap[n].type = page_free;
-   extent->pagemap[n].bcount = 0;
-   }
-
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
+   /* Mark all pages as free in the page map. */
+   memset(extent->pagemap, 0, lastpgnum * sizeof(struct page_entry));
 
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to align

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-08 Thread git repository hosting
Module: xenomai-3
Branch: next
Commit: 497af95d240458e758685d940d4eec6a5a9a4388
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=497af95d240458e758685d940d4eec6a5a9a4388

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list for maintaining pages leads to pathological
execution times when releasing blocks obtained from huge heaps
(i.e. hundreds of megabytes). Rework the core to use an allocation
bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  424 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 259 insertions(+), 183 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..bd9ea47 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
-   int n, lastpgnum;
+   int lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -146,20 +154,18 @@ static void init_extent(void *base, struct shared_extent 
*extent)
 */
assert(lastpgnum >= 1);
 
-   /* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
-   extent->pagemap[n].type = page_free;
-   extent->pagemap[n].bcount = 0;
-   }
-
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
+   /* Mark all pages as free in the page map. */
+   memset(extent->pagemap, 0, lastpgnum * sizeof(struct page_entry));
 
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to alignment) as

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-07 Thread git repository hosting
Module: xenomai-3
Branch: wip/heap-bitmap
Commit: f36e50b95dcc5a897bb8685eefb4a4077407cc66
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=f36e50b95dcc5a897bb8685eefb4a4077407cc66

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list for maintaining pages leads to pathological
execution times when releasing blocks obtained from huge heaps
(i.e. hundreds of megabytes). Rework the core to use an allocation
bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  424 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 259 insertions(+), 183 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..bd9ea47 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
-   int n, lastpgnum;
+   int lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -146,20 +154,18 @@ static void init_extent(void *base, struct shared_extent 
*extent)
 */
assert(lastpgnum >= 1);
 
-   /* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
-   extent->pagemap[n].type = page_free;
-   extent->pagemap[n].bcount = 0;
-   }
-
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
+   /* Mark all pages as free in the page map. */
+   memset(extent->pagemap, 0, lastpgnum * sizeof(struct page_entry));
 
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to al

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-06 Thread git repository hosting
Module: xenomai-3
Branch: wip/heap-bitmap
Commit: 1a01fe305302af8e1cfabb32bd5c0e60ac4f6d46
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=1a01fe305302af8e1cfabb32bd5c0e60ac4f6d46

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list for maintaining pages leads to pathological
execution times when releasing blocks obtained from huge heaps
(i.e. hundreds of megabytes). Rework the core to use an allocation
bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  418 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 253 insertions(+), 183 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..c897d69 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
-   int n, lastpgnum;
+   int lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -146,20 +154,18 @@ static void init_extent(void *base, struct shared_extent 
*extent)
 */
assert(lastpgnum >= 1);
 
-   /* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
-   extent->pagemap[n].type = page_free;
-   extent->pagemap[n].bcount = 0;
-   }
-
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
+   /* Mark all pages as free in the page map. */
+   memset(extent->pagemap, 0, lastpgnum * sizeof(struct page_entry));
 
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to al

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-06 Thread git repository hosting
Module: xenomai-3
Branch: wip/heap-bitmap
Commit: 5f317e3756a92bfbb86da0f46826da9fe626bc2d
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=5f317e3756a92bfbb86da0f46826da9fe626bc2d

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list for maintaining pages leads to pathological
execution times when releasing blocks obtained from huge heaps
(i.e. hundreds of megabytes). Rework the core to use an allocation
bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  411 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 251 insertions(+), 178 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..43aac70 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with future 
bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
int n, lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -147,19 +155,20 @@ static void init_extent(void *base, struct shared_extent 
*extent)
assert(lastpgnum >= 1);
 
/* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
+   for (n = 0; n <= lastpgnum; n++) {
extent->pagemap[n].type = page_free;
extent->pagemap[n].bcount = 0;
}
 
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
-
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to alignment) as busy,
+* we don't want to pick them since they don't map any actual
+* memory from th

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-06 Thread git repository hosting
Module: xenomai-3
Branch: wip/heap-bitmap
Commit: 4b6c4cce7debb28937ae914c12b89c5a68db11cd
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=4b6c4cce7debb28937ae914c12b89c5a68db11cd

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list leads to pathological execution times when releasing
blocks obtained from huge heaps (i.e. hundreds of megabytes). Rework
the core to use an allocation bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  411 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 251 insertions(+), 178 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..43aac70 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with future 
bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
int n, lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -147,19 +155,20 @@ static void init_extent(void *base, struct shared_extent 
*extent)
assert(lastpgnum >= 1);
 
/* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
+   for (n = 0; n <= lastpgnum; n++) {
extent->pagemap[n].type = page_free;
extent->pagemap[n].bcount = 0;
}
 
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
-
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to alignment) as busy,
+* we don't want to pick them since they don't map any actual
+* memory from the page pool.
+

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-06 Thread git repository hosting
Module: xenomai-3
Branch: wip/heap-bitmap
Commit: 8f3d0b1a0aac47b7b2a5f1b3b6e307a2aab9643c
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=8f3d0b1a0aac47b7b2a5f1b3b6e307a2aab9643c

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list leads to pathological execution times when releasing
blocks obtained from huge heaps (i.e. hundreds of megabytes). Rework
the core to use an allocation bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  411 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 251 insertions(+), 178 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..8b8156b 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with future 
bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
int n, lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -147,19 +155,20 @@ static void init_extent(void *base, struct shared_extent 
*extent)
assert(lastpgnum >= 1);
 
/* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
+   for (n = 0; n <= lastpgnum; n++) {
extent->pagemap[n].type = page_free;
extent->pagemap[n].bcount = 0;
}
 
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
-
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to alignment) as busy,
+* we don't want to pick them since they don't map any actual
+* memory from the page pool.
+

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-05 Thread git repository hosting
Module: xenomai-3
Branch: wip/heap-bitmap
Commit: 92650808fc2c3f19248a81987f1d327affbbb152
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=92650808fc2c3f19248a81987f1d327affbbb152

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list leads to pathological execution times when releasing
blocks obtained from huge heaps (i.e. hundreds of megabytes). Rework
the core to use an allocation bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  389 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 238 insertions(+), 169 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..557c540 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with future 
bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
int n, lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -147,19 +155,20 @@ static void init_extent(void *base, struct shared_extent 
*extent)
assert(lastpgnum >= 1);
 
/* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
+   for (n = 0; n <= lastpgnum; n++) {
extent->pagemap[n].type = page_free;
extent->pagemap[n].bcount = 0;
}
 
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
-
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to alignment) as busy,
+* we don't want to pick them since they don't map any actual
+* memory from the page pool.
+

[Xenomai-git] Philippe Gerum : copperplate/heapobj-pshared: introduce allocation bitmap

2016-06-05 Thread git repository hosting
Module: xenomai-3
Branch: wip/heap-bitmap
Commit: 72ea1bdc6a12839c10326daf59564c2a16768e0c
URL:
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=72ea1bdc6a12839c10326daf59564c2a16768e0c

Author: Philippe Gerum 
Date:   Fri Jun  3 10:00:38 2016 +0200

copperplate/heapobj-pshared: introduce allocation bitmap

Using a free list leads to pathological execution times when releasing
blocks obtained from huge heaps (i.e. hundreds of megabytes). Rework
the core to use an allocation bitmap instead.

---

 lib/copperplate/heapobj-pshared.c |  389 +
 lib/copperplate/internal.h|   18 +-
 2 files changed, 238 insertions(+), 169 deletions(-)

diff --git a/lib/copperplate/heapobj-pshared.c 
b/lib/copperplate/heapobj-pshared.c
index 8c5dac6..2186d7c 100644
--- a/lib/copperplate/heapobj-pshared.c
+++ b/lib/copperplate/heapobj-pshared.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -43,15 +44,7 @@
 #include "xenomai/init.h"
 #include "internal.h"
 
-#define HOBJ_PAGE_SHIFT9   /* 2^9 => 512 bytes */
-#define HOBJ_PAGE_SIZE (1U << HOBJ_PAGE_SHIFT)
-#define HOBJ_PAGE_MASK (~(HOBJ_PAGE_SIZE-1))
-#define HOBJ_PAGE_ALIGN(addr)  (((addr)+HOBJ_PAGE_SIZE-1)&HOBJ_PAGE_MASK)
-
-#define HOBJ_MINALIGNSZ (1U << 4) /* i.e. 16 bytes */
-#define HOBJ_MAXEXTSZ   (1U << 31) /* i.e. 2Gb */
-
-enum {
+enum { /* FIXME: page_free redundant with future 
bitmap */
page_free =0,
page_cont =1,
page_list =2
@@ -66,8 +59,9 @@ struct shared_extent {
struct holder link;
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 */
+   memoff_t bitmap;/* Offset of allocation bitmap */
+   int bitwords;   /* 32bit words in bitmap */
+   struct page_entry pagemap[0]; /* Start of page map */
 };
 
 /*
@@ -117,24 +111,38 @@ static inline size_t __align_to(size_t size, size_t al)
return ((size+al-1)&(~(al-1)));
 }
 
-static inline size_t get_pagemap_size(size_t h)
+static inline size_t get_pagemap_size(size_t h,
+ memoff_t *bmapoff, int *bmapwords)
 {
+   int nrpages = h >> HOBJ_PAGE_SHIFT, bitmapw;
+   size_t pagemapsz;
+
/*
 * 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.
+* length of the page mapping array followed by the allocation
+* bitmap. '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_MINALIGNSZ);
+   pagemapsz = __align_to(nrpages * sizeof(struct page_entry),
+  sizeof(uint32_t));
+   bitmapw =__align_to(nrpages, 32) / 32;
+   if (bmapoff)
+   *bmapoff = offsetof(struct shared_extent, pagemap) + pagemapsz;
+   if (bmapwords)
+   *bmapwords = bitmapw;
+
+   return __align_to(pagemapsz
+ + sizeof(struct shared_extent)
+ + bitmapw * sizeof(uint32_t),
+ HOBJ_MINALIGNSZ);
 }
 
 static void init_extent(void *base, struct shared_extent *extent)
 {
-   caddr_t freepage;
int n, lastpgnum;
+   uint32_t *p;
 
__holder_init_nocheck(base, &extent->link);
 
@@ -147,19 +155,20 @@ static void init_extent(void *base, struct shared_extent 
*extent)
assert(lastpgnum >= 1);
 
/* Mark each page as free in the page map. */
-   for (n = 0, freepage = __shref(base, extent->membase);
-n < lastpgnum; n++, freepage += HOBJ_PAGE_SIZE) {
-   *((memoff_t *)freepage) = __shoff(base, freepage) + 
HOBJ_PAGE_SIZE;
+   for (n = 0; n <= lastpgnum; n++) {
extent->pagemap[n].type = page_free;
extent->pagemap[n].bcount = 0;
}
 
-   *((memoff_t *)freepage) = 0;
-   extent->pagemap[lastpgnum].type = page_free;
-   extent->pagemap[lastpgnum].bcount = 0;
-
-   /* The first page starts the free list of a new extent. */
-   extent->freelist = extent->membase;
+   /* Clear the allocation bitmap. */
+   p = __shref(base, extent->bitmap);
+   memset(p, 0, extent->bitwords * sizeof(uint32_t));
+   /*
+* Mark the unused trailing bits (due to alignment) as busy,
+* we don't want to pick them since they don't map any actual
+* memory from the page pool.
+