Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ target_compile_definitions(slotsboxmalloc PRIVATE
# 依赖 blockmalloc 走 header-only(src/slotsboxmalloc.c 里 #define *_IMPLEMENTATION),
# 故不链接它的 .so;头的搜索路径由系统 include 提供。

enable_testing()
add_subdirectory(tutorial)

include("${CMAKE_CURRENT_LIST_DIR}/cmake/packagex.cmake")
25 changes: 11 additions & 14 deletions include/slotsboxmalloc/slotsboxobj.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,9 @@ static inline void sbo_update_parent(sbo_meta_t *meta, sbo_box_t *box,
if (sbo_usage_cmp(nm, box->child_max_cap) != 0) box->child_max_cap = nm;
else child_c = false;
}
if ((slot_c || child_c) && box->parent > 0) {
if ((slot_c || child_c) && sbo_self_id(meta, box) != 0) {
sbo_box_t *p = sbo_child(meta, box, box->parent);
if (p) sbo_update_parent(meta, p, slot_c, child_c);
if (p) sbo_update_parent(meta, p, false, true);
}
}

Expand All @@ -292,7 +292,7 @@ static inline void sbo_box_format(sbo_meta_t *meta, sbo_box_t *box,
box->slots[i].state = SBO_FREE;
box->children[i] = -1;
}
box->child_max_cap = (sbo_usage_t){objlevel + 1, 1};
box->child_max_cap = (sbo_usage_t){0, 0};
}

/* ================================================================
Expand Down Expand Up @@ -330,7 +330,7 @@ static inline int8_t sbo_alloc_obj_slots(sbo_meta_t *meta, sbo_box_t *box, uint8
uint8_t nc = sbo_continuous_max(box);
if (box->max_obj_cap != nc) {
box->max_obj_cap = nc;
if (box->parent > 0) {
if (sbo_self_id(meta, box) != 0) {
sbo_box_t *pp = sbo_child(meta, box, box->parent);
if (pp) sbo_update_parent(meta, pp, false, true);
}
Expand Down Expand Up @@ -358,7 +358,7 @@ static inline void sbo_free_obj_slots(sbo_meta_t *meta, sbo_box_t *box, uint8_t
uint8_t nc = sbo_continuous_max(box);
if (box->max_obj_cap != nc) {
box->max_obj_cap = nc;
if (box->parent > 0) {
if (sbo_self_id(meta, box) != 0) {
sbo_box_t *parent = sbo_child(meta, box, box->parent);
if (parent) sbo_update_parent(meta, parent, false, true);
}
Expand All @@ -372,7 +372,7 @@ static inline void sbo_free_obj_slots(sbo_meta_t *meta, sbo_box_t *box, uint8_t
#define SBO_ALLOC_FAIL ((uint64_t)-1)

static inline uint64_t sbo_find_alloc(sbo_meta_t *meta, sbo_box_t *box,
sbo_box_t *parent, sbo_usage_t usage) {
sbo_usage_t usage) {
if (!box || box->state != SBO_BOX) return SBO_ALLOC_FAIL;

if (usage.level == box->objlevel) {
Expand All @@ -388,7 +388,7 @@ static inline uint64_t sbo_find_alloc(sbo_meta_t *meta, sbo_box_t *box,
sbo_box_t *ch = sbo_child(meta, box, box->children[i]);
if (!ch) continue;
if (sbo_usage_cmp(sbo_box_and_child_max_cap(ch), usage) < 0) continue;
uint64_t sub = sbo_find_alloc(meta, ch, box, usage);
uint64_t sub = sbo_find_alloc(meta, ch, usage);
if (sub != SBO_ALLOC_FAIL)
return sbo_offset_raw(box->objlevel, (uint8_t)i) + sub;
}
Expand All @@ -408,15 +408,11 @@ static inline uint64_t sbo_find_alloc(sbo_meta_t *meta, sbo_box_t *box,
sbo_box_format(meta, ch, box->objlevel - 1, sbo_self_id(meta, box));
ch->slot_id = box->slot_id;

uint8_t nc = sbo_continuous_max(box);
if (box->max_obj_cap != nc) {
box->max_obj_cap = nc;
if (parent) sbo_update_parent(meta, parent, true, false);
}
sbo_update_parent(meta, box, true, true);

sbo_usage_t ch_max = {ch->objlevel + 1, 1};
if (sbo_usage_cmp(ch_max, usage) >= 0) {
uint64_t sub = sbo_find_alloc(meta, ch, box, usage);
uint64_t sub = sbo_find_alloc(meta, ch, usage);
if (sub != SBO_ALLOC_FAIL)
return sbo_offset_raw(box->objlevel, (uint8_t)slot) + sub;
}
Expand Down Expand Up @@ -482,6 +478,7 @@ int sbo_init(void *metaptr, size_t head_size, size_t data_size) {
meta->per_slot_meta = per_slot_meta;

for (uint8_t si = 0; si < root_slots; si++) {
atomic_init(&sbo_pool_lock(meta, si)->lock, 0);
void *pool_mem = sbo_pool_mem(meta, si);
blocks_init(sbo_pool_meta(meta, si), per_slot_meta, sizeof(sbo_box_t));

Expand Down Expand Up @@ -518,7 +515,7 @@ uint64_t sbo_alloc(void *metaptr, size_t size) {
sbo_box_t *root = (sbo_box_t *)((uint8_t *)sbo_pool_mem(meta, si)
+ meta->sizeof_block_head);
if (sbo_usage_cmp(sbo_box_and_child_max_cap(root), usage) >= 0) {
uint64_t off = sbo_find_alloc(meta, root, NULL, usage);
uint64_t off = sbo_find_alloc(meta, root, usage);
if (off != SBO_ALLOC_FAIL) {
uint64_t total = (uint64_t)si * meta->slot_bytes + off;
if (total + sbo_offset_of(usage) <= meta->data_size) {
Expand Down
13 changes: 8 additions & 5 deletions tutorial/03_stress.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@
#define SMALL_OBJ_SIZE 8 // 小对象大小 <=8byte

int main() {
const size_t data_size = 8ULL * 64 * 64 * 64 * 64;
// 初始化 slotsboxmalloc 的元数据和数据区,使用更大的内存池以支持高负载
uint8_t *buddy = malloc(4 * 1024 * 1024); // 元数据区,增大到4MB
uint8_t *data = malloc(64 * 1024 * 1024); // 数据区,增大到64MB
uint8_t *data = malloc(data_size);
if (!buddy || !data) {
perror("Failed to allocate memory for slotsboxmalloc");
return 1;
}

// 初始化 slotsboxmalloc
if (sbo_init(buddy, 4 * 1024 * 1024, 64 * 1024 * 1024) != 0) {
if (sbo_init(buddy, 4 * 1024 * 1024, data_size) != 0) {
printf("Failed to initialize slotsboxmalloc\n");
free(buddy);
free(data);
Expand Down Expand Up @@ -61,6 +62,7 @@ int main() {
printf("Phase 2: Starting random free/malloc loop (2s limit)...\n");
srand(time(NULL)); // 初始化随机种子
long long loop_count = 0;
int failed = 0;
clock_t start = clock();

while (1) {
Expand All @@ -77,7 +79,8 @@ int main() {
uint64_t new_offset = sbo_alloc(buddy, SMALL_OBJ_SIZE);
if (new_offset == (uint64_t)-1) {
printf("Re-allocation failed at loop %lld\n", loop_count);
break; // 如果分配失败,退出循环
failed = 1;
break;
}

// 更新指针数组
Expand All @@ -103,5 +106,5 @@ int main() {
free(buddy);
free(data);
printf("Stress test completed after %lld loops.\n", loop_count);
return 0;
}
return failed;
}
62 changes: 62 additions & 0 deletions tutorial/18_capacity.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <slotsboxmalloc/slotsboxobj.h>

static int exercise(void *meta, uint8_t *data, size_t data_size) {
uint64_t offsets[190];
size_t sizes[190];
int count = 0;
size_t size = data_size;
for (int depth = 0; depth < 3; depth++) {
size /= 64;
int n = depth == 2 ? 64 : 63;
for (int i = 0; i < n; i++) {
uint64_t off = sbo_alloc(meta, size);
if (off == UINT64_MAX || off + size > data_size ||
sbo_allocated_size(meta, off) != size)
return 2;
for (int j = 0; j < count; j++) {
if (off < offsets[j] + sizes[j] && offsets[j] < off + size)
return 3;
}
offsets[count] = off;
sizes[count] = size;
data[off] = data[off + size - 1] = (uint8_t)count;
count++;
}
}
if (sbo_alloc(meta, size) != UINT64_MAX)
return 4;

int hole = 143;
sbo_free(meta, offsets[hole]);
uint64_t replacement = sbo_alloc(meta, sizes[hole]);
if (replacement != offsets[hole])
return 5;
for (int i = 0; i < count; i++) {
if (i != hole && (data[offsets[i]] != (uint8_t)i ||
data[offsets[i] + sizes[i] - 1] != (uint8_t)i))
return 6;
sbo_free(meta, offsets[i]);
}
return 0;
}

int main(void) {
size_t data_size = 8ULL * 64 * 64 * 64 * 64;
size_t head_size = sbo_meta_size(data_size, 256 * 1024);
void *meta = malloc(head_size);
uint8_t *data = calloc(1, data_size);
int rc = 1;
if (meta)
memset(meta, 0xa5, head_size);
if (meta && data && sbo_init(meta, head_size, data_size) == 0)
rc = exercise(meta, data, data_size);
free(data);
free(meta);
if (rc == 0)
puts("capacity and reuse passed");
return rc;
}
5 changes: 5 additions & 0 deletions tutorial/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,8 @@ target_link_libraries(16_bench_malloc slotsboxmalloc Threads::Threads)

add_executable(17_data_integrity 17_data_integrity.c)
target_link_libraries(17_data_integrity slotsboxmalloc)
add_test(NAME 17_data_integrity COMMAND 17_data_integrity)

add_executable(18_capacity 18_capacity.c)
target_link_libraries(18_capacity slotsboxmalloc)
add_test(NAME 18_capacity COMMAND 18_capacity)