]> git.kaiwu.me - klib.git/commitdiff
update kalloc
authorAttractive Chaos <attractor@live.co.uk>
Mon, 3 Jun 2024 04:40:19 +0000 (00:40 -0400)
committerAttractive Chaos <attractor@live.co.uk>
Mon, 3 Jun 2024 04:40:19 +0000 (00:40 -0400)
kalloc.c
kalloc.h

index b36c333e4c1cd7ce7cedba3da6c61da45f93a4bd..f5de41ad62a078be1f99fbf18aa4a520cdd9239b 100644 (file)
--- a/kalloc.c
+++ b/kalloc.c
  *       |                           |                 |                               |
  *       p=p->ptr->ptr->ptr->ptr     p->ptr            p->ptr->ptr                     p->ptr->ptr->ptr
  */
-
-#define MIN_CORE_SIZE 0x80000
-
 typedef struct header_t {
        size_t size;
        struct header_t *ptr;
 } header_t;
 
 typedef struct {
+       void *par;
+       size_t min_core_size;
        header_t base, *loop_head, *core_head; /* base is a zero-sized block always kept in the loop */
 } kmem_t;
 
@@ -36,31 +35,40 @@ static void panic(const char *s)
        abort();
 }
 
-void *km_init(void)
+void *km_init2(void *km_par, size_t min_core_size)
 {
-       return calloc(1, sizeof(kmem_t));
+       kmem_t *km;
+       km = (kmem_t*)kcalloc(km_par, 1, sizeof(kmem_t));
+       km->par = km_par;
+       if (km_par) km->min_core_size = min_core_size > 0? min_core_size : ((kmem_t*)km_par)->min_core_size - 2;
+       else km->min_core_size = min_core_size > 0? min_core_size : 0x80000;
+       return (void*)km;
 }
 
+void *km_init(void) { return km_init2(0, 0); }
+
 void km_destroy(void *_km)
 {
        kmem_t *km = (kmem_t*)_km;
+       void *km_par;
        header_t *p, *q;
        if (km == NULL) return;
+       km_par = km->par;
        for (p = km->core_head; p != NULL;) {
                q = p->ptr;
-               free(p);
+               kfree(km_par, p);
                p = q;
        }
-       free(km);
+       kfree(km_par, km);
 }
 
 static header_t *morecore(kmem_t *km, size_t nu)
 {
        header_t *q;
        size_t bytes, *p;
-       nu = (nu + 1 + (MIN_CORE_SIZE - 1)) / MIN_CORE_SIZE * MIN_CORE_SIZE; /* the first +1 for core header */
+       nu = (nu + 1 + (km->min_core_size - 1)) / km->min_core_size * km->min_core_size; /* the first +1 for core header */
        bytes = nu * sizeof(header_t);
-       q = (header_t*)malloc(bytes);
+       q = (header_t*)kmalloc(km->par, bytes);
        if (!q) panic("[morecore] insufficient memory");
        q->ptr = km->core_head, q->size = nu, km->core_head = q;
        p = (size_t*)(q + 1);
@@ -125,7 +133,7 @@ void *kmalloc(void *_km, size_t n_bytes)
 
        if (n_bytes == 0) return 0;
        if (km == NULL) return malloc(n_bytes);
-       n_units = (n_bytes + sizeof(size_t) + sizeof(header_t) - 1) / sizeof(header_t) + 1;
+       n_units = (n_bytes + sizeof(size_t) + sizeof(header_t) - 1) / sizeof(header_t); /* header+n_bytes requires at least this number of units */
 
        if (!(q = km->loop_head)) /* the first time when kmalloc() is called, intialize it */
                q = km->loop_head = km->base.ptr = &km->base;
@@ -160,22 +168,32 @@ void *kcalloc(void *_km, size_t count, size_t size)
 void *krealloc(void *_km, void *ap, size_t n_bytes) // TODO: this can be made more efficient in principle
 {
        kmem_t *km = (kmem_t*)_km;
-       size_t n_units, *p, *q;
+       size_t cap, *p, *q;
 
        if (n_bytes == 0) {
                kfree(km, ap); return 0;
        }
        if (km == NULL) return realloc(ap, n_bytes);
        if (ap == NULL) return kmalloc(km, n_bytes);
-       n_units = (n_bytes + sizeof(size_t) + sizeof(header_t) - 1) / sizeof(header_t);
        p = (size_t*)ap - 1;
-       if (*p >= n_units) return ap; /* TODO: this prevents shrinking */
+       cap = (*p) * sizeof(header_t) - sizeof(size_t);
+       if (cap >= n_bytes) return ap; /* TODO: this prevents shrinking */
        q = (size_t*)kmalloc(km, n_bytes);
-       memcpy(q, ap, (*p - 1) * sizeof(header_t));
+       memcpy(q, ap, cap);
        kfree(km, ap);
        return q;
 }
 
+void *krelocate(void *km, void *ap, size_t n_bytes)
+{
+       void *p;
+       if (km == 0 || ap == 0) return ap;
+       p = kmalloc(km, n_bytes);
+       memcpy(p, ap, n_bytes);
+       kfree(km, ap);
+       return p;
+}
+
 void km_stat(const void *_km, km_stat_t *s)
 {
        kmem_t *km = (kmem_t*)_km;
@@ -196,3 +214,11 @@ void km_stat(const void *_km, km_stat_t *s)
                s->largest = s->largest > size? s->largest : size;
        }
 }
+
+void km_stat_print(const void *km)
+{
+       km_stat_t st;
+       km_stat(km, &st);
+       fprintf(stderr, "[km_stat] cap=%ld, avail=%ld, largest=%ld, n_core=%ld, n_block=%ld\n",
+                       st.capacity, st.available, st.largest, st.n_blocks, st.n_cores);
+}
index e891892994df3f124376071dbe809dfcda0ab337..437867238c60fd58171ddff85cc2a1d6c56f3267 100644 (file)
--- a/kalloc.h
+++ b/kalloc.h
@@ -13,15 +13,75 @@ typedef struct {
 
 void *kmalloc(void *km, size_t size);
 void *krealloc(void *km, void *ptr, size_t size);
+void *krelocate(void *km, void *ap, size_t n_bytes);
 void *kcalloc(void *km, size_t count, size_t size);
 void kfree(void *km, void *ptr);
 
 void *km_init(void);
+void *km_init2(void *km_par, size_t min_core_size);
 void km_destroy(void *km);
 void km_stat(const void *_km, km_stat_t *s);
+void km_stat_print(const void *km);
 
 #ifdef __cplusplus
 }
 #endif
 
+#define Kmalloc(km, type, cnt)       ((type*)kmalloc((km), (cnt) * sizeof(type)))
+#define Kcalloc(km, type, cnt)       ((type*)kcalloc((km), (cnt), sizeof(type)))
+#define Krealloc(km, type, ptr, cnt) ((type*)krealloc((km), (ptr), (cnt) * sizeof(type)))
+
+#define Kexpand(km, type, a, m) do { \
+               (m) = (m) >= 4? (m) + ((m)>>1) : 16; \
+               (a) = Krealloc(km, type, (a), (m)); \
+       } while (0)
+
+#define KMALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kmalloc((km), (len) * sizeof(*(ptr))))
+#define KCALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kcalloc((km), (len), sizeof(*(ptr))))
+#define KREALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))krealloc((km), (ptr), (len) * sizeof(*(ptr))))
+
+#define KEXPAND(km, a, m) do { \
+               (m) = (m) >= 4? (m) + ((m)>>1) : 16; \
+               KREALLOC((km), (a), (m)); \
+       } while (0)
+
+#ifndef klib_unused
+#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
+#define klib_unused __attribute__ ((__unused__))
+#else
+#define klib_unused
+#endif
+#endif /* klib_unused */
+
+#define KALLOC_POOL_INIT2(SCOPE, name, kmptype_t) \
+       typedef struct { \
+               size_t cnt, n, max; \
+               kmptype_t **buf; \
+               void *km; \
+       } kmp_##name##_t; \
+       SCOPE kmp_##name##_t *kmp_init_##name(void *km) { \
+               kmp_##name##_t *mp; \
+               mp = Kcalloc(km, kmp_##name##_t, 1); \
+               mp->km = km; \
+               return mp; \
+       } \
+       SCOPE void kmp_destroy_##name(kmp_##name##_t *mp) { \
+               size_t k; \
+               for (k = 0; k < mp->n; ++k) kfree(mp->km, mp->buf[k]); \
+               kfree(mp->km, mp->buf); kfree(mp->km, mp); \
+       } \
+       SCOPE kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \
+               ++mp->cnt; \
+               if (mp->n == 0) return (kmptype_t*)kcalloc(mp->km, 1, sizeof(kmptype_t)); \
+               return mp->buf[--mp->n]; \
+       } \
+       SCOPE void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \
+               --mp->cnt; \
+               if (mp->n == mp->max) Kexpand(mp->km, kmptype_t*, mp->buf, mp->max); \
+               mp->buf[mp->n++] = p; \
+       }
+
+#define KALLOC_POOL_INIT(name, kmptype_t) \
+       KALLOC_POOL_INIT2(static inline klib_unused, name, kmptype_t)
+
 #endif