stdio: puts() and vprintf()
[neatlibc.git] / malloc.c
blobf0af6938414263eac287111368e6320e7b891476
1 #include <stdlib.h>
2 #include <string.h>
3 #include <sys/mman.h>
5 #define PGSIZE 4096
6 #define PGMASK (PGSIZE - 1)
7 #define MSETMAX 4096
8 #define MSETLEN (1 << 15)
10 struct mset {
11 int refs;
12 int size;
15 static struct mset *pool;
17 static int mk_pool(void)
19 if (pool && !pool->refs) {
20 pool->size = sizeof(*pool);
21 return 0;
23 pool = mmap(NULL, MSETLEN, PROT_READ | PROT_WRITE,
24 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
25 if (pool == MAP_FAILED) {
26 pool = NULL;
27 return 1;
29 pool->size = sizeof(*pool);
30 pool->refs = 0;
31 return 0;
34 void *malloc(long n)
36 void *m;
37 if (n >= MSETMAX) {
38 m = mmap(NULL, n + PGSIZE, PROT_READ | PROT_WRITE,
39 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
40 if (m == MAP_FAILED)
41 return NULL;
42 *(long *) m = n + PGSIZE; /* store length in the first page */
43 return m + PGSIZE;
45 if (!pool || MSETLEN - pool->size < n + sizeof(void *))
46 if (mk_pool())
47 return NULL;
48 m = (void *) pool + pool->size;
49 *(void **) m = pool; /* the address of the owning mset */
50 pool->refs++;
51 pool->size += (n + sizeof(void *) + 7) & ~7;
52 if (!((unsigned long) (pool + pool->size + sizeof(void *)) & PGMASK))
53 pool->size += sizeof(long);
54 return m + sizeof(void *);
57 void *calloc(long n, long sz)
59 void *r = malloc(n * sz);
60 if (r)
61 memset(r, 0, n * sz);
62 return r;
65 void free(void *v)
67 if (!v)
68 return;
69 if ((unsigned long) v & PGMASK) {
70 struct mset *mset = *(void **) (v - sizeof(void *));
71 mset->refs--;
72 if (!mset->refs && mset != pool)
73 munmap(mset, mset->size);
74 } else {
75 munmap(v - PGSIZE, *(long *) (v - PGSIZE));