| @@ -0,0 +1,28 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| int sm_alloc_valid_pool(struct smalloc_pool *spool, const void *p) | |||
| { | |||
| struct smalloc_hdr *shdr; | |||
| if (!smalloc_verify_pool(spool)) { | |||
| errno = EINVAL; | |||
| return 0; | |||
| } | |||
| if (!p) return 0; | |||
| shdr = USER_TO_HEADER(p); | |||
| if (smalloc_is_alloc(spool, shdr)) return 1; | |||
| return 0; | |||
| } | |||
| int sm_alloc_valid(const void *p) | |||
| { | |||
| return sm_alloc_valid_pool(&smalloc_curr_pool, p); | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| void *sm_calloc_pool(struct smalloc_pool *spool, size_t x, size_t y) | |||
| { | |||
| return sm_zalloc_pool(spool, x * y); | |||
| } | |||
| void *sm_calloc(size_t x, size_t y) | |||
| { | |||
| return sm_calloc_pool(&smalloc_curr_pool, x, y); | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| void sm_free_pool(struct smalloc_pool *spool, void *p) | |||
| { | |||
| struct smalloc_hdr *shdr; | |||
| char *s; | |||
| if (!smalloc_verify_pool(spool)) { | |||
| errno = EINVAL; | |||
| return; | |||
| } | |||
| if (!p) return; | |||
| shdr = USER_TO_HEADER(p); | |||
| if (smalloc_is_alloc(spool, shdr)) { | |||
| if (spool->do_zero) memset(p, 0, shdr->rsz); | |||
| s = CHAR_PTR(p); | |||
| s += shdr->usz; | |||
| memset(s, 0, HEADER_SZ); | |||
| if (spool->do_zero) memset(s+HEADER_SZ, 0, shdr->rsz - shdr->usz); | |||
| memset(shdr, 0, HEADER_SZ); | |||
| return; | |||
| } | |||
| smalloc_UB(spool, p); | |||
| return; | |||
| } | |||
| void sm_free(void *p) | |||
| { | |||
| sm_free_pool(&smalloc_curr_pool, p); | |||
| } | |||
| @@ -0,0 +1,40 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| /* An adopted Jenkins one-at-a-time hash */ | |||
| #define UIHOP(x, s) do { \ | |||
| hash += (x >> s) & 0xff;\ | |||
| hash += hash << 10; \ | |||
| hash ^= hash >> 6; \ | |||
| } while (0) | |||
| uintptr_t smalloc_uinthash(uintptr_t x) | |||
| { | |||
| uintptr_t hash = 0; | |||
| UIHOP(x, 0); | |||
| UIHOP(x, 8); | |||
| UIHOP(x, 16); | |||
| UIHOP(x, 24); | |||
| hash += hash << 3; | |||
| hash ^= hash >> 11; | |||
| hash += hash << 15; | |||
| return hash; | |||
| } | |||
| #undef UIHOP | |||
| uintptr_t smalloc_mktag(struct smalloc_hdr *shdr) | |||
| { | |||
| uintptr_t r = smalloc_uinthash(PTR_UINT(shdr)); | |||
| r += shdr->rsz; | |||
| r = smalloc_uinthash(r); | |||
| r += shdr->usz; | |||
| r = smalloc_uinthash(r); | |||
| return r; | |||
| } | |||
| @@ -0,0 +1,108 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| void *sm_malloc_pool(struct smalloc_pool *spool, size_t n) | |||
| { | |||
| struct smalloc_hdr *basehdr, *shdr, *dhdr; | |||
| char *s; | |||
| int found; | |||
| size_t x; | |||
| again: if (!smalloc_verify_pool(spool)) { | |||
| errno = EINVAL; | |||
| return NULL; | |||
| } | |||
| if (n == 0) n++; /* return a block successfully */ | |||
| if (n > SIZE_MAX | |||
| || n > (spool->pool_size - HEADER_SZ)) goto oom; | |||
| shdr = basehdr = spool->pool; | |||
| while (CHAR_PTR(shdr)-CHAR_PTR(basehdr) < spool->pool_size) { | |||
| /* | |||
| * Already allocated block. | |||
| * Skip it by jumping over it. | |||
| */ | |||
| if (smalloc_is_alloc(spool, shdr)) { | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += shdr->rsz + HEADER_SZ; | |||
| shdr = HEADER_PTR(s); | |||
| continue; | |||
| } | |||
| /* | |||
| * Free blocks ahead! | |||
| * Do a second search over them to find out if they're | |||
| * really large enough to fit the new allocation. | |||
| */ | |||
| else { | |||
| dhdr = shdr; found = 0; | |||
| while (CHAR_PTR(dhdr)-CHAR_PTR(basehdr) < spool->pool_size) { | |||
| /* pre calculate free block size */ | |||
| x = CHAR_PTR(dhdr)-CHAR_PTR(shdr); | |||
| /* | |||
| * ugh, found next allocated block. | |||
| * skip this candidate then. | |||
| */ | |||
| if (smalloc_is_alloc(spool, dhdr)) | |||
| goto allocblock; | |||
| /* | |||
| * did not see allocated block yet, | |||
| * but this free block is of enough size | |||
| * - finally, use it. | |||
| */ | |||
| if (n + HEADER_SZ <= x) { | |||
| x -= HEADER_SZ; | |||
| found = 1; | |||
| goto outfound; | |||
| } | |||
| dhdr++; | |||
| } | |||
| outfound: if (found) { | |||
| uintptr_t tag; | |||
| /* allocate and return this block */ | |||
| shdr->rsz = x; | |||
| shdr->usz = n; | |||
| shdr->tag = tag = smalloc_mktag(shdr); | |||
| if (spool->do_zero) memset(HEADER_TO_USER(shdr), 0, shdr->rsz); | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += shdr->usz; | |||
| for (x = 0; | |||
| x < sizeof(struct smalloc_hdr); | |||
| x += sizeof(uintptr_t)) { | |||
| tag = smalloc_uinthash(tag); | |||
| memcpy(s+x, &tag, sizeof(uintptr_t)); | |||
| } | |||
| memset(s+x, 0xff, shdr->rsz - shdr->usz); | |||
| return HEADER_TO_USER(shdr); | |||
| } | |||
| /* continue first search for next free block */ | |||
| allocblock: shdr = dhdr; | |||
| continue; | |||
| } | |||
| shdr++; | |||
| } | |||
| oom: if (spool->oomfn) { | |||
| x = spool->oomfn(spool, n); | |||
| if (x > spool->pool_size) { | |||
| spool->pool_size = x; | |||
| if (sm_align_pool(spool)) goto again; | |||
| } | |||
| } | |||
| errno = ENOMEM; | |||
| return NULL; | |||
| } | |||
| void *sm_malloc(size_t n) | |||
| { | |||
| return sm_malloc_pool(&smalloc_curr_pool, n); | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| int sm_malloc_stats_pool(struct smalloc_pool *spool, size_t *total, size_t *user, size_t *free, int *nr_blocks) | |||
| { | |||
| struct smalloc_hdr *shdr, *basehdr; | |||
| int r = 0; | |||
| if (!smalloc_verify_pool(spool)) { | |||
| errno = EINVAL; | |||
| return -1; | |||
| } | |||
| if (!total && !user && !free && !nr_blocks) return 0; | |||
| if (total) *total = 0; | |||
| if (user) *user = 0; | |||
| if (free) *free = 0; | |||
| if (nr_blocks) *nr_blocks = 0; | |||
| shdr = basehdr = spool->pool; | |||
| while (CHAR_PTR(shdr)-CHAR_PTR(basehdr) < spool->pool_size) { | |||
| if (smalloc_is_alloc(spool, shdr)) { | |||
| if (total) *total += HEADER_SZ + shdr->rsz + HEADER_SZ; | |||
| if (user) *user += shdr->usz; | |||
| if (nr_blocks) *nr_blocks += 1; | |||
| r = 1; | |||
| } | |||
| shdr++; | |||
| } | |||
| *free = spool->pool_size - *total; | |||
| return r; | |||
| } | |||
| int sm_malloc_stats(size_t *total, size_t *user, size_t *free, int *nr_blocks) | |||
| { | |||
| return sm_malloc_stats_pool(&smalloc_curr_pool, total, user, free, nr_blocks); | |||
| } | |||
| @@ -0,0 +1,78 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| struct smalloc_pool smalloc_curr_pool; | |||
| int smalloc_verify_pool(struct smalloc_pool *spool) | |||
| { | |||
| if (!spool->pool || !spool->pool_size) return 0; | |||
| if (spool->pool_size % HEADER_SZ) return 0; | |||
| return 1; | |||
| } | |||
| int sm_align_pool(struct smalloc_pool *spool) | |||
| { | |||
| size_t x; | |||
| if (smalloc_verify_pool(spool)) return 1; | |||
| x = spool->pool_size % HEADER_SZ; | |||
| if (x) spool->pool_size -= x; | |||
| if (spool->pool_size <= MIN_POOL_SZ) { | |||
| errno = ENOSPC; | |||
| return 0; | |||
| } | |||
| return 1; | |||
| } | |||
| int sm_set_pool(struct smalloc_pool *spool, void *new_pool, size_t new_pool_size, int do_zero, smalloc_oom_handler oom_handler) | |||
| { | |||
| if (!spool) { | |||
| errno = EINVAL; | |||
| return 0; | |||
| } | |||
| if (!new_pool || !new_pool_size) { | |||
| if (smalloc_verify_pool(spool)) { | |||
| if (spool->do_zero) memset(spool->pool, 0, spool->pool_size); | |||
| memset(spool, 0, sizeof(struct smalloc_pool)); | |||
| return 1; | |||
| } | |||
| errno = EINVAL; | |||
| return 0; | |||
| } | |||
| spool->pool = new_pool; | |||
| spool->pool_size = new_pool_size; | |||
| spool->oomfn = oom_handler; | |||
| if (!sm_align_pool(spool)) return 0; | |||
| if (do_zero) { | |||
| spool->do_zero = do_zero; | |||
| memset(spool->pool, 0, spool->pool_size); | |||
| } | |||
| return 1; | |||
| } | |||
| int sm_set_default_pool(void *new_pool, size_t new_pool_size, int do_zero, smalloc_oom_handler oom_handler) | |||
| { | |||
| return sm_set_pool(&smalloc_curr_pool, new_pool, new_pool_size, do_zero, oom_handler); | |||
| } | |||
| int sm_release_pool(struct smalloc_pool *spool) | |||
| { | |||
| return sm_set_pool(spool, NULL, 0, 0, NULL); | |||
| } | |||
| int sm_release_default_pool(void) | |||
| { | |||
| return sm_release_pool(&smalloc_curr_pool); | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| void *sm_realloc_pool(struct smalloc_pool *spool, void *p, size_t n) | |||
| { | |||
| return sm_realloc_pool_i(spool, p, n, 0); | |||
| } | |||
| void *sm_realloc(void *p, size_t n) | |||
| { | |||
| return sm_realloc_pool_i(&smalloc_curr_pool, p, n, 0); | |||
| } | |||
| @@ -0,0 +1,128 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| /* | |||
| * Please do NOT use this function directly or rely on it's presence. | |||
| * It may go away in future SMalloc versions, or it's calling | |||
| * signature may change. It is internal function, hence "_i" suffix. | |||
| */ | |||
| void *sm_realloc_pool_i(struct smalloc_pool *spool, void *p, size_t n, int nomove) | |||
| { | |||
| struct smalloc_hdr *basehdr, *shdr, *dhdr; | |||
| void *r; | |||
| char *s; | |||
| int found; | |||
| size_t rsz, usz, x; | |||
| uintptr_t tag; | |||
| if (!smalloc_verify_pool(spool)) { | |||
| errno = EINVAL; | |||
| return NULL; | |||
| } | |||
| if (!p) return sm_malloc_pool(spool, n); | |||
| if (!n && p) { | |||
| sm_free_pool(spool, p); | |||
| return NULL; | |||
| } | |||
| /* determine user size */ | |||
| shdr = USER_TO_HEADER(p); | |||
| if (!smalloc_is_alloc(spool, shdr)) smalloc_UB(spool, p); | |||
| usz = shdr->usz; | |||
| rsz = shdr->rsz; | |||
| /* newsize is lesser than allocated - truncate */ | |||
| if (n <= usz) { | |||
| if (spool->do_zero) memset(p + n, 0, shdr->rsz - n); | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += usz; | |||
| memset(s, 0, HEADER_SZ); | |||
| if (spool->do_zero) memset(s+HEADER_SZ, 0, rsz - usz); | |||
| shdr->rsz = (n%HEADER_SZ)?(((n/HEADER_SZ)+1)*HEADER_SZ):n; | |||
| shdr->usz = n; | |||
| shdr->tag = tag = smalloc_mktag(shdr); | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += shdr->usz; | |||
| for (x = 0; x < sizeof(struct smalloc_hdr); x += sizeof(uintptr_t)) { | |||
| tag = smalloc_uinthash(tag); | |||
| memcpy(s+x, &tag, sizeof(uintptr_t)); | |||
| } | |||
| memset(s+x, 0xff, shdr->rsz - shdr->usz); | |||
| return p; | |||
| } | |||
| /* newsize is bigger than allocated, but there is free room - modify */ | |||
| if (n > usz && n <= rsz) { | |||
| if (spool->do_zero) { | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += usz; | |||
| memset(s, 0, HEADER_SZ); | |||
| } | |||
| shdr->usz = n; | |||
| shdr->tag = tag = smalloc_mktag(shdr); | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += shdr->usz; | |||
| for (x = 0; x < sizeof(struct smalloc_hdr); x += sizeof(uintptr_t)) { | |||
| tag = smalloc_uinthash(tag); | |||
| memcpy(s+x, &tag, sizeof(uintptr_t)); | |||
| } | |||
| memset(s+x, 0xff, shdr->rsz - shdr->usz); | |||
| return p; | |||
| } | |||
| /* newsize is bigger, larger than rsz but there are free blocks beyond - extend */ | |||
| basehdr = spool->pool; dhdr = shdr+(rsz/HEADER_SZ); found = 0; | |||
| while (CHAR_PTR(dhdr)-CHAR_PTR(basehdr) < spool->pool_size) { | |||
| x = CHAR_PTR(dhdr)-CHAR_PTR(shdr); | |||
| if (smalloc_is_alloc(spool, dhdr)) | |||
| goto allocblock; | |||
| if (n + HEADER_SZ <= x) { | |||
| x -= HEADER_SZ; | |||
| found = 1; | |||
| goto outfound; | |||
| } | |||
| dhdr++; | |||
| } | |||
| outfound: | |||
| /* write new numbers of same allocation */ | |||
| if (found) { | |||
| if (spool->do_zero) { | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += usz; | |||
| memset(s, 0, HEADER_SZ); | |||
| memset(s+HEADER_SZ, 0, rsz - usz); | |||
| } | |||
| shdr->rsz = x; | |||
| shdr->usz = n; | |||
| shdr->tag = tag = smalloc_mktag(shdr); | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += shdr->usz; | |||
| for (x = 0; x < sizeof(struct smalloc_hdr); x += sizeof(uintptr_t)) { | |||
| tag = smalloc_uinthash(tag); | |||
| memcpy(s+x, &tag, sizeof(uintptr_t)); | |||
| } | |||
| memset(s+x, 0xff, shdr->rsz - shdr->usz); | |||
| return p; | |||
| } | |||
| allocblock: | |||
| /* newsize is bigger than allocated and no free space - move */ | |||
| if (nomove) { | |||
| /* fail if user asked */ | |||
| errno = ERANGE; | |||
| return NULL; | |||
| } | |||
| r = sm_malloc_pool(spool, n); | |||
| if (!r) return NULL; | |||
| memcpy(r, p, usz); | |||
| sm_free_pool(spool, p); | |||
| return r; | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| void *sm_realloc_move_pool(struct smalloc_pool *spool, void *p, size_t n) | |||
| { | |||
| return sm_realloc_pool_i(spool, p, n, 1); | |||
| } | |||
| void *sm_realloc_move(void *p, size_t n) | |||
| { | |||
| return sm_realloc_pool_i(&smalloc_curr_pool, p, n, 1); | |||
| } | |||
| @@ -0,0 +1,29 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| size_t sm_szalloc_pool(struct smalloc_pool *spool, const void *p) | |||
| { | |||
| struct smalloc_hdr *shdr; | |||
| if (!smalloc_verify_pool(spool)) { | |||
| errno = EINVAL; | |||
| return ((size_t)-1); | |||
| } | |||
| if (!p) return 0; | |||
| shdr = USER_TO_HEADER(p); | |||
| if (smalloc_is_alloc(spool, shdr)) return shdr->usz; | |||
| smalloc_UB(spool, p); | |||
| return 0; | |||
| } | |||
| size_t sm_szalloc(const void *p) | |||
| { | |||
| return sm_szalloc_pool(&smalloc_curr_pool, p); | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| static int smalloc_check_bounds(struct smalloc_pool *spool, struct smalloc_hdr *shdr) | |||
| { | |||
| if (!spool) return 0; | |||
| if (CHAR_PTR(shdr) >= CHAR_PTR(spool->pool) | |||
| && CHAR_PTR(shdr) <= (CHAR_PTR(spool->pool)+spool->pool_size)) | |||
| return 1; | |||
| return 0; | |||
| } | |||
| static int smalloc_valid_tag(struct smalloc_hdr *shdr) | |||
| { | |||
| char *s; | |||
| uintptr_t r = smalloc_mktag(shdr); | |||
| size_t x; | |||
| if (shdr->tag == r) { | |||
| s = CHAR_PTR(HEADER_TO_USER(shdr)); | |||
| s += shdr->usz; | |||
| for (x = 0; x < sizeof(struct smalloc_hdr); x += sizeof(uintptr_t)) { | |||
| r = smalloc_uinthash(r); | |||
| if (memcmp(s+x, &r, sizeof(uintptr_t)) != 0) return 0; | |||
| } | |||
| s += x; x = 0; | |||
| while (x < shdr->rsz - shdr->usz) { | |||
| if (s[x] != '\xFF') return 0; | |||
| x++; | |||
| } | |||
| return 1; | |||
| } | |||
| return 0; | |||
| } | |||
| static void smalloc_do_crash(struct smalloc_pool *spool, const void *p) | |||
| { | |||
| char *c = NULL; | |||
| *c = 'X'; | |||
| } | |||
| smalloc_ub_handler smalloc_UB = smalloc_do_crash; | |||
| void sm_set_ub_handler(smalloc_ub_handler handler) | |||
| { | |||
| if (!handler) smalloc_UB = smalloc_do_crash; | |||
| else smalloc_UB = handler; | |||
| } | |||
| int smalloc_is_alloc(struct smalloc_pool *spool, struct smalloc_hdr *shdr) | |||
| { | |||
| if (!smalloc_check_bounds(spool, shdr)) return 0; | |||
| if (shdr->rsz == 0) return 0; | |||
| if (shdr->rsz > SIZE_MAX) return 0; | |||
| if (shdr->usz > SIZE_MAX) return 0; | |||
| if (shdr->usz > shdr->rsz) return 0; | |||
| if (shdr->rsz % HEADER_SZ) return 0; | |||
| if (!smalloc_valid_tag(shdr)) return 0; | |||
| return 1; | |||
| } | |||
| @@ -0,0 +1,19 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #include "smalloc_i.h" | |||
| void *sm_zalloc_pool(struct smalloc_pool *spool, size_t n) | |||
| { | |||
| void *r = sm_malloc_pool(spool, n); | |||
| if (r) memset(r, 0, n); | |||
| return r; | |||
| } | |||
| void *sm_zalloc(size_t n) | |||
| { | |||
| return sm_zalloc_pool(&smalloc_curr_pool, n); | |||
| } | |||
| @@ -0,0 +1,77 @@ | |||
| /* | |||
| * SMalloc -- a *static* memory allocator. | |||
| * | |||
| * See README for a complete description. | |||
| * | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| * Written during Aug2017. | |||
| */ | |||
| #ifndef _SMALLOC_H | |||
| #define _SMALLOC_H | |||
| #include <stddef.h> | |||
| #include <stdint.h> | |||
| struct smalloc_pool; | |||
| typedef size_t (*smalloc_oom_handler)(struct smalloc_pool *, size_t); | |||
| /* describes static pool, if you're going to use multiple pools at same time */ | |||
| struct smalloc_pool { | |||
| void *pool; /* pointer to your pool */ | |||
| size_t pool_size; /* it's size. Must be aligned with sm_align_pool. */ | |||
| int do_zero; /* zero pool before use and all the new allocations from it. */ | |||
| smalloc_oom_handler oomfn; /* this will be called, if non-NULL, on OOM condition in pool */ | |||
| }; | |||
| /* a default one which is initialised with sm_set_default_pool. */ | |||
| extern struct smalloc_pool smalloc_curr_pool; | |||
| /* undefined behavior handler is called on typical malloc UB situations */ | |||
| typedef void (*smalloc_ub_handler)(struct smalloc_pool *, const void *); | |||
| void sm_set_ub_handler(smalloc_ub_handler); | |||
| int sm_align_pool(struct smalloc_pool *); | |||
| int sm_set_pool(struct smalloc_pool *, void *, size_t, int, smalloc_oom_handler); | |||
| int sm_set_default_pool(void *, size_t, int, smalloc_oom_handler); | |||
| int sm_release_pool(struct smalloc_pool *); | |||
| int sm_release_default_pool(void); | |||
| /* Use these with multiple pools which you control */ | |||
| void *sm_malloc_pool(struct smalloc_pool *, size_t); | |||
| void *sm_zalloc_pool(struct smalloc_pool *, size_t); | |||
| void sm_free_pool(struct smalloc_pool *, void *); | |||
| void *sm_realloc_pool(struct smalloc_pool *, void *, size_t); | |||
| void *sm_realloc_move_pool(struct smalloc_pool *, void *, size_t); | |||
| void *sm_calloc_pool(struct smalloc_pool *, size_t, size_t); | |||
| int sm_alloc_valid_pool(struct smalloc_pool *spool, const void *p); | |||
| size_t sm_szalloc_pool(struct smalloc_pool *, const void *); | |||
| int sm_malloc_stats_pool(struct smalloc_pool *, size_t *, size_t *, size_t *, int *); | |||
| /* Use these when you use just default smalloc_curr_pool pool */ | |||
| void *sm_malloc(size_t); | |||
| void *sm_zalloc(size_t); /* guarantee zero memory allocation */ | |||
| void sm_free(void *); | |||
| void *sm_realloc(void *, size_t); | |||
| void *sm_realloc_move(void *, size_t); | |||
| void *sm_calloc(size_t, size_t); /* calls zalloc internally */ | |||
| int sm_alloc_valid(const void *p); /* verify pointer without intentional crash */ | |||
| size_t sm_szalloc(const void *); /* get size of allocation */ | |||
| /* | |||
| * get stats: total used, user used, total free, nr. of allocated blocks. | |||
| * any of pointers maybe set to NULL, but at least one must be non NULL. | |||
| */ | |||
| int sm_malloc_stats(size_t *, size_t *, size_t *, int *); | |||
| #endif | |||
| @@ -0,0 +1,40 @@ | |||
| /* | |||
| * This file is a part of SMalloc. | |||
| * SMalloc is MIT licensed. | |||
| * Copyright (c) 2017 Andrey Rys. | |||
| */ | |||
| #ifndef _SMALLOC_I_H | |||
| #define _SMALLOC_I_H | |||
| #include "smalloc.h" | |||
| #include <string.h> | |||
| #include <limits.h> | |||
| #include <errno.h> | |||
| struct smalloc_hdr { | |||
| size_t rsz; /* real allocated size with overhead (if any) */ | |||
| size_t usz; /* exact user size as reported by s_szalloc */ | |||
| uintptr_t tag; /* sum of all the above, hashed value */ | |||
| }; | |||
| #define HEADER_SZ (sizeof(struct smalloc_hdr)) | |||
| #define MIN_POOL_SZ (HEADER_SZ*20) | |||
| #define VOID_PTR(p) ((void *)p) | |||
| #define CHAR_PTR(p) ((char *)p) | |||
| #define PTR_UINT(p) ((uintptr_t)VOID_PTR(p)) | |||
| #define HEADER_PTR(p) ((struct smalloc_hdr *)p) | |||
| #define USER_TO_HEADER(p) (HEADER_PTR((CHAR_PTR(p)-HEADER_SZ))) | |||
| #define HEADER_TO_USER(p) (VOID_PTR((CHAR_PTR(p)+HEADER_SZ))) | |||
| extern smalloc_ub_handler smalloc_UB; | |||
| uintptr_t smalloc_uinthash(uintptr_t x); | |||
| uintptr_t smalloc_mktag(struct smalloc_hdr *shdr); | |||
| int smalloc_verify_pool(struct smalloc_pool *spool); | |||
| int smalloc_is_alloc(struct smalloc_pool *spool, struct smalloc_hdr *shdr); | |||
| void *sm_realloc_pool_i(struct smalloc_pool *spool, void *p, size_t n, int nomove); | |||
| #endif | |||