// Config

#include <stddef.h>
#include "hal/hal.h"
#include "spinlock/spinlock.h"
#include "kprintf.h"
#include "bitmap/bitmap.h"
#include "util/util.h"
#include "pmm/pmm.h"
#include "malloc.h"
#include "bootinfo/bootinfo.h"

#define USE_DL_PREFIX 1
#define LACKS_SYS_TYPES_H 1
#define NO_MALLOC_STATS 1
#define LACKS_ERRNO_H 1
#define LACKS_TIME_H 1
#define LACKS_STDLIB_H 1
#define LACKS_SYS_MMAN_H 1
#define LACKS_FCNTL_H 1
#define LACKS_UNISTD_H 1
#define LACKS_SYS_PARAM_H 1
#define LACKS_STRINGS_H 1
#define LACKS_SCHED_H 1
#define HAVE_MMAP 0
#define ABORT \
  do { \
    ERR("dlmalloc", "Aborting..."); \
    hal_hang(); \
  } while(0)
#define MALLOC_FAILURE_ACTION
#define HAVE_MORECORE 1
#define USE_LOCKS 2
#define malloc_getpagesize 0x1000
#define EINVAL 0xdeadbeef
#define ENOMEM 0xb16b00b5
#define MORECORE_CONTIGUOUS 0

#define MLOCK_T SpinLock

int ACQUIRE_LOCK(SpinLock *sl) {
  spinlock_acquire(sl);
  return 0;
}

int RELEASE_LOCK(SpinLock *sl) {
  spinlock_release(sl);
  return 0;
}

int INITIAL_LOCK(SpinLock *sl) {
  spinlock_init(sl);
  return 0;
}
    
static MLOCK_T malloc_global_mutex = { 0 };

void *_last = 0;

void *sbrk(long inc) {
  if (inc < 0) {
    return 0;
  }
  if (!inc) {
    return _last;
  }

  uint64_t blocks = _DIV_ROUNDUP(inc, BITMAP_BLOCK_SIZE);
  uint8_t *virt = VIRT(pmm_alloc(blocks));
  hal_memset(virt, 0, blocks * BITMAP_BLOCK_SIZE);
  _last = (void *)(virt + inc);
  return virt;
}
