]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/third_party/duktape-1.5.2/examples/alloc-hybrid/duk_alloc_hybrid.c
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / third_party / prometheus-cpp / 3rdparty / civetweb / src / third_party / duktape-1.5.2 / examples / alloc-hybrid / duk_alloc_hybrid.c
diff --git a/ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/third_party/duktape-1.5.2/examples/alloc-hybrid/duk_alloc_hybrid.c b/ceph/src/jaegertracing/opentelemetry-cpp/third_party/prometheus-cpp/3rdparty/civetweb/src/third_party/duktape-1.5.2/examples/alloc-hybrid/duk_alloc_hybrid.c
new file mode 100644 (file)
index 0000000..9235b85
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ *  Example memory allocator with pool allocation for small sizes and
+ *  fallback into malloc/realloc/free for larger sizes or when the pools
+ *  are exhausted.
+ *
+ *  Useful to reduce memory churn or work around a platform allocator
+ *  that doesn't handle a lot of small allocations efficiently.
+ */
+
+#include "duktape.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+/* Define to enable some debug printfs. */
+/* #define DUK_ALLOC_HYBRID_DEBUG */
+
+typedef struct {
+       size_t size;
+       int count;
+} pool_size_spec;
+
+static pool_size_spec pool_sizes[] = {
+       { 32, 1024 },
+       { 48, 2048 },
+       { 64, 2048 },
+       { 128, 2048 },
+       { 256, 512 },
+       { 1024, 64 },
+       { 2048, 32 }
+};
+
+#define  NUM_POOLS  (sizeof(pool_sizes) / sizeof(pool_size_spec))
+
+/* This must fit into the smallest pool entry. */
+struct pool_free_entry;
+typedef struct pool_free_entry pool_free_entry;
+struct pool_free_entry {
+       pool_free_entry *next;
+};
+
+typedef struct {
+       pool_free_entry *free;
+       char *alloc_start;
+       char *alloc_end;
+       size_t size;
+       int count;
+} pool_header;
+
+typedef struct {
+       pool_header headers[NUM_POOLS];
+       size_t pool_max_size;
+       char *alloc_start;
+       char *alloc_end;
+} pool_state;
+
+#define ADDR_IN_STATE_ALLOC(st,p) \
+       ((char *) (p) >= (st)->alloc_start && (char *) (p) < (st)->alloc_end)
+#define ADDR_IN_HEADER_ALLOC(hdr,p) \
+       ((char *) (p) >= (hdr)->alloc_start && (char *) (p) < (hdr)->alloc_end)
+
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+static void dump_pool_state(pool_state *st) {
+       pool_free_entry *free;
+       int free_len;
+       int i;
+
+       printf("=== Pool state: st=%p\n", (void *) st);
+       for (i = 0; i < (int) NUM_POOLS; i++) {
+               pool_header *hdr = st->headers + i;
+
+               for (free = hdr->free, free_len = 0; free != NULL; free = free->next) {
+                       free_len++;
+               }
+
+               printf("[%d]: size %ld, count %ld, used %ld, free list len %ld\n",
+                      i, (long) hdr->size, (long) hdr->count,
+                      (long) (hdr->count - free_len),
+                      (long) free_len);
+       }
+}
+#else
+static void dump_pool_state(pool_state *st) {
+       (void) st;
+}
+#endif
+
+void *duk_alloc_hybrid_init(void) {
+       pool_state *st;
+       size_t total_size, max_size;
+       int i, j;
+       char *p;
+
+       st = (pool_state *) malloc(sizeof(pool_state));
+       if (!st) {
+               return NULL;
+       }
+       memset((void *) st, 0, sizeof(pool_state));
+       st->alloc_start = NULL;
+       st->alloc_end = NULL;
+
+       for (i = 0, total_size = 0, max_size = 0; i < (int) NUM_POOLS; i++) {
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+               printf("Pool %d: size %ld, count %ld\n", i, (long) pool_sizes[i].size, (long) pool_sizes[i].count);
+#endif
+               total_size += pool_sizes[i].size * pool_sizes[i].count;
+               if (pool_sizes[i].size > max_size) {
+                       max_size = pool_sizes[i].size;
+               }
+       }
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+       printf("Total size %ld, max pool size %ld\n", (long) total_size, (long) max_size);
+#endif
+
+       st->alloc_start = (char *) malloc(total_size);
+       if (!st->alloc_start) {
+               free(st);
+               return NULL;
+       }
+       st->alloc_end = st->alloc_start + total_size;
+       st->pool_max_size = max_size;
+       memset((void *) st->alloc_start, 0, total_size);
+
+       for (i = 0, p = st->alloc_start; i < (int) NUM_POOLS; i++) {
+               pool_header *hdr = st->headers + i;
+
+               hdr->alloc_start = p;
+               hdr->alloc_end = p + pool_sizes[i].size * pool_sizes[i].count;
+               hdr->free = (pool_free_entry *) (void *) p;
+               hdr->size = pool_sizes[i].size;
+               hdr->count = pool_sizes[i].count;
+
+               for (j = 0; j < pool_sizes[i].count; j++) {
+                       pool_free_entry *ent = (pool_free_entry *) (void *) p;
+                       if (j == pool_sizes[i].count - 1) {
+                               ent->next = (pool_free_entry *) NULL;
+                       } else {
+                               ent->next = (pool_free_entry *) (void *) (p + pool_sizes[i].size);
+                       }
+                       p += pool_sizes[i].size;
+               }
+       }
+
+       dump_pool_state(st);
+
+       /* Use 'st' as udata. */
+       return (void *) st;
+}
+
+void *duk_alloc_hybrid(void *udata, duk_size_t size) {
+       pool_state *st = (pool_state *) udata;
+       int i;
+       void *new_ptr;
+
+#if 0
+       dump_pool_state(st);
+#endif
+
+       if (size == 0) {
+               return NULL;
+       }
+       if (size > st->pool_max_size) {
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+               printf("alloc fallback: %ld\n", (long) size);
+#endif
+               return malloc(size);
+       }
+
+       for (i = 0; i < (int) NUM_POOLS; i++) {
+               pool_header *hdr = st->headers + i;
+               if (hdr->size < size) {
+                       continue;
+               }
+
+               if (hdr->free) {
+#if 0
+                       printf("alloc from pool: %ld -> pool size %ld\n", (long) size, (long) hdr->size);
+#endif
+                       new_ptr = (void *) hdr->free;
+                       hdr->free = hdr->free->next;
+                       return new_ptr;
+               } else {
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+                       printf("alloc out of pool entries: %ld -> pool size %ld\n", (long) size, (long) hdr->size);
+#endif
+                       break;
+               }
+       }
+
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+       printf("alloc fallback (out of pool): %ld\n", (long) size);
+#endif
+       return malloc(size);
+}
+
+void *duk_realloc_hybrid(void *udata, void *ptr, duk_size_t size) {
+       pool_state *st = (pool_state *) udata;
+       void *new_ptr;
+       int i;
+
+#if 0
+       dump_pool_state(st);
+#endif
+
+       if (ADDR_IN_STATE_ALLOC(st, ptr)) {
+               /* 'ptr' cannot be NULL. */
+               for (i = 0; i < (int) NUM_POOLS; i++) {
+                       pool_header *hdr = st->headers + i;
+                       if (ADDR_IN_HEADER_ALLOC(hdr, ptr)) {
+                               if (size <= hdr->size) {
+                                       /* Still fits, no shrink support. */
+#if 0
+                                       printf("realloc original from pool: still fits, size %ld, pool size %ld\n",
+                                              (long) size, (long) hdr->size);
+#endif
+                                       return ptr;
+                               }
+
+                               new_ptr = duk_alloc_hybrid(udata, size);
+                               if (!new_ptr) {
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+                                       printf("realloc original from pool: needed larger size, failed to alloc\n");
+#endif
+                                       return NULL;
+                               }
+                               memcpy(new_ptr, ptr, hdr->size);
+
+                               ((pool_free_entry *) ptr)->next = hdr->free;
+                               hdr->free = (pool_free_entry *) ptr;
+#if 0
+                               printf("realloc original from pool: size %ld, pool size %ld\n", (long) size, (long) hdr->size);
+#endif
+                               return new_ptr;
+                       }
+               }
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+               printf("NEVER HERE\n");
+#endif
+               return NULL;
+       } else if (ptr != NULL) {
+               if (size == 0) {
+                       free(ptr);
+                       return NULL;
+               } else {
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+                       printf("realloc fallback: size %ld\n", (long) size);
+#endif
+                       return realloc(ptr, size);
+               }
+       } else {
+#if 0
+               printf("realloc NULL ptr, call alloc: %ld\n", (long) size);
+#endif
+               return duk_alloc_hybrid(udata, size);
+       }
+}
+
+void duk_free_hybrid(void *udata, void *ptr) {
+       pool_state *st = (pool_state *) udata;
+       int i;
+
+#if 0
+       dump_pool_state(st);
+#endif
+
+       if (!ADDR_IN_STATE_ALLOC(st, ptr)) {
+               if (ptr == NULL) {
+                       return;
+               }
+#if 0
+               printf("free out of pool: %p\n", (void *) ptr);
+#endif
+               free(ptr);
+               return;
+       }
+
+       for (i = 0; i < (int) NUM_POOLS; i++) {
+               pool_header *hdr = st->headers + i;
+               if (ADDR_IN_HEADER_ALLOC(hdr, ptr)) {
+                       ((pool_free_entry *) ptr)->next = hdr->free;
+                       hdr->free = (pool_free_entry *) ptr;
+#if 0
+                       printf("free from pool: %p\n", ptr);
+#endif
+                       return;
+               }
+       }
+
+#ifdef DUK_ALLOC_HYBRID_DEBUG
+       printf("NEVER HERE\n");
+#endif
+}