1 /* pointless without assertions */
7 #include <machine/vm.h>
8 #include <machine/vmparam.h>
9 #include <minix/minlib.h>
15 #define mmap minix_mmap
16 #define munmap minix_munmap
18 #include "malloc-debug.h"
23 #define LOG(args) if (!reenter) { reenter++; printf args; reenter--; }
33 static u8_t
*ptr_min
, *ptr_max
;
35 static unsigned long page_round_down(unsigned long x
)
37 return x
- x
% PAGE_SIZE
;
40 static unsigned long page_round_up(unsigned long x
)
51 #define page_round_down_ptr(x) ((u8_t *) page_round_down((unsigned long) (x)))
52 #define page_round_up_ptr(x) ((u8_t *) page_round_up((unsigned long) (x)))
54 static unsigned long block_compute_magic(struct block
*block
)
56 return (unsigned long) block
+ block
->size
+ 0xDEADBEEFUL
;
59 static size_t block_get_totalsize(size_t size
)
61 return page_round_up(sizeof(struct block
) + size
);
64 static u8_t
*block_get_endptr(struct block
*block
)
66 return (u8_t
*) block
+ block_get_totalsize(block
->size
);
69 static u8_t
*block_get_dataptr(struct block
*block
)
71 return block_get_endptr(block
) - block
->size
;
74 static void block_check(struct block
*block
)
80 assert(!((unsigned long) block
% PAGE_SIZE
));
81 assert((u8_t
*) block
>= ptr_min
);
82 assert((u8_t
*) block
<= ptr_max
);
85 assert(block
->size
> 0);
88 assert(block
->magic
== block_compute_magic(block
));
89 dataptr
= block_get_dataptr(block
);
90 for (p
= (u8_t
*) (block
+ 1); p
< dataptr
; p
++)
91 assert(*p
== ((unsigned long) p
& 0xff));
94 static struct block
*block_alloc(size_t size
)
97 u8_t
*dataptr
, *p
, *ptr
;
98 unsigned page_index
, page_index_max
;
99 size_t sizerem
, totalsize
;
102 LOG(("block_alloc; size=0x%x\n", size
));
105 /* round size up to machine word size */
106 sizerem
= size
% sizeof(long);
108 size
+= sizeof(long) - sizerem
;
110 /* initialize address range */
111 if (!ptr_min
&& !ptr_max
) {
112 /* keep a safe distance from areas that are in use:
113 * - 4MB from the break (should not change if traditional
114 * malloc is not used so a small margin is sufficient
115 * - 256MB from the stack (big margin because memory beyond
116 * this may be allocated by mmap when the address space
119 ptr_min
= page_round_up_ptr((u8_t
*) sbrk(0) + 0x400000);
120 ptr_max
= page_round_down_ptr((u8_t
*) &size
- 0x10000000);
124 assert(ptr_min
< ptr_max
);
126 /* select address at random */
131 /* LSC Broken for now... */
132 /* read_tsc_64(&tsc); */
134 totalsize
= block_get_totalsize(size
);
135 page_index_max
= (ptr_max
- ptr_min
- totalsize
) / PAGE_SIZE
;
136 page_index
= (page_index_max
> 0) ? (ex64lo(tsc
) % page_index_max
) : 0;
137 ptr
= ptr_min
+ page_index
* PAGE_SIZE
;
140 block
= (struct block
*) mmap(
143 PROT_READ
|PROT_WRITE
, /* prot */
144 MAP_PREALLOC
, /* flags */
147 if (block
== MAP_FAILED
) {
148 /* mmap call failed */
152 /* block may not be at the requested location if that is in use */
153 if (ptr_min
> (u8_t
*) block
)
154 ptr_min
= (u8_t
*) block
;
156 if (ptr_max
< (u8_t
*) block
)
157 ptr_max
= (u8_t
*) block
;
159 /* initialize block, including fillers */
161 block
->magic
= block_compute_magic(block
);
162 dataptr
= block_get_dataptr(block
);
163 for (p
= (u8_t
*) (block
+ 1); p
< dataptr
; p
++)
164 *p
= ((unsigned long) p
& 0xff);
166 LOG(("block_alloc; block=0x%x\n", block
));
170 static struct block
*block_find(const void *ptr
)
174 LOG(("block_find; ptr=0x%x\n", ptr
));
177 /* locate block based on pointer, then check whether it is valid */
178 block
= (struct block
*) page_round_down(
179 (unsigned long) ((struct block
*) __UNCONST(ptr
) - 1));
181 LOG(("block_find; block=0x%x\n", block
));
185 static void block_free(struct block
*block
)
187 LOG(("block_free; block=0x%x\n", block
));
190 /* simply unmap the block */
191 if (munmap(block
, block_get_totalsize(block
->size
)) < 0) {
192 /* munmap call failed */
197 void *_dbg_malloc(size_t size
)
199 struct block
*newblock
;
202 LOG(("_dbg_malloc; size=0x%x\n", size
));
203 assert(size
> 0); /* enforced by regular malloc */
205 newblock
= block_alloc(size
);
209 ptr
= block_get_dataptr(newblock
);
210 LOG(("_dbg_malloc; ptr=0x%x\n", ptr
));
214 void *_dbg_realloc(void *oldp
, size_t size
)
217 struct block
*oldblock
, *newblock
;
219 LOG(("_dbg_realloc; oldp=0x%x; size=0x%x\n", oldp
, size
));
220 assert(oldp
); /* enforced by regular realloc */
221 assert(size
> 0); /* enforced by regular realloc */
223 /* always allocate new block */
224 newblock
= block_alloc(size
);
229 oldblock
= block_find(oldp
);
230 memcpy(block_get_dataptr(newblock
),
231 block_get_dataptr(oldblock
),
232 MIN(newblock
->size
, oldblock
->size
));
234 /* deallocate old block */
235 block_free(oldblock
);
237 newp
= block_get_dataptr(newblock
);
238 LOG(("_dbg_realloc; newp=0x%x\n", newp
));
242 void _dbg_free(void *ptr
)
244 LOG(("_dbg_free; ptr=0x%x\n", ptr
));
245 assert(ptr
); /* enforced by regular free */
247 /* find the block and free it */
248 block_free(block_find(ptr
));
250 LOG(("_dbg_free done\n"));