#define _GNU_SOURCE
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
struct freeblocks{
unsigned long *block;
struct freeblocks *next;
} *freelist = NULL;
static char *where = NULL;
static long blocksize = 0;
void *malloc64(int size){
if(!blocksize){
char *tmp = sbrk(0); //end of heap
char *tmp2 = (char *)&size; //end of stack
long total = tmp2 - tmp; //memory available
total -= (long)4 * 1024 * 1024 * 1024; //leave some for the libc malloc (4GB)
blocksize = total/10000000; //10 million allocations of over 4k should be enough for anyone (at least 40 Gb requested at that point, in reality probably at least 10 times more!)
blocksize -= blocksize % 4096;
where = tmp + (long)4 * 1024 * 1024 * 1024;
where -= (long)where % 4096;
printf("start %xl: blocksize: %xl\n", (long)where, blocksize);
}
if(size < 4088){
register unsigned long *res = malloc(size+sizeof(long));
if(!res){
perror("malloc: ");
exit(-1);
}
*res=size;
return &res[1];
}
register unsigned long *res;
if(!freelist){
res = mmap(where, size+sizeof(long),MAP_FIXED|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,0,0);
where += blocksize;
}else{
res = mmap(freelist->block, size+sizeof(long),MAP_FIXED|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,0,0);
struct freeblocks *tmp = freelist;
freelist = freelist->next;
free(tmp);
}
if((long)res == -1){
perror("malloc: ");
exit(-1);
}
*res=size;
return &res[1];
}
void free64(void *p){
register unsigned long *mem = p;
mem--;
if(mem < (unsigned long *)sbrk(0) || mem > (unsigned long *)where)
free(mem);
else{
munmap(mem, *mem+sizeof(long));
struct freeblocks *bl = malloc(sizeof(struct freeblocks));
bl->block = mem;
bl->next = freelist;
freelist = bl;
}
}
void *realloc64(void *p, int size){
register unsigned long *mem = p;
unsigned int oldsize;
mem--;
oldsize = *mem+sizeof(long);
if(mem < (unsigned long *)sbrk(0) || mem > (unsigned long *)where){
if(size < 4088){
mem = realloc(mem, size + sizeof(long));
*mem = size;
return (void *)&mem[1];
} else {
mem++;
unsigned long *newmem = malloc64(size);
memcpy(newmem, mem, oldsize-sizeof(long));
mem--;
free(mem);
return (void *)newmem;
}
}
if(size < 4088){
mem++;
unsigned long *newmem = malloc(size+sizeof(long));
*newmem = size;
newmem++;
memcpy(newmem, mem, size);
free64(mem);
return (void *)newmem;
}
mem = mremap(mem, oldsize, size+sizeof(long), 1);
*mem = size;
return (void *)&mem[1];
}
void *calloc64(int num, int size){
register void *p;
size *= num;
if ((p = malloc64(size)))
memset(p, 0, size);
return (p);
}