Skip to content

Commit

Permalink
Add an ignore_data parameter to the realloc family of functions (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
spaskalev authored Nov 22, 2023
1 parent 6a766f0 commit bff90ce
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 61 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ jobs:
- name: setup
run: sudo apt-get update && sudo apt-get -y -qq install clang-tidy cppcheck cflow spell gcc-powerpc64-linux-gnu gcc-powerpc-linux-gnu gcc-aarch64-linux-gnu gcc-i686-linux-gnu qemu-user-binfmt
- name: test-main
run: make LLVM_VERSION=14
run: make LLVM_VERSION=14 CC=clang
working-directory: .
- name: bench-main
run: make LLVM_VERSION=14 bench
run: make LLVM_VERSION=14 CC=clang bench
working-directory: .
- name: test-multiplatform
run: make test-multiplatform
run: make test-multiplatform CC=clang
working-directory: .
- name: test-cpp-translation-unit
run: make LLVM_VERSION=14 test-cpp-translation-unit
run: make LLVM_VERSION=14 CC=clang CXX=clang++ test-cpp-translation-unit
working-directory: .
- uses: actions/upload-artifact@v3
if: failure()
Expand Down
9 changes: 5 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ MAKEFLAGS += --no-builtin-rules
.SUFFIXES:

LLVM_VERSION?=11
CC=clang-$(LLVM_VERSION)
CXX=clang++-$(LLVM_VERSION)
CFLAGS=-std=c99 --coverage -pg -no-pie -fno-builtin -g -O0 -Og -fstrict-aliasing -fstack-protector-all -fsanitize=undefined -fsanitize=bounds -pedantic -Wall -Wextra -Werror -Wfatal-errors -Wformat=2 -Wformat-security -Wconversion -Wcast-qual -Wnull-dereference -Wstack-protector -Warray-bounds -Warray-bounds-pointer-arithmetic -Wassign-enum -Wbad-function-cast -Wconditional-uninitialized -Wfloat-equal -Wformat-type-confusion -Widiomatic-parentheses -Wimplicit-fallthrough -Wloop-analysis -Wpointer-arith -Wshift-sign-overflow -Wshorten-64-to-32 -Wswitch-enum -Wtautological-constant-in-range-compare -Wunreachable-code-aggressive -Wthread-safety -Wthread-safety-beta -Wcomma -Wdeclaration-after-statement -D_FORTIFY_SOURCE=3
CXXFLAGS=-std=c++11 --coverage -pg -no-pie -fno-builtin -g -O0 -Og -fstrict-aliasing -fstack-protector-all -fsanitize=undefined -fsanitize=bounds -pedantic -Wall -Wextra -Wformat=2 -Wformat-security -Wconversion -Wcast-qual -Wnull-dereference -Wstack-protector -Warray-bounds -Warray-bounds-pointer-arithmetic -Wassign-enum -Wbad-function-cast -Wconditional-uninitialized -Wfloat-equal -Wformat-type-confusion -Widiomatic-parentheses -Wimplicit-fallthrough -Wloop-analysis -Wpointer-arith -Wshift-sign-overflow -Wshorten-64-to-32 -Wswitch-enum -Wtautological-constant-in-range-compare -Wunreachable-code-aggressive -Wthread-safety -Wthread-safety-beta -Wcomma -Wdeclaration-after-statement -D_FORTIFY_SOURCE=3
CC?=clang-$(LLVM_VERSION)
CXX?=clang++-$(LLVM_VERSION)
CFLAGS?=-std=c99 --coverage -pg -no-pie -fno-builtin -g -O0 -Og -fstrict-aliasing -fstack-protector-all -fsanitize=undefined -fsanitize=bounds -pedantic -Wall -Wextra -Werror -Wfatal-errors -Wformat=2 -Wformat-security -Wconversion -Wcast-qual -Wnull-dereference -Wstack-protector -Warray-bounds -Warray-bounds-pointer-arithmetic -Wassign-enum -Wbad-function-cast -Wconditional-uninitialized -Wfloat-equal -Wformat-type-confusion -Widiomatic-parentheses -Wimplicit-fallthrough -Wloop-analysis -Wpointer-arith -Wshift-sign-overflow -Wshorten-64-to-32 -Wswitch-enum -Wtautological-constant-in-range-compare -Wunreachable-code-aggressive -Wthread-safety -Wthread-safety-beta -Wcomma -Wdeclaration-after-statement -D_FORTIFY_SOURCE=3
CXXFLAGS?=-std=c++11 --coverage -pg -no-pie -fno-builtin -g -O0 -Og -fstrict-aliasing -fstack-protector-all -fsanitize=undefined -fsanitize=bounds -pedantic -Wall -Wextra -Wformat=2 -Wformat-security -Wconversion -Wcast-qual -Wnull-dereference -Wstack-protector -Warray-bounds -Warray-bounds-pointer-arithmetic -Wassign-enum -Wbad-function-cast -Wconditional-uninitialized -Wfloat-equal -Wformat-type-confusion -Widiomatic-parentheses -Wimplicit-fallthrough -Wloop-analysis -Wpointer-arith -Wshift-sign-overflow -Wshorten-64-to-32 -Wswitch-enum -Wtautological-constant-in-range-compare -Wunreachable-code-aggressive -Wthread-safety -Wthread-safety-beta -Wcomma -Wdeclaration-after-statement -D_FORTIFY_SOURCE=3
LLVM_COV?=llvm-cov-$(LLVM_VERSION)
CPPCHECK?=cppcheck

TESTS_SRC=tests.c
TESTCXX_SRC=testcxx.cpp
LIB_SRC=buddy_alloc.h
Expand Down
25 changes: 13 additions & 12 deletions bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,31 @@
#include "buddy_alloc.h"
#undef BUDDY_ALLOC_IMPLEMENTATION

double test_malloc(size_t alloc_size);
double test_malloc(struct buddy *buddy, size_t alloc_size);
double test_malloc_firstfit(size_t alloc_size);
void *freeing_callback(void *ctx, void *addr, size_t slot_size, size_t allocated);

int main() {
setvbuf(stdout, NULL, _IONBF, 0);

size_t arena_size = 1 << 30;
unsigned char *buddy_buf = malloc(buddy_sizeof_alignment(arena_size, 64));
unsigned char *data_buf = malloc(arena_size);
struct buddy *buddy = buddy_init_alignment(buddy_buf, data_buf, arena_size, 64);

double total = 0;
for (size_t i = 0; i <= 6; i++) {
total += test_malloc(64 << i);
total += test_malloc(buddy, 64 << i);
total += test_malloc(buddy, 64 << i);
total += test_malloc(buddy, 64 << i);
}
printf("Total malloc runtime was %f seconds.\n\n", total);
}

double test_malloc(size_t alloc_size) {

size_t arena_size = 1 << 30;
unsigned char *buddy_buf = malloc(buddy_sizeof(arena_size));
unsigned char *data_buf = malloc(arena_size);
struct buddy *buddy = buddy_init(buddy_buf, data_buf, arena_size);
free(data_buf);
free(buddy_buf);
}

double test_malloc(struct buddy *buddy, size_t alloc_size) {
printf("Starting test with alloc size [%zu].\n", alloc_size);
time_t start_time = time(NULL);

Expand All @@ -53,9 +57,6 @@ double test_malloc(size_t alloc_size) {
printf("Test took %.f seconds in total. Allocation: %.f freeing: %.f\n", delta,
difftime(alloc_time, start_time), difftime(end_time, alloc_time));

free(data_buf);
free(buddy_buf);

return delta;
}

Expand Down
47 changes: 27 additions & 20 deletions buddy_alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@

#ifndef BUDDY_HEADER
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#ifndef BUDDY_PRINTF
#include <stdio.h>
#endif
#include <string.h>
#include <sys/types.h>
#endif

#ifdef __cplusplus
Expand Down Expand Up @@ -92,11 +93,11 @@ void *buddy_malloc(struct buddy *buddy, size_t requested_size);
void *buddy_calloc(struct buddy *buddy, size_t members_count, size_t member_size);

/* Realloc semantics are a joke. See realloc. */
void *buddy_realloc(struct buddy *buddy, void *ptr, size_t requested_size);
void *buddy_realloc(struct buddy *buddy, void *ptr, size_t requested_size, bool ignore_data);

/* Realloc-like behavior that checks for overflow. See reallocarray*/
void *buddy_reallocarray(struct buddy *buddy, void *ptr,
size_t members_count, size_t member_size);
size_t members_count, size_t member_size, bool ignore_data);

/* Use the specified buddy to free memory. See free. */
void buddy_free(struct buddy *buddy, void *ptr);
Expand Down Expand Up @@ -338,7 +339,7 @@ static inline void bitset_set(unsigned char *bitset, size_t pos);

static inline void bitset_clear(unsigned char *bitset, size_t pos);

static inline unsigned int bitset_test(const unsigned char *bitset, size_t pos);
static inline unsigned char bitset_test(const unsigned char *bitset, size_t pos);

static void bitset_shift_left(unsigned char *bitset, size_t from_pos, size_t to_pos, size_t by);

Expand Down Expand Up @@ -707,7 +708,7 @@ void *buddy_calloc(struct buddy *buddy, size_t members_count, size_t member_size
return result;
}

void *buddy_realloc(struct buddy *buddy, void *ptr, size_t requested_size) {
void *buddy_realloc(struct buddy *buddy, void *ptr, size_t requested_size, bool ignore_data) {
struct buddy_tree *tree;
struct buddy_tree_pos origin, new_pos;
size_t current_depth, target_depth;
Expand Down Expand Up @@ -758,26 +759,30 @@ void *buddy_realloc(struct buddy *buddy, void *ptr, size_t requested_size) {
return ptr;
}

/* Copy the content */
source = address_for_position(buddy, origin);
destination = address_for_position(buddy, new_pos);
memmove(destination, source, size_for_depth(buddy,
current_depth > target_depth ? current_depth : target_depth));

if (! ignore_data) {
/* Copy the content */
source = address_for_position(buddy, origin);
memmove(destination, source, size_for_depth(buddy,
current_depth > target_depth ? current_depth : target_depth));
}

/* Allocate and return */
buddy_tree_mark(tree, new_pos);
return destination;
}

void *buddy_reallocarray(struct buddy *buddy, void *ptr,
size_t members_count, size_t member_size) {
size_t members_count, size_t member_size, bool ignore_data) {
if (members_count == 0 || member_size == 0) {
return buddy_realloc(buddy, ptr, 0);
return buddy_realloc(buddy, ptr, 0, ignore_data);
}
/* Check for overflow */
if ((members_count * member_size)/members_count != member_size) {
return NULL;
}
return buddy_realloc(buddy, ptr, members_count * member_size);
return buddy_realloc(buddy, ptr, members_count * member_size, ignore_data);
}

void buddy_free(struct buddy *buddy, void *ptr) {
Expand Down Expand Up @@ -1218,7 +1223,7 @@ static void buddy_tree_populate_size_for_order(struct buddy_tree *t);
static inline size_t buddy_tree_size_for_order(struct buddy_tree *t, uint8_t to);
static void write_to_internal_position(unsigned char *bitset, struct internal_position pos, size_t value);
static size_t read_from_internal_position(unsigned char *bitset, struct internal_position pos);
static size_t compare_with_internal_position(unsigned char *bitset, struct internal_position pos, size_t value);
static inline unsigned char compare_with_internal_position(unsigned char *bitset, struct internal_position pos, size_t value);

static inline size_t size_for_order(uint8_t order, uint8_t to) {
size_t result = 0;
Expand Down Expand Up @@ -1484,7 +1489,7 @@ static size_t read_from_internal_position(unsigned char *bitset, struct internal
return bitset_count_range(bitset, pos.bitset_location, pos.bitset_location+pos.local_offset-1);
}

static size_t compare_with_internal_position(unsigned char *bitset, struct internal_position pos, size_t value) {
static inline unsigned char compare_with_internal_position(unsigned char *bitset, struct internal_position pos, size_t value) {
return bitset_test(bitset, pos.bitset_location+value-1);
}

Expand Down Expand Up @@ -1602,13 +1607,15 @@ static struct buddy_tree_pos buddy_tree_find_free(struct buddy_tree *t, uint8_t
uint8_t target_status;
size_t current_depth, right_status;
struct internal_position left_internal, right_internal;
unsigned char *tree_bits;

current_pos = buddy_tree_root();
target_status = target_depth - 1;
current_depth = buddy_tree_depth(current_pos);
if (buddy_tree_status(t, current_pos) > target_status) {
return INVALID_POS; /* No position available down the tree */
}
tree_bits = buddy_tree_bits(t);
while (current_depth != target_depth) {
/* Advance criteria */
target_status -= 1;
Expand All @@ -1622,15 +1629,15 @@ static struct buddy_tree_pos buddy_tree_find_free(struct buddy_tree *t, uint8_t
right_internal = left_internal;
right_internal.bitset_location += right_internal.local_offset; /* advance to the right */

if (compare_with_internal_position(buddy_tree_bits(t), left_internal, target_status+1)) { /* left branch is busy, pick right */
if (compare_with_internal_position(tree_bits, left_internal, target_status+1)) { /* left branch is busy, pick right */
current_pos = right_pos;
} else if (compare_with_internal_position(buddy_tree_bits(t), right_internal, target_status+1)) { /* right branch is busy, pick left */
} else if (compare_with_internal_position(tree_bits, right_internal, target_status+1)) { /* right branch is busy, pick left */
current_pos = left_pos;
} else {
/* One of the child nodes must be read in order to compare it to its sibling. */
right_status = read_from_internal_position(buddy_tree_bits(t), right_internal);
right_status = read_from_internal_position(tree_bits, right_internal);
if (right_status) {
if (compare_with_internal_position(buddy_tree_bits(t), left_internal, right_status)) {
if (compare_with_internal_position(tree_bits, left_internal, right_status)) {
current_pos = left_pos; /* Left is equal or more busy than right, prefer left */
} else {
current_pos = right_pos;
Expand Down Expand Up @@ -1798,7 +1805,7 @@ static inline void bitset_clear(unsigned char *bitset, size_t pos) {
bitset[bucket] &= ~bitset_index_mask[index];
}

static inline unsigned int bitset_test(const unsigned char *bitset, size_t pos) {
static inline unsigned char bitset_test(const unsigned char *bitset, size_t pos) {
size_t bucket = pos / CHAR_BIT;
size_t index = pos % CHAR_BIT;
return bitset[bucket] & bitset_index_mask[index];
Expand Down
4 changes: 2 additions & 2 deletions test-fuzz.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ int main(void)
} else {
size = size*2;
}
buddy_realloc(b, allocs[slot], size);
buddy_realloc(b, allocs[slot], size, true);
}
assert(buddy_tree_check_invariant(tree, buddy_tree_root()) == 0);
allocs[slot] = 0;
Expand All @@ -39,4 +39,4 @@ int main(void)
assert(buddy_tree_check_invariant(tree, buddy_tree_root()) == 0);
}
}
}
}
Loading

0 comments on commit bff90ce

Please sign in to comment.