#include "libc.h"
#include "atomic.h"
#include "pthread_impl.h"
+#include "malloc_impl.h"
#if defined(__GNUC__) && defined(__PIC__)
#define inline inline __attribute__((always_inline))
#endif
-void *__mmap(void *, size_t, int, int, int, off_t);
-int __munmap(void *, size_t);
-void *__mremap(void *, size_t, size_t, int, ...);
-int __madvise(void *, size_t, int);
-
-struct chunk {
- size_t psize, csize;
- struct chunk *next, *prev;
-};
-
-struct bin {
- volatile int lock[2];
- struct chunk *head;
- struct chunk *tail;
-};
-
static struct {
volatile uint64_t binmap;
struct bin bins[64];
volatile int free_lock[2];
} mal;
-
-#define SIZE_ALIGN (4*sizeof(size_t))
-#define SIZE_MASK (-SIZE_ALIGN)
-#define OVERHEAD (2*sizeof(size_t))
-#define MMAP_THRESHOLD (0x1c00*SIZE_ALIGN)
-#define DONTCARE 16
-#define RECLAIM 163840
-
-#define CHUNK_SIZE(c) ((c)->csize & -2)
-#define CHUNK_PSIZE(c) ((c)->psize & -2)
-#define PREV_CHUNK(c) ((struct chunk *)((char *)(c) - CHUNK_PSIZE(c)))
-#define NEXT_CHUNK(c) ((struct chunk *)((char *)(c) + CHUNK_SIZE(c)))
-#define MEM_TO_CHUNK(p) (struct chunk *)((char *)(p) - OVERHEAD)
-#define CHUNK_TO_MEM(c) (void *)((char *)(c) + OVERHEAD)
-#define BIN_TO_CHUNK(i) (MEM_TO_CHUNK(&mal.bins[i].head))
-
-#define C_INUSE ((size_t)1)
-
-#define IS_MMAPPED(c) !((c)->csize & (C_INUSE))
-
+int __malloc_replaced;
/* Synchronization tools */
static inline void lock(volatile int *lk)
{
- if (libc.threads_minus_1)
+ int need_locks = libc.need_locks;
+ if (need_locks) {
while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1);
+ if (need_locks < 0) libc.need_locks = 0;
+ }
}
static inline void unlock(volatile int *lk)
}
#endif
-void *__expand_heap(size_t *);
-
static struct chunk *expand_heap(size_t n)
{
static int heap_lock[2];
return 1;
}
-static void bin_chunk(struct chunk *);
-
static void trim(struct chunk *self, size_t n)
{
size_t n1 = CHUNK_SIZE(self);
next->psize = n1-n | C_INUSE;
self->csize = n | C_INUSE;
- bin_chunk(split);
+ __bin_chunk(split);
}
void *malloc(size_t n)
}
}
-void *__malloc0(size_t n)
+void *calloc(size_t m, size_t n)
{
+ if (n && m > (size_t)-1/n) {
+ errno = ENOMEM;
+ return 0;
+ }
+ n *= m;
void *p = malloc(n);
- if (!p || IS_MMAPPED(MEM_TO_CHUNK(p)))
- return p;
- if (n >= PAGE_SIZE)
- n = mal0_clear(p, PAGE_SIZE, n);
+ if (!p) return p;
+ if (!__malloc_replaced) {
+ if (IS_MMAPPED(MEM_TO_CHUNK(p)))
+ return p;
+ if (n >= PAGE_SIZE)
+ n = mal0_clear(p, PAGE_SIZE, n);
+ }
return memset(p, 0, n);
}
return new;
}
-static void bin_chunk(struct chunk *self)
+void __bin_chunk(struct chunk *self)
{
struct chunk *next = NEXT_CHUNK(self);
size_t final_size, new_size, size;
if (IS_MMAPPED(self))
unmap_chunk(self);
else
- bin_chunk(self);
+ __bin_chunk(self);
}
void __malloc_donate(char *start, char *end)
struct chunk *c = MEM_TO_CHUNK(start), *n = MEM_TO_CHUNK(end);
c->psize = n->csize = C_INUSE;
c->csize = n->psize = C_INUSE | (end-start);
- bin_chunk(c);
+ __bin_chunk(c);
}