From d84aff64209b63bd06b0c6f031c770dca5075db9 Mon Sep 17 00:00:00 2001 From: "Sergio R. Caprile" Date: Wed, 29 Oct 2025 15:51:42 -0300 Subject: [PATCH] Add memory management example, o1heap flavor --- tutorials/core/memory/o1heap/Makefile | 33 +++++++++++ tutorials/core/memory/o1heap/main.c | 77 +++++++++++++++++++++++++ tutorials/core/memory/o1heap/mongoose.c | 1 + tutorials/core/memory/o1heap/mongoose.h | 1 + 4 files changed, 112 insertions(+) create mode 100644 tutorials/core/memory/o1heap/Makefile create mode 100644 tutorials/core/memory/o1heap/main.c create mode 120000 tutorials/core/memory/o1heap/mongoose.c create mode 120000 tutorials/core/memory/o1heap/mongoose.h diff --git a/tutorials/core/memory/o1heap/Makefile b/tutorials/core/memory/o1heap/Makefile new file mode 100644 index 00000000..93d4c48e --- /dev/null +++ b/tutorials/core/memory/o1heap/Makefile @@ -0,0 +1,33 @@ +SOURCES = main.c mongoose.c # Source code files +CFLAGS = -W -Wall -Wextra -g -I. # Build options + +# O(1) Heap +SOURCES += o1heap/o1heap/o1heap.c +CFLAGS += -Io1heap/o1heap + +# Mongoose build options. See https://mongoose.ws/documentation/#build-options +CFLAGS_MONGOOSE += -DMG_ENABLE_CUSTOM_CALLOC + +ifeq ($(OS),Windows_NT) + # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD + PROG ?= example.exe # Use .exe suffix for the binary + CC = gcc # Use MinGW gcc compiler + CFLAGS += -lws2_32 # Link against Winsock library + DELETE = cmd /C del /f /q /s # Command prompt command to delete files +else + # Mac, Linux + PROG ?= example + DELETE = rm -rf +endif + +all: $(PROG) + $(RUN) ./$(PROG) $(ARGS) + +$(PROG): $(SOURCES) + $(CC) $(SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) -o $@ + +o1heap/o1heap/o1heap.c: # O(1) Heap sources + git clone --depth 1 -b 2.1.0 https://github.com/pavel-kirienko/o1heap.git + +clean: + $(DELETE) $(PROG) *.o *.obj *.exe *.dSYM diff --git a/tutorials/core/memory/o1heap/main.c b/tutorials/core/memory/o1heap/main.c new file mode 100644 index 00000000..8bf8afec --- /dev/null +++ b/tutorials/core/memory/o1heap/main.c @@ -0,0 +1,77 @@ +// Copyright (c) 2025 Cesanta Software Limited +// All rights reserved + +#include "mongoose.h" +#include "o1heap.h" + +#define POOL_SIZE (5 * MG_IO_SIZE) + +O1HeapInstance *s_mem; + +// memory allocation +void *mg_calloc(size_t count, size_t size) { + size_t bytes = count * size; + void *ptr = o1heapAllocate(s_mem, bytes); + if (ptr != NULL) memset(ptr, 0, bytes); + if (ptr != NULL) MG_DEBUG(("%lu bytes @%p", bytes, ptr)); + if (ptr == NULL) MG_ERROR(("Failed to allocate %lu bytes", bytes)); + return ptr; +} + +void mg_free(void *ptr) { + o1heapFree(s_mem, ptr); + if (ptr != NULL) MG_DEBUG(("block @%p", ptr)); +} + +// HTTP request callback +static void fn(struct mg_connection *c, int ev, void *ev_data) { + if (ev == MG_EV_HTTP_MSG) { + struct mg_http_message *hm = (struct mg_http_message *) ev_data; + if (mg_match(hm->uri, mg_str("/hi"), NULL)) { + mg_http_reply(c, 200, "Host: foo.com\r\n", "hi\n"); + } else if (mg_match(hm->uri, mg_str("/echo"), NULL)) { + mg_http_reply(c, 200, "", "%.*s", (int) hm->body.len, hm->body.buf); + } else if (mg_match(hm->uri, mg_str("/stats"), NULL)) { + struct mg_connection *t; + mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"); + mg_http_printf_chunk(c, "ID PROTO TYPE LOCAL REMOTE\n"); + for (t = c->mgr->conns; t != NULL; t = t->next) { + mg_http_printf_chunk(c, "%-3lu %4s %s %M %M\n", t->id, + t->is_udp ? "UDP" : "TCP", + t->is_listening ? "LISTENING" + : t->is_accepted ? "ACCEPTED " + : "CONNECTED", + mg_print_ip, &t->loc, mg_print_ip, &t->rem); + } + mg_http_printf_chunk(c, ""); // Don't forget the last empty chunk + } else { + struct mg_http_serve_opts opts; + memset(&opts, 0, sizeof(opts)); + opts.root_dir = "."; + mg_http_serve_dir(c, ev_data, &opts); + } + } +} + +int main(void) { + struct mg_mgr mgr; + + void *pool = malloc(POOL_SIZE + O1HEAP_ALIGNMENT); + void *aligned = (void *) (((uintptr_t) pool) & ~(O1HEAP_ALIGNMENT - 1)); + O1HeapDiagnostics d; + s_mem = o1heapInit(aligned, POOL_SIZE); + d = o1heapGetDiagnostics(s_mem); + MG_INFO( + ("Created aligned %lu-byte pool @%p, out of a %lu-byte allocated system " + "memory pool", + d.capacity, s_mem, POOL_SIZE)); + + mg_mgr_init(&mgr); // Initialise event manager + mg_log_set(MG_LL_DEBUG); // Set debug log level + mg_http_listen(&mgr, "http://localhost:8000", fn, NULL); // Create listener + for (;;) { // Event loop + mg_mgr_poll(&mgr, 1000); + } + mg_mgr_free(&mgr); + return 0; +} diff --git a/tutorials/core/memory/o1heap/mongoose.c b/tutorials/core/memory/o1heap/mongoose.c new file mode 120000 index 00000000..7a2752cb --- /dev/null +++ b/tutorials/core/memory/o1heap/mongoose.c @@ -0,0 +1 @@ +../../../../mongoose.c \ No newline at end of file diff --git a/tutorials/core/memory/o1heap/mongoose.h b/tutorials/core/memory/o1heap/mongoose.h new file mode 120000 index 00000000..daff1633 --- /dev/null +++ b/tutorials/core/memory/o1heap/mongoose.h @@ -0,0 +1 @@ +../../../../mongoose.h \ No newline at end of file