set basic scripts to generate automatic shared object files using the benchmark ABI
This commit is contained in:
@@ -115,7 +115,10 @@ void init_alloc(int num_chunks, int chunk_size)
|
|||||||
* allocate fixed size chunk with bitmap allocator
|
* allocate fixed size chunk with bitmap allocator
|
||||||
* this is our simplistic `malloc` function
|
* this is our simplistic `malloc` function
|
||||||
*/
|
*/
|
||||||
char *malloc()
|
// Length is not used but just kept
|
||||||
|
// to keep the integrity of the
|
||||||
|
// malloc shape.
|
||||||
|
void *malloc(size_t len)
|
||||||
{
|
{
|
||||||
unsigned char updated_byte = 0;
|
unsigned char updated_byte = 0;
|
||||||
int chunk_index = 0;
|
int chunk_index = 0;
|
||||||
207
allocator/bitmap/Regular/bitmap_alloc.c
Normal file
207
allocator/bitmap/Regular/bitmap_alloc.c
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
/**********************************
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
// Length is not used but just kept
|
||||||
|
// to keep the integrity of the
|
||||||
|
// malloc shape.
|
||||||
|
void *malloc(size_t len)
|
||||||
|
{
|
||||||
|
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/Regular/bitmap_alloc.h
Normal file
0
allocator/bitmap/Regular/bitmap_alloc.h
Normal file
2
allocator/bitmap/build.sh
Normal file
2
allocator/bitmap/build.sh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
cc -g -Wall -shared -o malloc-huge.so -mabi=purecap-benchmark -lpthread HugePage/bitmap_alloc.c
|
||||||
|
cc -g -Wall -shared -o malloc-regular.so -mabi=purecap-benchmark -lpthread Regular/bitmap_alloc.c
|
||||||
@@ -46,7 +46,7 @@ void init_alloc(int size_in_bytes)
|
|||||||
* allocate len bytes with bump pointer allocator
|
* allocate len bytes with bump pointer allocator
|
||||||
* this is our simplistic `malloc` function
|
* this is our simplistic `malloc` function
|
||||||
*/
|
*/
|
||||||
char *malloc(int len)
|
void *malloc(size_t len)
|
||||||
{
|
{
|
||||||
char *chunk = buffer + count;
|
char *chunk = buffer + count;
|
||||||
size_t rounded_len; /* for CHERI alignment */
|
size_t rounded_len; /* for CHERI alignment */
|
||||||
78
allocator/bump_alloc/Regular/bump_alloc.c
Normal file
78
allocator/bump_alloc/Regular/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
|
||||||
|
*/
|
||||||
|
void *malloc(size_t 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/Regular/bump_alloc.h
Normal file
18
allocator/bump_alloc/Regular/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() ! */
|
||||||
2
allocator/bump_alloc/build.sh
Normal file
2
allocator/bump_alloc/build.sh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
cc -g -Wall -shared -o malloc-huge.so -mabi=purecap-benchmark -lpthread HugePage/bump_alloc.c
|
||||||
|
cc -g -Wall -shared -o malloc-regular.so -mabi=purecap-benchmark -lpthread Regular/bump_alloc.c
|
||||||
@@ -19,10 +19,10 @@ The interface goes as the following:
|
|||||||
- The linkage of the C program should consist either of a shared object file
|
- 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
|
which is preferred. Or with a header file which can compile the appropriate
|
||||||
file at compile.
|
file at compile.
|
||||||
- [ ] To write a script to compile and link shared object files.
|
- [x] To write a script to compile and link shared object files.
|
||||||
- [ ] Automate generating header files.
|
- [ ] Automate generating header files.
|
||||||
|
|
||||||
## Automating the extracting of various performance counters.
|
## Automating the extracting of various performance counters and Parsing and analyzing the various benchmark metrics extracted.
|
||||||
The extraction library to generate the decided performance counters is implemented.
|
The extraction library to generate the decided performance counters is implemented.
|
||||||
ARM unclear documentation from the A profile manual gives a unclear picture of
|
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
|
exactly what the performance counters do. The script to extract it and to generate graphs
|
||||||
|
|||||||
Reference in New Issue
Block a user