summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xreduced_system_layer.c94
-rwxr-xr-xstackless_coroutine.c98
2 files changed, 127 insertions, 65 deletions
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 847edae..b1bb8ce 100755
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -775,25 +775,16 @@ void run_main_window_event_loop(void) {
//
// ================================================================
-enum {
- OCCUPIED_SIZE_ = (STATIC_MEMORY_BUFFER_SIZE + 64 * MEMORY_CHUNK_SIZE - 1) / (64 * MEMORY_CHUNK_SIZE),
-};
-
-typedef struct {
- i64 next_chunk;
- u64 occupied[OCCUPIED_SIZE_];
-} Memory_Buffer_Header_;
-
static u8 memory_buffer_[STATIC_MEMORY_BUFFER_SIZE] = {0};
-static i64 num_memory_slots_(void) {
- return *(i64 *) &g_platform.memory_buffer[g_platform.memory_buffer_size - 8];
-}
-
static i64 align_(i64 x, i64 alignment) {
return ((x + (alignment - 1)) / alignment) * alignment;
}
+static i64 memory_buffer_occupied_len_(i64 buffer_size) {
+ return (buffer_size + 64 * MEMORY_CHUNK_SIZE - 1) / (64 * MEMORY_CHUNK_SIZE);
+}
+
void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *previous_data) {
if (g_platform.memory_buffer_size < 0) {
LOG_ERROR("Invalid memory buffer size.");
@@ -810,32 +801,62 @@ void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *p
g_platform.memory_buffer = memory_buffer_;
}
- if (g_platform.memory_buffer_size <= (i64) sizeof(Memory_Buffer_Header_)) {
+ i64 occupied_len = memory_buffer_occupied_len_(g_platform.memory_buffer_size);
+ u64 *occupied = (u64 *) g_platform.memory_buffer;
+
+ if (g_platform.memory_buffer_size <= occupied_len * 64) {
LOG_ERROR("Memory buffer too small.");
return NULL;
}
- Memory_Buffer_Header_ *h = (Memory_Buffer_Header_ *) g_platform.memory_buffer;
- u8 * data = g_platform.memory_buffer + sizeof(Memory_Buffer_Header_);
+ if (alignment <= 0) {
+ LOG_ERROR("Invalid alignment: %lld", alignment);
+ return NULL;
+ }
+
+ if (size < 0) {
+ LOG_ERROR("Invalid size: %lld", size);
+ return NULL;
+ }
+
+ if (previous_size < 0) {
+ LOG_ERROR("Invalid previous size: %lld", previous_size);
+ return NULL;
+ }
+
+ if (previous_size > 0 && previous_data == NULL) {
+ LOG_ERROR("Invalid previous data.");
+ return NULL;
+ }
- i64 prev_num_chunks = (align_(previous_size, alignment) + MEMORY_CHUNK_SIZE - 1) / MEMORY_CHUNK_SIZE;
- i64 prev_chunk = ((u8 *) previous_data - data) / MEMORY_CHUNK_SIZE;
+ u8 *data = g_platform.memory_buffer + occupied_len * 64;
- i64 num_chunks = (align_(size, alignment) + MEMORY_CHUNK_SIZE - 1) / MEMORY_CHUNK_SIZE;
- i64 chunk = 0;
+ i64 prev_num_chunks = 0;
+ i64 prev_chunk = 0;
+
+ if (previous_size > 0) {
+ prev_num_chunks = (align_(previous_size, alignment) + MEMORY_CHUNK_SIZE - 1) / MEMORY_CHUNK_SIZE;
+ prev_chunk = ((u8 *) previous_data - data) / MEMORY_CHUNK_SIZE;
+ }
- // Find free space
- for (i64 i = h->next_chunk; i < OCCUPIED_SIZE_ * 64; ++i) {
- b8 occupied = 0;
+ i64 num_chunks = (align_(size, alignment) + MEMORY_CHUNK_SIZE - 1) / MEMORY_CHUNK_SIZE;
+ i64 chunk = (g_platform.memory_buffer_size + MEMORY_CHUNK_SIZE - 1) / MEMORY_CHUNK_SIZE;
+
+ // Search free space
+ i64 i0 = 0;
+ while (i0 < occupied_len && occupied[i0] == ~0ull)
+ ++i0;
+ for (i64 i = i0; i < occupied_len * 64; ++i) {
+ b8 is_occupied = 0;
for (i64 j = i; j < i + num_chunks; ++j) {
if (j >= prev_chunk && j < prev_chunk + prev_num_chunks) continue;
- if ((h->occupied[j / 64] & (1ull << (j % 64))) == 0) continue;
- occupied = 1;
+ if ((occupied[j / 64] & (1ull << (j % 64))) == 0) continue;
+ is_occupied = 1;
break;
}
- if (occupied) {
+ if (is_occupied) {
chunk = i;
break;
}
@@ -846,14 +867,14 @@ void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *p
i64 len = size < previous_size ? size : previous_size;
// Check if out of memory
- if (data + size > g_platform.memory_buffer + g_platform.memory_buffer_size) {
+ if (dst + size > g_platform.memory_buffer + g_platform.memory_buffer_size) {
LOG_ERROR("Out of memory.");
return NULL;
}
// Claim required space
for (i64 j = chunk; j < chunk + num_chunks; ++j)
- h->occupied[j / 64] |= 1ull << (j % 64);
+ occupied[j / 64] |= 1ull << (j % 64);
// Copy data
if (dst > src)
@@ -866,7 +887,7 @@ void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *p
// Free previous space
for (i64 j = prev_chunk; j < prev_chunk + prev_num_chunks; ++j) {
if (j >= chunk && j < chunk + num_chunks) continue;
- h->occupied[j / 64] &= ~(1ull << (j % 64));
+ occupied[j / 64] &= ~(1ull << (j % 64));
}
if (num_chunks == 0)
@@ -875,6 +896,21 @@ void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *p
return dst;
}
+void memory_buffer_wrap(i64 *num, void **data, i64 element_size, i64 new_num) {
+ void *new_data = memory_buffer_allocate(
+ new_num * element_size,
+ element_size,
+ *num * element_size,
+ *data
+ );
+
+ if (new_data == NULL && new_num > 0)
+ return;
+
+ *num = new_num;
+ *data = new_data;
+}
+
// ================================================================
//
// BLAKE2B
diff --git a/stackless_coroutine.c b/stackless_coroutine.c
index cbd02f9..27a1123 100755
--- a/stackless_coroutine.c
+++ b/stackless_coroutine.c
@@ -123,7 +123,7 @@ static void stackless_coroutine_dispatch(void *promise) {
# pragma GCC diagnostic pop
#endif
-#define CORO_PROMISE_STRUCT_(Ret_Type_, coro_, ...) \
+#define CORO_PROMISE_STRUCT_(coro_, Ret_Type_, ...) \
struct Coro_Promise_##coro_ { \
CORO_PROMISE_DATA_; \
Ret_Type_ return_value; \
@@ -147,30 +147,30 @@ static void stackless_coroutine_dispatch(void *promise) {
self->_index = -1; \
}
-#define CORO_DECL(Ret_Type_, coro_, ...) \
- CORO_PROMISE_STRUCT_(Ret_Type_, coro_, __VA_ARGS__); \
+#define CORO_DECL(coro_, Ret_Type_, ...) \
+ CORO_PROMISE_STRUCT_(coro_, Ret_Type_, __VA_ARGS__); \
CORO_PROC_DECL_(coro_)
-#define CORO_DECL_STATIC(Ret_Type_, coro_, ...) \
- CORO_PROMISE_STRUCT_(Ret_Type_, coro_, __VA_ARGS__); \
+#define CORO_DECL_STATIC(coro_, Ret_Type_, ...) \
+ CORO_PROMISE_STRUCT_(coro_, Ret_Type_, __VA_ARGS__); \
static CORO_PROC_DECL_(coro_)
-#define CORO(Ret_Type_, coro_, ...) \
- CORO_PROMISE_STRUCT_(Ret_Type_, coro_, __VA_ARGS__); \
+#define CORO(coro_, Ret_Type_, ...) \
+ CORO_PROMISE_STRUCT_(coro_, Ret_Type_, __VA_ARGS__); \
CORO_IMPL(coro_)
#define CORO_DECL_VOID(coro_, ...) \
- CORO_DECL(Coro_Void_, coro_, __VA_ARGS__)
+ CORO_DECL(coro_, Coro_Void_, __VA_ARGS__)
#define CORO_VOID(coro_, ...) \
- CORO(Coro_Void_, coro_, __VA_ARGS__)
+ CORO(coro_, Coro_Void_, __VA_ARGS__)
-#define CORO_STATIC(Ret_Type_, coro_, ...) \
- CORO_PROMISE_STRUCT_(Ret_Type_, coro_, __VA_ARGS__); \
+#define CORO_STATIC(coro_, Ret_Type_, ...) \
+ CORO_PROMISE_STRUCT_(coro_, Ret_Type_, __VA_ARGS__); \
static CORO_IMPL(coro_)
#define CORO_STATIC_VOID(coro_, ...) \
- CORO_STATIC(Coro_Void_, coro_, __VA_ARGS__)
+ CORO_STATIC(coro_, Coro_Void_, __VA_ARGS__)
#define coro_resume(promise_) \
stackless_coroutine_dispatch(&(promise_))
@@ -285,11 +285,16 @@ static void stackless_coroutine_dispatch(void *promise) {
#define TEST_FILE stackless_coroutine
#include "test.c"
-CORO_DECL(int, test_foo, );
+CORO_DECL(
+ test_foo,
+ int,
+);
-CORO_IMPL(test_foo) {
- async_return(42);
-} CORO_END
+CORO_IMPL(test_foo)
+{
+ async_return (42);
+}
+CORO_END
TEST("coroutine init") {
Promise_Of(test_foo) promise;
@@ -311,12 +316,17 @@ TEST("coroutine execute and return") {
REQUIRE(coro_finished(promise));
}
-CORO_DECL_STATIC(int, test_bar, );
+CORO_DECL_STATIC(
+ test_bar,
+ int,
+);
-CORO_IMPL(test_bar) {
+CORO_IMPL(test_bar)
+{
yield_void;
- async_return(42);
-} CORO_END
+ async_return (42);
+}
+CORO_END
TEST("coroutine execute two steps") {
Promise_Of(test_bar) promise;
@@ -327,17 +337,22 @@ TEST("coroutine execute two steps") {
REQUIRE(promise.return_value == 42);
}
-CORO_STATIC(int, test_gen, int i; int min; int max;) {
+CORO_STATIC(
+ test_gen,
+ int,
+ int i; int min; int max;
+) {
for (self->i = self->min; self->i < self->max; self->i++)
- yield(self->i);
- async_return(self->max);
-} CORO_END
+ yield (self->i);
+ async_return (self->max);
+}
+CORO_END
TEST("coroutine generator") {
- int i;
Promise_Of(test_gen) promise;
CORO_INIT(promise, test_gen, .min = 10, .max = 15);
- for (i = 0; i <= 5; i++) REQUIRE(coro_next(promise) == 10 + i);
+ for (i32 i = 0; i <= 5; i++)
+ REQUIRE(coro_next(promise) == 10 + i);
}
TEST("coroutine status finished") {
@@ -350,11 +365,13 @@ TEST("coroutine status finished") {
REQUIRE(coro_finished(promise));
}
-CORO_STATIC_VOID(test_task, ) {
+CORO_STATIC_VOID(test_task, )
+{
yield_void;
yield_void;
async_return_void;
-} CORO_END
+}
+CORO_END
TEST("coroutine task") {
Promise_Of(test_task) promise;
@@ -367,12 +384,16 @@ TEST("coroutine task") {
REQUIRE(coro_finished(promise));
}
-CORO_STATIC_VOID(test_nest_task, Promise_Of(test_task) promise;) {
+CORO_STATIC_VOID(
+ test_nest_task,
+ Promise_Of(test_task) promise;
+) {
CORO_INIT(self->promise, test_task, );
- await(self->promise);
- await(self->promise);
- await(self->promise);
-} CORO_END
+ await (self->promise);
+ await (self->promise);
+ await (self->promise);
+}
+CORO_END
TEST("coroutine nested task") {
Promise_Of(test_nest_task) promise;
@@ -385,10 +406,15 @@ TEST("coroutine nested task") {
REQUIRE(coro_finished(promise));
}
-CORO_STATIC(int, test_nest_generator, Promise_Of(test_gen) promise;) {
+CORO_STATIC(
+ test_nest_generator,
+ int,
+ Promise_Of(test_gen) promise;
+) {
CORO_INIT(self->promise, test_gen, .min = 1, .max = 3);
- yield_await(self->promise);
-} CORO_END
+ yield_await (self->promise);
+}
+CORO_END
TEST("coroutine nested generator") {
Promise_Of(test_nest_generator) promise;