Commit f033b4f3 authored by Rusty Russell's avatar Rusty Russell

More cleanups where get_bit_pair should be used instead of

get_page_state.
Combine alloc_get_pages and alloc_from_bitmap.
Fix error in alloc_init (valgrind found uninitialized mem)
parent e6737e85
...@@ -143,14 +143,14 @@ void alloc_init(void *pool, unsigned long poolsize) ...@@ -143,14 +143,14 @@ void alloc_init(void *pool, unsigned long poolsize)
mh = first_mheader(pool, poolsize); mh = first_mheader(pool, poolsize);
/* len covers all page states, plus the metaheader. */ /* Mark all page states FREE, and all of metaheader bitmap which takes
len = (char *)(mh + 1) - (char *)pool; * rest of first page. */
/* Mark all page states FREE */ len = align_up(pool_offset(pool, mh + 1), getpagesize());
BUILD_ASSERT(FREE == 0); BUILD_ASSERT(FREE == 0);
memset(pool, 0, len); memset(pool, 0, len);
/* metaheader len takes us up to next page boundary. */ /* Set up metalen */
mh->metalen = align_up(len, getpagesize()) - len; mh->metalen = len - pool_offset(pool, mh + 1);
/* Mark the pagestate and metadata page(s) allocated. */ /* Mark the pagestate and metadata page(s) allocated. */
set_page_state(pool, 0, TAKEN_START); set_page_state(pool, 0, TAKEN_START);
...@@ -158,8 +158,11 @@ void alloc_init(void *pool, unsigned long poolsize) ...@@ -158,8 +158,11 @@ void alloc_init(void *pool, unsigned long poolsize)
set_page_state(pool, i, TAKEN); set_page_state(pool, i, TAKEN);
} }
/* Two bits per element, representing page states. Returns -1 on fail. */ /* Two bits per element, representing page states. Returns 0 on fail.
static long alloc_from_bitmap(uint8_t *bits, unsigned long elems, * off is used to allocate from subpage bitmaps, which use the first 2
* bits as the type, so the real bitmap is offset by 1. */
static unsigned long alloc_from_bitmap(uint8_t *bits, unsigned long off,
unsigned long elems,
unsigned long want, unsigned long align) unsigned long want, unsigned long align)
{ {
long i; long i;
...@@ -168,7 +171,7 @@ static long alloc_from_bitmap(uint8_t *bits, unsigned long elems, ...@@ -168,7 +171,7 @@ static long alloc_from_bitmap(uint8_t *bits, unsigned long elems,
free = 0; free = 0;
/* We allocate from far end, to increase ability to expand metadata. */ /* We allocate from far end, to increase ability to expand metadata. */
for (i = elems - 1; i >= 0; i--) { for (i = elems - 1; i >= 0; i--) {
switch (get_bit_pair(bits, i)) { switch (get_bit_pair(bits, off+i)) {
case FREE: case FREE:
if (++free >= want) { if (++free >= want) {
unsigned long j; unsigned long j;
...@@ -177,10 +180,10 @@ static long alloc_from_bitmap(uint8_t *bits, unsigned long elems, ...@@ -177,10 +180,10 @@ static long alloc_from_bitmap(uint8_t *bits, unsigned long elems,
if (align && i % align) if (align && i % align)
continue; continue;
set_bit_pair(bits, off+i, TAKEN_START);
for (j = i+1; j < i + want; j++) for (j = i+1; j < i + want; j++)
set_bit_pair(bits, j, TAKEN); set_bit_pair(bits, off+j, TAKEN);
set_bit_pair(bits, i, TAKEN_START); return off+i;
return i;
} }
break; break;
case SPECIAL: case SPECIAL:
...@@ -191,44 +194,14 @@ static long alloc_from_bitmap(uint8_t *bits, unsigned long elems, ...@@ -191,44 +194,14 @@ static long alloc_from_bitmap(uint8_t *bits, unsigned long elems,
} }
} }
return -1; return 0;
} }
static unsigned long alloc_get_pages(void *pool, unsigned long poolsize, static unsigned long alloc_get_pages(void *pool, unsigned long poolsize,
unsigned long pages, unsigned long align) unsigned long pages, unsigned long align)
{ {
long i; return alloc_from_bitmap(pool, 0, poolsize / getpagesize(), pages,
unsigned long free; align / getpagesize());
free = 0;
/* We allocate from far end, to increase ability to expand metadata. */
for (i = poolsize / getpagesize() - 1; i >= 0; i--) {
switch (get_page_state(pool, i)) {
case FREE:
if (++free >= pages) {
unsigned long j, addr;
addr = (unsigned long)pool + i * getpagesize();
/* They might ask for multi-page alignment. */
if (addr % align)
continue;
for (j = i+1; j < i + pages; j++)
set_page_state(pool, j, TAKEN);
set_page_state(pool, i, TAKEN_START);
return i;
}
break;
case SPECIAL:
case TAKEN_START:
case TAKEN:
free = 0;
break;
}
}
return 0;
} }
/* Offset to metadata is at end of page. */ /* Offset to metadata is at end of page. */
...@@ -252,39 +225,43 @@ static unsigned long sub_page_alloc(void *pool, unsigned long page, ...@@ -252,39 +225,43 @@ static unsigned long sub_page_alloc(void *pool, unsigned long page,
unsigned long size, unsigned long align) unsigned long size, unsigned long align)
{ {
uint8_t *bits = get_page_metadata(pool, page); uint8_t *bits = get_page_metadata(pool, page);
long i; unsigned long i;
/* TAKEN at end means a bitwise alloc. */ /* TAKEN at start means a bitwise alloc. */
assert(get_bit_pair(bits, getpagesize()/BITMAP_GRANULARITY-1) == TAKEN); assert(get_bit_pair(bits, 0) == BITMAP);
/* Our bits are the same as the page bits. */ /* We use a standart bitmap, but offset because of that BITMAP
i = alloc_from_bitmap(bits, SUBPAGE_METAOFF/BITMAP_GRANULARITY, * header. */
i = alloc_from_bitmap(bits, 1, SUBPAGE_METAOFF/BITMAP_GRANULARITY,
div_up(size, BITMAP_GRANULARITY), div_up(size, BITMAP_GRANULARITY),
align / BITMAP_GRANULARITY); align / BITMAP_GRANULARITY);
/* Can't allocate? */ /* Can't allocate? */
if (i < 0) if (i == 0)
return 0; return 0;
return page*getpagesize() + i*BITMAP_GRANULARITY; /* i-1 because of the header. */
return page*getpagesize() + (i-1)*BITMAP_GRANULARITY;
} }
static uint8_t *alloc_metaspace(struct metaheader *mh, unsigned long bytes) static uint8_t *alloc_metaspace(struct metaheader *mh, unsigned long bytes,
enum sub_metadata_type type)
{ {
uint8_t *meta = (uint8_t *)(mh + 1); uint8_t *meta = (uint8_t *)(mh + 1);
unsigned long free = 0, len; unsigned long free = 0, len;
long i; unsigned long i;
/* TAKEN tags end a subpage alloc. */ /* TAKEN tags end a subpage alloc. */
for (i = mh->metalen * CHAR_BIT / BITS_PER_PAGE - 1; i >= 0; i -= len) { for (i = 0; i < mh->metalen * CHAR_BIT / BITS_PER_PAGE; i += len) {
switch (get_bit_pair(meta, i)) { switch (get_bit_pair(meta, i)) {
case FREE: case FREE:
len = 1; len = 1;
free++; free++;
if (free == bytes * CHAR_BIT / BITS_PER_PAGE) { if (free == bytes * CHAR_BIT / BITS_PER_PAGE) {
/* TAKEN marks end of metablock. */ /* Mark this as a bitmap. */
set_page_state(meta, i + free - 1, TAKEN); set_bit_pair(meta, i - free + 1, type);
return meta + i / (CHAR_BIT / BITS_PER_PAGE); return meta + (i - free + 1)
/ (CHAR_BIT / BITS_PER_PAGE);
} }
break; break;
case BITMAP: case BITMAP:
...@@ -302,13 +279,13 @@ static uint8_t *alloc_metaspace(struct metaheader *mh, unsigned long bytes) ...@@ -302,13 +279,13 @@ static uint8_t *alloc_metaspace(struct metaheader *mh, unsigned long bytes)
/* We need this many bytes of metadata. */ /* We need this many bytes of metadata. */
static uint8_t *new_metadata(void *pool, unsigned long poolsize, static uint8_t *new_metadata(void *pool, unsigned long poolsize,
unsigned long bytes) unsigned long bytes, enum sub_metadata_type type)
{ {
struct metaheader *mh, *newmh; struct metaheader *mh, *newmh;
unsigned long page; unsigned long page;
for (mh = first_mheader(pool,poolsize); mh; mh = next_mheader(pool,mh)){ for (mh = first_mheader(pool,poolsize); mh; mh = next_mheader(pool,mh)){
uint8_t *meta = alloc_metaspace(mh, bytes); uint8_t *meta = alloc_metaspace(mh, bytes, type);
if (meta) if (meta)
return meta; return meta;
...@@ -331,7 +308,7 @@ static uint8_t *new_metadata(void *pool, unsigned long poolsize, ...@@ -331,7 +308,7 @@ static uint8_t *new_metadata(void *pool, unsigned long poolsize,
BUILD_ASSERT(FREE == 0); BUILD_ASSERT(FREE == 0);
memset((char *)pool + nextpage, 0, getpagesize()); memset((char *)pool + nextpage, 0, getpagesize());
mh->metalen += getpagesize(); mh->metalen += getpagesize();
return alloc_metaspace(mh, bytes); return alloc_metaspace(mh, bytes, type);
} }
/* No metadata left at all? */ /* No metadata left at all? */
...@@ -349,7 +326,7 @@ static uint8_t *new_metadata(void *pool, unsigned long poolsize, ...@@ -349,7 +326,7 @@ static uint8_t *new_metadata(void *pool, unsigned long poolsize,
newmh->next = mh->next; newmh->next = mh->next;
mh->next = pool_offset(pool, newmh); mh->next = pool_offset(pool, newmh);
return alloc_metaspace(newmh, bytes); return alloc_metaspace(newmh, bytes, type);
} }
static void alloc_free_pages(void *pool, unsigned long pagenum) static void alloc_free_pages(void *pool, unsigned long pagenum)
...@@ -383,7 +360,7 @@ static unsigned long alloc_sub_page(void *pool, unsigned long poolsize, ...@@ -383,7 +360,7 @@ static unsigned long alloc_sub_page(void *pool, unsigned long poolsize,
return 0; return 0;
/* Get metadata for page. */ /* Get metadata for page. */
metadata = new_metadata(pool, poolsize, BITMAP_METALEN); metadata = new_metadata(pool, poolsize, BITMAP_METALEN, BITMAP);
if (!metadata) { if (!metadata) {
alloc_free_pages(pool, i); alloc_free_pages(pool, i);
return 0; return 0;
...@@ -412,12 +389,13 @@ static bool clean_empty_subpages(void *pool, unsigned long poolsize) ...@@ -412,12 +389,13 @@ static bool clean_empty_subpages(void *pool, unsigned long poolsize)
continue; continue;
meta = get_page_metadata(pool, i); meta = get_page_metadata(pool, i);
for (j = 0; j < SUBPAGE_METAOFF/BITMAP_GRANULARITY; j++) /* Skip the header (first bit of metadata). */
if (get_page_state(meta, j) != FREE) for (j = 1; j < SUBPAGE_METAOFF/BITMAP_GRANULARITY+1; j++)
if (get_bit_pair(meta, j) != FREE)
break; break;
/* So, is this page totally empty? */ /* So, is this page totally empty? */
if (j == SUBPAGE_METAOFF/BITMAP_GRANULARITY) { if (j == SUBPAGE_METAOFF/BITMAP_GRANULARITY+1) {
set_page_state(pool, i, FREE); set_page_state(pool, i, FREE);
progress = true; progress = true;
} }
...@@ -518,10 +496,13 @@ static void subpage_free(void *pool, unsigned long pagenum, void *free) ...@@ -518,10 +496,13 @@ static void subpage_free(void *pool, unsigned long pagenum, void *free)
off /= BITMAP_GRANULARITY; off /= BITMAP_GRANULARITY;
set_page_state(metadata, off++, FREE); /* Offset by one because first bit is used for header. */
off++;
set_bit_pair(metadata, off++, FREE);
while (off < SUBPAGE_METAOFF / BITMAP_GRANULARITY while (off < SUBPAGE_METAOFF / BITMAP_GRANULARITY
&& get_page_state(metadata, off) == TAKEN) && get_bit_pair(metadata, off) == TAKEN)
set_page_state(metadata, off++, FREE); set_bit_pair(metadata, off++, FREE);
} }
void alloc_free(void *pool, unsigned long poolsize, void *free) void alloc_free(void *pool, unsigned long poolsize, void *free)
...@@ -581,15 +562,15 @@ static bool check_subpage(void *pool, unsigned long poolsize, ...@@ -581,15 +562,15 @@ static bool check_subpage(void *pool, unsigned long poolsize,
if (!is_metadata_page(pool, poolsize, *mhoff / getpagesize())) if (!is_metadata_page(pool, poolsize, *mhoff / getpagesize()))
return false; return false;
/* Marker at end of subpage allocation is "taken" */ /* Header at start of subpage allocation */
if (get_bit_pair((uint8_t *)pool + *mhoff, if (get_bit_pair((uint8_t *)pool + *mhoff, 0) != BITMAP)
getpagesize()/BITMAP_GRANULARITY - 1) != TAKEN)
return false; return false;
for (i = 0; i < SUBPAGE_METAOFF / BITMAP_GRANULARITY; i++) { for (i = 0; i < SUBPAGE_METAOFF / BITMAP_GRANULARITY; i++) {
enum alloc_state state; enum alloc_state state;
state = get_bit_pair((uint8_t *)pool + *mhoff, i); /* +1 because header is the first byte. */
state = get_bit_pair((uint8_t *)pool + *mhoff, i+1);
switch (state) { switch (state) {
case SPECIAL: case SPECIAL:
return false; return false;
...@@ -700,16 +681,15 @@ void alloc_visualize(FILE *out, void *pool, unsigned long poolsize) ...@@ -700,16 +681,15 @@ void alloc_visualize(FILE *out, void *pool, unsigned long poolsize)
metadata_pages += (sizeof(*mh) + mh->metalen) / getpagesize(); metadata_pages += (sizeof(*mh) + mh->metalen) / getpagesize();
/* TAKEN tags end a subpage alloc. */ for (i = 0;
for (i = mh->metalen * CHAR_BIT/BITS_PER_PAGE - 1; i < mh->metalen * CHAR_BIT / BITS_PER_PAGE;
i >= 0; i += len) {
i -= len) {
switch (get_page_state(meta, i)) { switch (get_page_state(meta, i)) {
case FREE: case FREE:
len = 1; len = 1;
free++; free++;
break; break;
case TAKEN: case BITMAP:
/* Skip over this allocated part. */ /* Skip over this allocated part. */
len = BITMAP_METALEN * CHAR_BIT; len = BITMAP_METALEN * CHAR_BIT;
subpageblocks++; subpageblocks++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment