/* Copyright (c) 2016, 2019, 2022 Dennis Wölfing
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* libc/src/stdlib/malloc.h
 * Internal definitions for memory allocation.
 */

#ifndef MALLOC_H
#define MALLOC_H

#include <limits.h>
#include <stdlib.h>

#if __is_dennix_libc
#  define mmap __mmap
#  define munmap __munmap
#  include <sys/mman.h>
#  define mapMemory(size) mmap(NULL, size, PROT_READ | PROT_WRITE, \
        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
#  define unmapMemory(addr, size) munmap(addr, size)
#else /* if __is_dennix_libk */
extern void* __mapMemory(size_t);
extern void __unmapMemory(void*, size_t);

#  define mapMemory(size) __mapMemory(size)
#  define unmapMemory(addr, size) __unmapMemory(addr, size)
#endif

typedef struct Chunk {
    size_t magic;
    size_t size;
    struct Chunk* prev;
    struct Chunk* next;
} Chunk;

#define MAGIC_BIG_CHUNK 0xC001C0DE
#define MAGIC_FREE_CHUNK 0xBEEFBEEF
#define MAGIC_USED_CHUNK 0xDEADBEEF
#define MAGIC_END_CHUNK 0xDEADDEAD

#define alignUp(val, alignment) ((((val) - 1) & ~((alignment) - 1)) + (alignment))

extern Chunk* __firstBigChunk;

Chunk* __allocateBigChunk(Chunk* lastBigChunk, size_t size);
void __splitChunk(Chunk* chunk, size_t size);
Chunk* __unifyChunks(Chunk* first, Chunk* second);

void __lockHeap(void);
void __unlockHeap(void);

#endif
