Skip to content

Commit

Permalink
Slightly polish the buddy allocator and ensure mutual exclusion in it…
Browse files Browse the repository at this point in the history
… (related to #118 and #220)
  • Loading branch information
devreal committed Jan 12, 2017
1 parent e2b311e commit dcbc040
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 5 deletions.
35 changes: 31 additions & 4 deletions dart-impl/mpi/include/dash/dart/mpi/dart_mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,47 @@
#define DART_MAX_TEAM_NUMBER (256)
#define DART_MAX_LENGTH (1024*1024*16)

struct dart_buddy {
int level;
uint8_t tree[1];
};
struct dart_buddy;


extern char* dart_mempool_localalloc;
extern struct dart_buddy* dart_localpool;

/**
* Create a new buddy allocator instance.
*
* The amount of memory allocatable through the allocator
* depends on the number of levels in the binary tree.
* The maximum number of bytes managed by the allocator is
* 2**(level). The internal memory requirements are
* O(2**(2*level)).
*
* \param level The number of levels of the internal binary tree.
*/
struct dart_buddy *
dart_buddy_new(int level);

/**
* Delete the given buddy allocator instance.
*/
void dart_buddy_delete(struct dart_buddy *);

/**
* Allocate memory from the external memory pool.
*
* \return The offset relative to the starting adddress of the external
* memory block where the allocated memory begins.
*/
uint64_t dart_buddy_alloc(struct dart_buddy *, size_t size);

/**
* Return the previously allocated memory chunk to the allocator for reuse.
*/
int dart_buddy_free(struct dart_buddy *, uint64_t offset);

/**
* ???
*/
int buddy_size(struct dart_buddy *, uint64_t offset);
void buddy_dump(struct dart_buddy *);

Expand Down
37 changes: 36 additions & 1 deletion dart-impl/mpi/src/dart_mem.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
//https://github.com/cloudwu/buddy
/*
* Buddy allocator to be used with externally allocated blocks.
*
* The main use for this allocator is \c dart_memalloc where a
* fixed-size pre-allocated shared window is used to facilitate
* shared-memory optimizations.
*
* The code was taken from https://github.com/cloudwu/buddy and
* the right to use it has been kindly granted by the author.
*
*/

#include <dash/dart/mpi/dart_mem.h>
#include <dash/dart/base/mutex.h>

/* For PRIu64, uint64_t in printf */
#define __STDC_FORMAT_MACROS
Expand All @@ -11,6 +22,12 @@
#define NODE_SPLIT 2
#define NODE_FULL 3

struct dart_buddy {
dart_mutex_t mutex;
int level;
uint8_t tree[1];
};

struct dart_buddy *
dart_buddy_new(int level)
{
Expand All @@ -19,6 +36,7 @@ struct dart_buddy *
malloc(sizeof(struct dart_buddy) + sizeof(uint8_t) * (size * 2 - 2));
self->level = level;
memset(self->tree, NODE_UNUSED, size * 2 - 1);
dart_mutex_init(&self->mutex);
return self;
}

Expand Down Expand Up @@ -85,11 +103,14 @@ dart_buddy_alloc(struct dart_buddy * self, size_t s) {
int index = 0;
int level = 0;

dart_mutex_lock(&self->mutex);

while (index >= 0) {
if (size == length) {
if (self->tree[index] == NODE_UNUSED) {
self->tree[index] = NODE_USED;
_mark_parent(self, index);
dart_mutex_unlock(&self->mutex);
return _index_offset(index, level, self->level);
}
}
Expand All @@ -104,6 +125,7 @@ dart_buddy_alloc(struct dart_buddy * self, size_t s) {
self->tree[index] = NODE_SPLIT;
self->tree[index * 2 + 1] = NODE_UNUSED;
self->tree[index * 2 + 2] = NODE_UNUSED;
// intentional fall-through (?)
default:
index = index * 2 + 1;
length /= 2;
Expand All @@ -120,6 +142,7 @@ dart_buddy_alloc(struct dart_buddy * self, size_t s) {
length *= 2;
index = (index + 1) / 2 - 1;
if (index < 0)
dart_mutex_unlock(&self->mutex);
return -1;
if (index & 1) {
++index;
Expand All @@ -128,6 +151,7 @@ dart_buddy_alloc(struct dart_buddy * self, size_t s) {
}
}

dart_mutex_unlock(&self->mutex);
return -1;
}

Expand Down Expand Up @@ -158,17 +182,21 @@ int dart_buddy_free(struct dart_buddy * self, uint64_t offset)
return -1;
}

dart_mutex_lock(&self->mutex);
for (;;) {
switch (self->tree[index]) {
case NODE_USED:
if (offset != left){
assert (offset == left);
dart_mutex_unlock(&self->mutex);
return -1;
}
_combine(self, index);
dart_mutex_unlock(&self->mutex);
return 0;
case NODE_UNUSED:
assert (0);
dart_mutex_unlock(&self->mutex);
return -1;
default:
length /= 2;
Expand All @@ -182,6 +210,10 @@ int dart_buddy_free(struct dart_buddy * self, uint64_t offset)
break;
}
}

dart_mutex_unlock(&self->mutex);
// TODO: is this ever reached?
return -1;
}

int buddy_size(struct dart_buddy * self, uint64_t offset)
Expand Down Expand Up @@ -212,6 +244,9 @@ int buddy_size(struct dart_buddy * self, uint64_t offset)
break;
}
}

// TODO: is this ever reached?
return -1;
}

static void
Expand Down

0 comments on commit dcbc040

Please sign in to comment.