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 #define MIN(x, y) ((x) < (y) ? (x) : (y))
37 static unsigned long page_round_down(unsigned long x
)
39 return x
- x
% PAGE_SIZE
;
42 static unsigned long page_round_up(unsigned long x
)
53 #define page_round_down_ptr(x) ((u8_t *) page_round_down((unsigned long) (x)))
54 #define page_round_up_ptr(x) ((u8_t *) page_round_up((unsigned long) (x)))
56 static unsigned long block_compute_magic(struct block
*block
)
58 return (unsigned long) block
+ block
->size
+ 0xDEADBEEFUL
;
61 static size_t block_get_totalsize(size_t size
)
63 return page_round_up(sizeof(struct block
) + size
);
66 static u8_t
*block_get_endptr(struct block
*block
)
68 return (u8_t
*) block
+ block_get_totalsize(block
->size
);
71 static u8_t
*block_get_dataptr(struct block
*block
)
73 return block_get_endptr(block
) - block
->size
;
76 static void block_check(struct block
*block
)
82 assert(!((unsigned long) block
% PAGE_SIZE
));
83 assert((u8_t
*) block
>= ptr_min
);
84 assert((u8_t
*) block
<= ptr_max
);
87 assert(block
->size
> 0);
90 assert(block
->magic
== block_compute_magic(block
));
91 dataptr
= block_get_dataptr(block
);
92 for (p
= (u8_t
*) (block
+ 1); p
< dataptr
; p
++)
93 assert(*p
== ((unsigned long) p
& 0xff));
96 static struct block
*block_alloc(size_t size
)
99 u8_t
*dataptr
, *p
, *ptr
;
100 unsigned page_index
, page_index_max
;
101 size_t sizerem
, totalsize
;
104 LOG(("block_alloc; size=0x%x\n", size
));
107 /* round size up to machine word size */
108 sizerem
= size
% sizeof(long);
110 size
+= sizeof(long) - sizerem
;
112 /* initialize address range */
113 if (!ptr_min
&& !ptr_max
) {
114 /* keep a safe distance from areas that are in use:
115 * - 4MB from the break (should not change if traditional
116 * malloc is not used so a small margin is sufficient
117 * - 256MB from the stack (big margin because memory beyond
118 * this may be allocated by mmap when the address space
121 ptr_min
= page_round_up_ptr((u8_t
*) sbrk(0) + 0x400000);
122 ptr_max
= page_round_down_ptr((u8_t
*) &size
- 0x10000000);
126 assert(ptr_min
< ptr_max
);
128 /* select address at random */
133 /* LSC Broken for now... */
134 /* read_tsc_64(&tsc); */
136 totalsize
= block_get_totalsize(size
);
137 page_index_max
= (ptr_max
- ptr_min
- totalsize
) / PAGE_SIZE
;
138 page_index
= (page_index_max
> 0) ? (ex64lo(tsc
) % page_index_max
) : 0;
139 ptr
= ptr_min
+ page_index
* PAGE_SIZE
;
142 block
= (struct block
*) mmap(
145 PROT_READ
|PROT_WRITE
, /* prot */
146 MAP_PREALLOC
, /* flags */
149 if (block
== MAP_FAILED
) {
150 /* mmap call failed */
154 /* block may not be at the requested location if that is in use */
155 if (ptr_min
> (u8_t
*) block
)
156 ptr_min
= (u8_t
*) block
;
158 if (ptr_max
< (u8_t
*) block
)
159 ptr_max
= (u8_t
*) block
;
161 /* initialize block, including fillers */
163 block
->magic
= block_compute_magic(block
);
164 dataptr
= block_get_dataptr(block
);
165 for (p
= (u8_t
*) (block
+ 1); p
< dataptr
; p
++)
166 *p
= ((unsigned long) p
& 0xff);
168 LOG(("block_alloc; block=0x%x\n", block
));
172 static struct block
*block_find(const void *ptr
)
176 LOG(("block_find; ptr=0x%x\n", ptr
));
179 /* locate block based on pointer, then check whether it is valid */
180 block
= (struct block
*) page_round_down(
181 (unsigned long) ((struct block
*) __UNCONST(ptr
) - 1));
183 LOG(("block_find; block=0x%x\n", block
));
187 static void block_free(struct block
*block
)
189 LOG(("block_free; block=0x%x\n", block
));
192 /* simply unmap the block */
193 if (munmap(block
, block_get_totalsize(block
->size
)) < 0) {
194 /* munmap call failed */
199 void *_dbg_malloc(size_t size
)
201 struct block
*newblock
;
204 LOG(("_dbg_malloc; size=0x%x\n", size
));
205 assert(size
> 0); /* enforced by regular malloc */
207 newblock
= block_alloc(size
);
211 ptr
= block_get_dataptr(newblock
);
212 LOG(("_dbg_malloc; ptr=0x%x\n", ptr
));
216 void *_dbg_realloc(void *oldp
, size_t size
)
219 struct block
*oldblock
, *newblock
;
221 LOG(("_dbg_realloc; oldp=0x%x; size=0x%x\n", oldp
, size
));
222 assert(oldp
); /* enforced by regular realloc */
223 assert(size
> 0); /* enforced by regular realloc */
225 /* always allocate new block */
226 newblock
= block_alloc(size
);
231 oldblock
= block_find(oldp
);
232 memcpy(block_get_dataptr(newblock
),
233 block_get_dataptr(oldblock
),
234 MIN(newblock
->size
, oldblock
->size
));
236 /* deallocate old block */
237 block_free(oldblock
);
239 newp
= block_get_dataptr(newblock
);
240 LOG(("_dbg_realloc; newp=0x%x\n", newp
));
244 void _dbg_free(void *ptr
)
246 LOG(("_dbg_free; ptr=0x%x\n", ptr
));
247 assert(ptr
); /* enforced by regular free */
249 /* find the block and free it */
250 block_free(block_find(ptr
));
252 LOG(("_dbg_free done\n"));