#define _DEFAULT_SOURCE
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <malloc.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/lock.h>
#include <sys/param.h>
#include <stdint.h>
#if MALLOC_DEBUG
void __malloc_validate(void);
void __malloc_validate_block(chunk_t *r);
#define MALLOC_LOCK \
do { \
__LIBC_LOCK(); \
__malloc_validate(); \
} while (0)
#define MALLOC_UNLOCK \
do { \
__malloc_validate(); \
__LIBC_UNLOCK(); \
} while (0)
#else
#define __malloc_validate()
#define __malloc_validate_block(r)
#define MALLOC_LOCK __LIBC_LOCK()
#define MALLOC_UNLOCK __LIBC_UNLOCK()
#endif
#if __STDC_VERSION__ >= 201112L
typedef max_align_t align_chunk_t;
#else
typedef union {
void *p;
double d;
long long ll;
size_t s;
long double ld;
} align_chunk_t;
#endif
typedef struct malloc_head {
size_t size;
} head_t;
typedef struct malloc_chunk {
struct malloc_chunk *next;
} chunk_t;
#define MALLOC_CHUNK_ALIGN _Alignof(align_chunk_t)
#define MALLOC_HEAD_ALIGN _Alignof(head_t)
#define MALLOC_HEAD sizeof(head_t)
#define MALLOC_PAGE_ALIGN (0x1000)
#define MALLOC_MINSIZE __align_up(MALLOC_HEAD + sizeof(chunk_t), MALLOC_HEAD_ALIGN)
#define MALLOC_MAXSIZE (SIZE_MAX - (MALLOC_HEAD + 2 * MALLOC_CHUNK_ALIGN))
static inline size_t *
_size_ref(chunk_t *chunk)
{
return (size_t *)((char *)chunk - MALLOC_HEAD);
}
static inline size_t
_size(chunk_t *chunk)
{
return *_size_ref(chunk);
}
static inline void
_set_size(chunk_t *chunk, size_t size)
{
*_size_ref(chunk) = size;
}
extern chunk_t *__malloc_free_list;
extern char *__malloc_sbrk_start;
extern char *__malloc_sbrk_top;
#if MALLOC_DEBUG
#else
#endif
bool __malloc_grow_chunk(chunk_t *c, size_t new_size);
#ifdef __strong_reference
void __malloc_free(void *);
void *__malloc_malloc(size_t);
#else
#define __malloc_free(x) free(x)
#define __malloc_malloc(x) malloc(x)
#endif
static inline chunk_t *
ptr_to_chunk(void *ptr)
{
return (chunk_t *)ptr;
}
static inline void *
chunk_to_ptr(chunk_t *c)
{
return c;
}
static inline chunk_t *
blob_to_chunk(void *blob)
{
return (chunk_t *)((char *)blob + MALLOC_HEAD);
}
static inline void *
chunk_to_blob(chunk_t *c)
{
return (void *)((char *)c - MALLOC_HEAD);
}
static inline void *
chunk_end(chunk_t *c)
{
size_t *s = _size_ref(c);
return (char *)s + *s;
}
static inline chunk_t *
chunk_after(chunk_t *c)
{
return (chunk_t *)((char *)c + _size(c));
}
static inline size_t
chunk_size(size_t malloc_size)
{
malloc_size = __align_up(malloc_size, MALLOC_CHUNK_ALIGN);
malloc_size += MALLOC_HEAD;
malloc_size += (MALLOC_CHUNK_ALIGN - MALLOC_HEAD_ALIGN);
malloc_size = MAX(MALLOC_MINSIZE, malloc_size);
return malloc_size;
}
static inline size_t
chunk_usable(chunk_t *c)
{
return _size(c) - MALLOC_HEAD;
}
static inline void
make_free_chunk(chunk_t *c, size_t size)
{
_set_size(c, size);
__malloc_free(chunk_to_ptr(c));
}