/* | |||||
* 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); | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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; | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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; | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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; | |||||
} |
/* | |||||
* 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); | |||||
} |
/* | |||||
* 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 |
/* | |||||
* 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 |