8 /* FIXME: Doesn't handle non-page-aligned poolsize. */
9 /* FIXME: Doesn't handle sub-page allocations. */
11 #define MIN_SIZE (getpagesize() * 2)
20 void alloc_init(void *pool, unsigned long poolsize)
23 unsigned int pages = poolsize / getpagesize();
25 if (poolsize < MIN_SIZE)
28 memset(bits, 0, (pages * 2 + CHAR_BIT - 1)/ CHAR_BIT);
31 static enum page_state get_page_state(const uint8_t *bits, unsigned long page)
33 return bits[page * 2 / CHAR_BIT] >> (page * 2 % CHAR_BIT) & 3;
36 static void set_page_state(uint8_t *bits, unsigned long page, enum page_state s)
38 bits[page * 2 / CHAR_BIT] &= ~(3 << (page * 2 % CHAR_BIT));
39 bits[page * 2 / CHAR_BIT] |= ((uint8_t)s << (page * 2 % CHAR_BIT));
42 static unsigned long metadata_length(void *pool, unsigned long poolsize)
44 return ((poolsize / getpagesize() * 2 / CHAR_BIT) + getpagesize() - 1)
45 & ~(getpagesize() - 1);
48 void *alloc_get(void *pool, unsigned long poolsize,
49 unsigned long size, unsigned long align)
52 unsigned long free, want, metalen;
54 if (poolsize < MIN_SIZE)
57 /* FIXME: Necessary for this. */
61 want = (size + getpagesize() - 1) / getpagesize();
62 metalen = metadata_length(pool, poolsize);
65 /* We allocate from far end, to increase ability to expand metadata. */
66 for (i = (poolsize - metalen) / getpagesize() - 1; i >= 0; i--) {
67 switch (get_page_state(pool, i)) {
71 char *ret = (char *)pool + metalen
74 /* They might ask for multi-page alignment. */
75 if ((unsigned long)ret % align)
78 for (j = i+1; j < i + want; j++)
79 set_page_state(pool, j, TAKEN);
80 set_page_state(pool, i, TAKEN_START);
94 void alloc_free(void *pool, unsigned long poolsize, void *free)
96 unsigned long pagenum, metalen;
98 if (poolsize < MIN_SIZE)
104 metalen = metadata_length(pool, poolsize);
106 assert(free > pool && (char *)pool + poolsize > (char *)free);
107 assert((unsigned long)free % getpagesize() == 0);
109 pagenum = ((char *)free - (char *)pool - metalen) / getpagesize();
111 assert(get_page_state(pool, pagenum) == TAKEN_START);
112 set_page_state(pool, pagenum, FREE);
113 while (get_page_state(pool, ++pagenum) == TAKEN)
114 set_page_state(pool, pagenum, FREE);
117 bool alloc_check(void *pool, unsigned long poolsize)
119 unsigned int i, metalen;
120 enum page_state last_state = FREE;
122 if (poolsize < MIN_SIZE)
125 metalen = metadata_length(pool, poolsize);
126 for (i = 0; i < (poolsize - metalen) / getpagesize(); i++) {
127 enum page_state state = get_page_state(pool, i);
133 if (last_state == FREE)