added new memory allocator files and README
This commit is contained in:
0
allocator/alloc.c
Normal file
0
allocator/alloc.c
Normal file
204
allocator/bitmap/bitmap_alloc.c
Normal file
204
allocator/bitmap/bitmap_alloc.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/**********************************
|
||||
* bitmap_alloc.c
|
||||
* Jeremy.Singer@glasgow.ac.uk
|
||||
*
|
||||
* This is a simple fixed-size bitmap allocator.
|
||||
* It mmaps a large buffer of
|
||||
* NUM_CHUNKS * CHUNK_SIZE bytes
|
||||
* then allocates this space in equally-sized
|
||||
* chunks to client code.
|
||||
* A side bitmap is required to keep track of which
|
||||
* chunks are in use (corresponding bit set to 1)
|
||||
* and which chunks are free (corresponding bit
|
||||
* set to 0). There is one bit per allocatable chunk.
|
||||
*
|
||||
* This is _not_ a clever allocator, since it
|
||||
* does a linear scan of the bitmap to find the
|
||||
* first free chunk, which is expensive!
|
||||
* More efficient scans could be easily incorporated.
|
||||
*
|
||||
* This is _not_ a general-purpose allocator, since
|
||||
* it only allocates chunks of a fixed size. Further,
|
||||
* this size is constrained to be small enough to allow
|
||||
* exact bounds representation in CHERI capabilities.
|
||||
*
|
||||
* This is an initial simple memory allocator test
|
||||
* for CHERI / Capable VMs.
|
||||
* We explore capability alignment,
|
||||
* representable bounds, narrowing operations
|
||||
* and compiler intrinsic support.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <cheriintrin.h>
|
||||
|
||||
#include <cheri/cheric.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "bitmap_alloc.h"
|
||||
|
||||
#define BITS_PER_BYTE 8
|
||||
|
||||
char *buffer = NULL; /* allocation buffer */
|
||||
unsigned char *bitmap = NULL; /* bitmap for the buffer */
|
||||
|
||||
int buffer_size = 0; /* size of buffer (in bytes) */
|
||||
int bitmap_size = 0; /* size of bitmap (in bytes) */
|
||||
int bytes_per_chunk = 0; /* size of single chunk (in bytes) */
|
||||
|
||||
void init_alloc(int num_chunks, int chunk_size)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* we need to increase the num_chunks
|
||||
* so every bit in bitmap will be used
|
||||
*/
|
||||
int adjusted_num_chunks = (num_chunks % BITS_PER_BYTE == 0)
|
||||
? num_chunks
|
||||
: (num_chunks + (BITS_PER_BYTE - (num_chunks % BITS_PER_BYTE)));
|
||||
|
||||
/* we need to increase the chunk_size
|
||||
* so chunks will be CHERI aligned
|
||||
* (i.e. 16 bytes for RISC-V 64-bit arch)
|
||||
*/
|
||||
int adjusted_chunk_size =
|
||||
(chunk_size % (sizeof(void *)) == 0)
|
||||
? chunk_size
|
||||
: (chunk_size + (sizeof(void *)) - (chunk_size % (sizeof(void *))));
|
||||
|
||||
/* check this chunk size is small enough so we can represent
|
||||
* bounds precisely with CHERI compressed representation
|
||||
*/
|
||||
adjusted_chunk_size = cheri_representable_length(adjusted_chunk_size);
|
||||
|
||||
/* request memory for our allocation buffer */
|
||||
char *res = mmap(NULL, adjusted_num_chunks * adjusted_chunk_size, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
/* request memory for our bitmap */
|
||||
bitmap = (unsigned char *) mmap(NULL, adjusted_num_chunks / BITS_PER_BYTE,
|
||||
PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (res == MAP_FAILED || bitmap == MAP_FAILED)
|
||||
{
|
||||
perror("error in initial mem allocation");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* NB mmap min bounds for capability is 1 page (4K) */
|
||||
buffer = res;
|
||||
/* check buffer is aligned */
|
||||
assert((uintptr_t) buffer % sizeof(void *) == 0);
|
||||
/* check bitmap is aligned */
|
||||
assert((uintptr_t) bitmap % sizeof(void *) == 0);
|
||||
|
||||
bytes_per_chunk = adjusted_chunk_size;
|
||||
buffer_size = adjusted_num_chunks * adjusted_chunk_size;
|
||||
bitmap_size = adjusted_num_chunks / BITS_PER_BYTE;
|
||||
|
||||
/* zero bitmap, since all chunks are free initially */
|
||||
for (i = 0; i < bitmap_size; i++)
|
||||
{
|
||||
bitmap[i] = 0;
|
||||
}
|
||||
|
||||
// set exact bounds for buffer and bitmap?
|
||||
buffer = cheri_setbounds(buffer, buffer_size);
|
||||
bitmap = cheri_setbounds(bitmap, bitmap_size);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate fixed size chunk with bitmap allocator
|
||||
* this is our simplistic `malloc` function
|
||||
*/
|
||||
char *malloc()
|
||||
{
|
||||
unsigned char updated_byte = 0;
|
||||
int chunk_index = 0;
|
||||
char *chunk = NULL;
|
||||
// iterate over all bits in bitmap, looking for a 0
|
||||
// when we find a 0, set it to 1 and
|
||||
// return the corresponding chunk
|
||||
// (setting its capability bounds)
|
||||
int i = 0;
|
||||
while (bitmap[i] == (unsigned char) 0xff)
|
||||
{
|
||||
i++;
|
||||
if (i >= bitmap_size)
|
||||
break;
|
||||
}
|
||||
// do we have a 0?
|
||||
if (i < bitmap_size && bitmap[i] != (unsigned char) 0xff)
|
||||
{
|
||||
// find the lowest 0 ...
|
||||
int j = 0;
|
||||
// right shift until bottom bit is 0
|
||||
for (j = 0; j < BITS_PER_BYTE; j++)
|
||||
{
|
||||
int bit = (bitmap[i] >> j) & 1;
|
||||
if (bit == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// now i is the word index, j is the bit index
|
||||
// set this bit to 1 ...
|
||||
// and work out the chunk to allocate
|
||||
updated_byte = bitmap[i] + (unsigned char) (1 << j);
|
||||
bitmap[i] = updated_byte;
|
||||
|
||||
chunk_index = i * BITS_PER_BYTE + j;
|
||||
chunk = buffer + (chunk_index * bytes_per_chunk);
|
||||
|
||||
/* restrict capability range before returning ptr */
|
||||
chunk = cheri_setbounds(chunk, bytes_per_chunk);
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
void free(void *chunk)
|
||||
{
|
||||
vaddr_t base = cheri_getbase(chunk);
|
||||
vaddr_t buff_base = cheri_getbase(buffer);
|
||||
/* calculate chunk index in buffer */
|
||||
int chunk_index = (base - buff_base) / bytes_per_chunk;
|
||||
assert(chunk_index >= 0);
|
||||
/* calculate corresponding bitmap index */
|
||||
int bitmap_index = chunk_index / BITS_PER_BYTE;
|
||||
assert(bitmap_index < bitmap_size);
|
||||
int bitmap_offset = chunk_index % BITS_PER_BYTE;
|
||||
/* set this bitmap entry to 0 */
|
||||
unsigned char updated_byte = bitmap[bitmap_index] & (unsigned char) (~(1 << bitmap_offset));
|
||||
bitmap[bitmap_index] = updated_byte;
|
||||
return;
|
||||
}
|
||||
|
||||
int num_used_chunks()
|
||||
{
|
||||
int i = 0;
|
||||
int used_chunks = 0;
|
||||
|
||||
while (i < bitmap_size)
|
||||
{
|
||||
unsigned char x = bitmap[i];
|
||||
if (x != 0)
|
||||
{
|
||||
/* some used chunks here */
|
||||
unsigned char j;
|
||||
for (j = 1; j <= x; j = j << 1)
|
||||
{
|
||||
if (x & j)
|
||||
{
|
||||
used_chunks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return used_chunks;
|
||||
}
|
||||
0
allocator/bitmap/bitmap_alloc.h
Normal file
0
allocator/bitmap/bitmap_alloc.h
Normal file
78
allocator/bump_alloc/bump_alloc.c
Normal file
78
allocator/bump_alloc/bump_alloc.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/**********************************
|
||||
* bump_alloc.c
|
||||
* Jeremy.Singer@glasgow.ac.uk
|
||||
*
|
||||
* This is a simple bump-pointer allocator.
|
||||
* It mmaps a large buffer of SIZE bytes,
|
||||
* then allocates this space in word-sized
|
||||
* chunks to client code (in main fn).
|
||||
*
|
||||
* Initial simple memory allocator test.
|
||||
* Explore capability narrowing operations
|
||||
* and intrinsics for bound reporting.
|
||||
*/
|
||||
|
||||
#include <cheriintrin.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "bump_alloc.h"
|
||||
|
||||
int count = 0; /* number of bytes allocated so far*/
|
||||
int max = 0; /* upper limit for count */
|
||||
char *buffer = NULL; /* the allocation buffer */
|
||||
|
||||
void init_alloc(int size_in_bytes)
|
||||
{
|
||||
/* request memory for our allocation buffer
|
||||
* NB mmap min bounds for capability is 1 page (4K)
|
||||
*/
|
||||
char *res = mmap(NULL, size_in_bytes, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (res == MAP_FAILED)
|
||||
{
|
||||
perror("error in initial mem allocation");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
buffer = res;
|
||||
max = size_in_bytes;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate len bytes with bump pointer allocator
|
||||
* this is our simplistic `malloc` function
|
||||
*/
|
||||
char *malloc(int len)
|
||||
{
|
||||
char *chunk = buffer + count;
|
||||
size_t rounded_len; /* for CHERI alignment */
|
||||
size_t new_count; /* for buffer overflow check */
|
||||
|
||||
/* ensure we can represent the capability accurately,
|
||||
* see p30 of CHERI C/C++ Prog Guide (June 2020)
|
||||
* www.cl.cam.ac.uk/techreports/UCAM-CL-TR-947
|
||||
*/
|
||||
chunk = __builtin_align_up(chunk, ~cheri_representable_alignment_mask(len) + 1);
|
||||
rounded_len = cheri_representable_length(len);
|
||||
|
||||
new_count = (chunk + rounded_len) - buffer;
|
||||
if (new_count > max)
|
||||
{
|
||||
/* out of bounds - don't allocate anything */
|
||||
chunk = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* restrict capability range before returning ptr */
|
||||
chunk = cheri_bounds_set_exact(chunk, rounded_len);
|
||||
|
||||
/* update bytes allocated count */
|
||||
count = new_count;
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
18
allocator/bump_alloc/bump_alloc.h
Normal file
18
allocator/bump_alloc/bump_alloc.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/**********************************
|
||||
* bump_alloc.h
|
||||
* Jeremy.Singer@glasgow.ac.uk
|
||||
*
|
||||
* This is a simple bump-pointer allocator.
|
||||
* It mmaps a large buffer of SIZE bytes,
|
||||
* then allocates this space in word-sized
|
||||
* chunks to client code (in main fn).
|
||||
*
|
||||
* Initial simple memory allocator test.
|
||||
* Explore capability narrowing operations
|
||||
* and intrinsics for bound reporting.
|
||||
*/
|
||||
|
||||
void init_alloc(int size_in_bytes);
|
||||
|
||||
char *bump_alloc(int bytes); /* the simplest malloc */
|
||||
/* oh, and there's no free() ! */
|
||||
119
allocator/freelist/binary_trees.c
Normal file
119
allocator/freelist/binary_trees.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/* The Computer Language Benchmarks Game
|
||||
* https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
|
||||
|
||||
contributed by Kevin Carson
|
||||
compilation:
|
||||
gcc -O3 -fomit-frame-pointer -funroll-loops -static binary-trees.c -lm
|
||||
icc -O3 -ip -unroll -static binary-trees.c -lm
|
||||
|
||||
*reset*
|
||||
*/
|
||||
|
||||
/* modified by @jsinger for CHERI example allocators */
|
||||
#include "freelist_allocator.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct tn
|
||||
{
|
||||
struct tn *left;
|
||||
struct tn *right;
|
||||
} treeNode;
|
||||
|
||||
treeNode *NewTreeNode(treeNode *left, treeNode *right)
|
||||
{
|
||||
treeNode *new;
|
||||
|
||||
new = (treeNode *) alloc(sizeof(treeNode));
|
||||
|
||||
new->left = left;
|
||||
new->right = right;
|
||||
|
||||
return new;
|
||||
} /* NewTreeNode() */
|
||||
|
||||
long ItemCheck(treeNode *tree)
|
||||
{
|
||||
if (tree->left == NULL)
|
||||
return 1;
|
||||
else
|
||||
return 1 + ItemCheck(tree->left) + ItemCheck(tree->right);
|
||||
} /* ItemCheck() */
|
||||
|
||||
treeNode *BottomUpTree(unsigned depth)
|
||||
{
|
||||
if (depth > 0)
|
||||
return NewTreeNode(BottomUpTree(depth - 1), BottomUpTree(depth - 1));
|
||||
else
|
||||
return NewTreeNode(NULL, NULL);
|
||||
} /* BottomUpTree() */
|
||||
|
||||
void DeleteTree(treeNode *tree)
|
||||
{
|
||||
if (tree->left != NULL)
|
||||
{
|
||||
DeleteTree(tree->left);
|
||||
DeleteTree(tree->right);
|
||||
}
|
||||
|
||||
dealloc(tree);
|
||||
} /* DeleteTree() */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned N, depth, minDepth, maxDepth, stretchDepth;
|
||||
treeNode *stretchTree, *longLivedTree, *tempTree;
|
||||
unsigned pages; /* mem required */
|
||||
|
||||
N = (argc > 1) ? atol(argv[1]) : 0;
|
||||
|
||||
minDepth = 4;
|
||||
|
||||
if ((minDepth + 2) > N)
|
||||
maxDepth = minDepth + 2;
|
||||
else
|
||||
maxDepth = N;
|
||||
|
||||
stretchDepth = maxDepth + 1;
|
||||
|
||||
/* calculate mem requirements, with allocator-specific
|
||||
* size-class assumptions
|
||||
*/
|
||||
pages = ((2 << (stretchDepth + 3)) * sizeof(treeNode)) / BYTES_IN_PAGE;
|
||||
printf("treenode size is %u bytes\n", (unsigned int) sizeof(treeNode));
|
||||
printf("we need %u pages\n", pages);
|
||||
|
||||
/* allocate memory pool */
|
||||
initialize(pages);
|
||||
|
||||
/* start creating tree data structures */
|
||||
stretchTree = BottomUpTree(stretchDepth);
|
||||
printf("stretch tree of depth %u\t check: %li\n", stretchDepth, ItemCheck(stretchTree));
|
||||
|
||||
DeleteTree(stretchTree);
|
||||
|
||||
longLivedTree = BottomUpTree(maxDepth);
|
||||
|
||||
for (depth = minDepth; depth <= maxDepth; depth += 2)
|
||||
{
|
||||
long i, iterations, check;
|
||||
|
||||
iterations = pow(2, maxDepth - depth + minDepth);
|
||||
|
||||
check = 0;
|
||||
|
||||
for (i = 1; i <= iterations; i++)
|
||||
{
|
||||
tempTree = BottomUpTree(depth);
|
||||
check += ItemCheck(tempTree);
|
||||
DeleteTree(tempTree);
|
||||
} /* for(i = 1...) */
|
||||
|
||||
printf("%li\t trees of depth %u\t check: %li\n", iterations, depth, check);
|
||||
} /* for(depth = minDepth...) */
|
||||
|
||||
printf("long lived tree of depth %u\t check: %li\n", maxDepth, ItemCheck(longLivedTree));
|
||||
|
||||
return 0;
|
||||
} /* main() */
|
||||
166
allocator/freelist/freelist.c
Normal file
166
allocator/freelist/freelist.c
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "freelist_allocator.h"
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
char *small_freelist = NULL;
|
||||
|
||||
char *medium_freelist = NULL;
|
||||
|
||||
char *large_freelist = NULL;
|
||||
|
||||
void initialize(unsigned int size_in_pages)
|
||||
{
|
||||
/* request memory for our allocation buffer
|
||||
* NB mmap min bounds for capability is 1 page (4K)
|
||||
*/
|
||||
size_t bytes_to_allocate = size_in_pages * BYTES_IN_PAGE;
|
||||
char *res =
|
||||
mmap(NULL, bytes_to_allocate, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (res == MAP_FAILED)
|
||||
{
|
||||
perror("error in initial mem allocation");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// put in linked list pointers and
|
||||
// stick into the large freelist
|
||||
// give this space to the large freelist ...
|
||||
large_freelist = insert_linked_list_pointers(LARGE, bytes_to_allocate, res, large_freelist);
|
||||
return;
|
||||
}
|
||||
|
||||
char *insert_linked_list_pointers(size_t cell_size, size_t limit, char *start, char *freelist)
|
||||
{
|
||||
char *curr = start;
|
||||
char *next = curr + cell_size;
|
||||
char *max = start + limit;
|
||||
// ensure next ptr will fit into cell
|
||||
assert(sizeof(void *) <= cell_size);
|
||||
|
||||
while (next < max)
|
||||
{
|
||||
((char **) curr)[0] = next;
|
||||
curr = next;
|
||||
next = curr + cell_size;
|
||||
}
|
||||
// at the end, concatenate this newly formed
|
||||
// list with existing freelist
|
||||
((char **) curr)[0] = freelist;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
char *alloc(size_t bytes)
|
||||
{
|
||||
|
||||
size_t size;
|
||||
char *freelist_to_use = NULL;
|
||||
char *ret = NULL; // ptr to return
|
||||
|
||||
// work out which freelist to use
|
||||
if (bytes <= SMALL)
|
||||
{
|
||||
size = SMALL;
|
||||
freelist_to_use = small_freelist;
|
||||
}
|
||||
else if (bytes <= MEDIUM)
|
||||
{
|
||||
size = MEDIUM;
|
||||
freelist_to_use = medium_freelist;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = LARGE;
|
||||
freelist_to_use = large_freelist;
|
||||
}
|
||||
|
||||
if (freelist_to_use == NULL)
|
||||
{
|
||||
// fixup freelist (if no available mem there)
|
||||
char *new_space = NULL;
|
||||
switch (size)
|
||||
{
|
||||
case SMALL:
|
||||
new_space = alloc(MEDIUM);
|
||||
if (new_space != NULL)
|
||||
{
|
||||
small_freelist =
|
||||
insert_linked_list_pointers(SMALL, MEDIUM, new_space, small_freelist);
|
||||
freelist_to_use = small_freelist;
|
||||
// now we have replenished space...
|
||||
}
|
||||
break;
|
||||
case MEDIUM:
|
||||
new_space = alloc(LARGE);
|
||||
if (new_space != NULL)
|
||||
{
|
||||
medium_freelist =
|
||||
insert_linked_list_pointers(MEDIUM, LARGE, new_space, medium_freelist);
|
||||
freelist_to_use = medium_freelist;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// stuck! no more mem!
|
||||
// we will return NULL
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// pop from head of freelist (if there's anything there)
|
||||
if (freelist_to_use != NULL)
|
||||
{
|
||||
char *head = freelist_to_use;
|
||||
char *tail = ((char **) head)[0];
|
||||
switch (size)
|
||||
{
|
||||
case SMALL:
|
||||
small_freelist = tail;
|
||||
break;
|
||||
case MEDIUM:
|
||||
medium_freelist = tail;
|
||||
break;
|
||||
default:
|
||||
large_freelist = tail;
|
||||
break;
|
||||
}
|
||||
ret = head;
|
||||
SET_SIZE(ret, size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dealloc(void *buffer)
|
||||
{
|
||||
|
||||
// work out the size of the buffer
|
||||
size_t size;
|
||||
char *freelist;
|
||||
|
||||
size = GET_SIZE(buffer);
|
||||
|
||||
// then prepend it to the appropriate freelist
|
||||
switch (size)
|
||||
{
|
||||
case SMALL:
|
||||
small_freelist = cons_onto_freelist(buffer, small_freelist);
|
||||
break;
|
||||
case MEDIUM:
|
||||
medium_freelist = cons_onto_freelist(buffer, medium_freelist);
|
||||
break;
|
||||
default:
|
||||
large_freelist = cons_onto_freelist(buffer, large_freelist);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char *cons_onto_freelist(char *cell, char *freelist)
|
||||
{
|
||||
((char **) cell)[0] = freelist;
|
||||
return cell;
|
||||
}
|
||||
53
allocator/freelist/freelist_allocator.h
Normal file
53
allocator/freelist/freelist_allocator.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/**********************************
|
||||
* freelist_allocator.h
|
||||
* Jeremy.Singer@glasgow.ac.uk
|
||||
*
|
||||
* This is a simple segregated freelist allocator.
|
||||
* It mmaps a large buffer of num_pages pages,
|
||||
* then constructs a linked list of LARGE-sized cells.
|
||||
*
|
||||
* When an alloc request occurs, we have three size
|
||||
* classes we can use - SMALL, MEDIUM, and LARGE.
|
||||
* If there is a empty cell available in the appropriate
|
||||
* freelist, we return this cell.
|
||||
* If there are no cells available, we try to
|
||||
* grab a cell from a larger freelist to replenish
|
||||
* our freelist, and return one of these cells.
|
||||
* If there is no memory available, alloc returns NULL.
|
||||
*
|
||||
* When a dealloc request occurs, we know the size
|
||||
* of the cell so we can prepend the cell onto the
|
||||
* appropriate freelist.
|
||||
*
|
||||
* NB Allocated cells have their sizes encoded in the
|
||||
* corresponding cell capability - this means we
|
||||
* naively assume that allocator client code
|
||||
* does _not_ interfere with the capability
|
||||
* metadata.
|
||||
*/
|
||||
|
||||
#include <cheriintrin.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* possible sizes for cells */
|
||||
#define SMALL 16
|
||||
#define MEDIUM 256
|
||||
#define LARGE 4096
|
||||
|
||||
/* we assume 4K pages */
|
||||
#define BYTES_IN_PAGE LARGE
|
||||
|
||||
/* cell sizes encoded in CHERI bounds metadata */
|
||||
#define SET_SIZE(cell, size) cell = cheri_bounds_set_exact(cell, size)
|
||||
#define GET_SIZE(cell) cheri_length_get(cell)
|
||||
|
||||
/* allocator init routine */
|
||||
void initialize(unsigned int num_pages);
|
||||
|
||||
/* malloc and free */
|
||||
char *alloc(size_t bytes);
|
||||
void dealloc(void *buffer);
|
||||
|
||||
/* freelist management routines */
|
||||
char *insert_linked_list_pointers(size_t cell_size, size_t limit, char *start, char *freelist);
|
||||
char *cons_onto_freelist(char *cell, char *freelist);
|
||||
46
allocator/readme.md
Normal file
46
allocator/readme.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Convention for benchmarking various allocators
|
||||
We demonstrate the standard emitters each C memory allocator should follow to standardize the code being benchmarked.
|
||||
|
||||
There are 3 factors on the design for benchmarking these C programs:
|
||||
- Standard interface to test various memory allocators.
|
||||
- Automating the extracting of various performance counters.
|
||||
- Parsing and analyzing the various benchmark metrics extracted.
|
||||
|
||||
## Standard interface to test various memory allocators
|
||||
The interface goes as the following:
|
||||
- ```Malloc```, ```Free``` and ``ìnit_alloc``.
|
||||
- The folder structure is as follows:
|
||||
```
|
||||
- <Allocator name>
|
||||
- HugePages
|
||||
- Original
|
||||
- README (Explaining the Allocator design with the source of the allocator)
|
||||
```
|
||||
- The linkage of the C program should consist either of a shared object file
|
||||
which is preferred. Or with a header file which can compile the appropriate
|
||||
file at compile.
|
||||
- [ ] To write a script to compile and link shared object files.
|
||||
- [ ] Automate generating header files.
|
||||
|
||||
## Automating the extracting of various performance counters.
|
||||
The extraction library to generate the decided performance counters is implemented.
|
||||
ARM unclear documentation from the A profile manual gives a unclear picture of
|
||||
exactly what the performance counters do. The script to extract it and to generate graphs
|
||||
is completely isolated. This makes process from running to generating the end graphs
|
||||
pretty tedious.
|
||||
|
||||
### Steps to resolve this:
|
||||
- [ ] To build runners that runs with different memory allocators and the wall clock
|
||||
and metrics in semantically comparable file which is followed as a basic standard.
|
||||
This means.
|
||||
```
|
||||
Ex:
|
||||
- performance-benchmark.stat
|
||||
- performance-huge-benchmark.stat
|
||||
```
|
||||
- [ ] Extract results to a certain folder and then immediate run python program to generate the graphs.
|
||||
- [ ] Numeric values represented as a table.
|
||||
- [ ] Generate graphs in semantically readable folder structure.
|
||||
- [ ] Save generated data which can be loaded as graphs.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user