summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorderaadt <>2005-10-05 02:18:29 +0000
committerderaadt <>2005-10-05 02:18:29 +0000
commitebf131895962dd9b04cb0b762c71506f85c80cb4 (patch)
tree623a7776326eae6647e8e5c4197890cdbfdd4f41
parentcfbe16542ea1f8972cdb9925370ba7f111bfa39d (diff)
downloadopenbsd-ebf131895962dd9b04cb0b762c71506f85c80cb4.tar.gz
openbsd-ebf131895962dd9b04cb0b762c71506f85c80cb4.tar.bz2
openbsd-ebf131895962dd9b04cb0b762c71506f85c80cb4.zip
first KNF (no binary diffs)
-rw-r--r--src/lib/libc/stdlib/malloc.c2678
1 files changed, 1356 insertions, 1322 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 65675456ec..1697a6e65e 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: malloc.c,v 1.76 2005/08/08 08:05:36 espie Exp $ */ 1/* $OpenBSD: malloc.c,v 1.77 2005/10/05 02:18:29 deraadt Exp $ */
2/* 2/*
3 * ---------------------------------------------------------------------------- 3 * ----------------------------------------------------------------------------
4 * "THE BEER-WARE LICENSE" (Revision 42): 4 * "THE BEER-WARE LICENSE" (Revision 42):
@@ -32,7 +32,7 @@
32 * What to use for Junk. This is the byte value we use to fill with 32 * What to use for Junk. This is the byte value we use to fill with
33 * when the 'J' option is enabled. 33 * when the 'J' option is enabled.
34 */ 34 */
35#define SOME_JUNK 0xd0 /* as in "Duh" :-) */ 35#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
36 36
37#include <sys/types.h> 37#include <sys/types.h>
38#include <sys/time.h> 38#include <sys/time.h>
@@ -66,8 +66,8 @@
66 */ 66 */
67 67
68#if defined(__OpenBSD__) && defined(__sparc__) 68#if defined(__OpenBSD__) && defined(__sparc__)
69# define malloc_pageshift 13U 69#define malloc_pageshift 13U
70#endif /* __OpenBSD__ */ 70#endif /* __OpenBSD__ */
71 71
72/* 72/*
73 * No user serviceable parts behind this point. 73 * No user serviceable parts behind this point.
@@ -76,13 +76,13 @@
76 */ 76 */
77 77
78struct pginfo { 78struct pginfo {
79 struct pginfo *next; /* next on the free list */ 79 struct pginfo *next; /* next on the free list */
80 void *page; /* Pointer to the page */ 80 void *page; /* Pointer to the page */
81 u_short size; /* size of this page's chunks */ 81 u_short size; /* size of this page's chunks */
82 u_short shift; /* How far to shift for this size chunks */ 82 u_short shift; /* How far to shift for this size chunks */
83 u_short free; /* How many free chunks */ 83 u_short free; /* How many free chunks */
84 u_short total; /* How many chunk */ 84 u_short total; /* How many chunk */
85 u_long bits[1]; /* Which chunks are free */ 85 u_long bits[1];/* Which chunks are free */
86}; 86};
87 87
88/* 88/*
@@ -90,11 +90,11 @@ struct pginfo {
90 */ 90 */
91 91
92struct pgfree { 92struct pgfree {
93 struct pgfree *next; /* next run of free pages */ 93 struct pgfree *next; /* next run of free pages */
94 struct pgfree *prev; /* prev run of free pages */ 94 struct pgfree *prev; /* prev run of free pages */
95 void *page; /* pointer to free pages */ 95 void *page; /* pointer to free pages */
96 void *pdir; /* pointer to the base page's dir */ 96 void *pdir; /* pointer to the base page's dir */
97 size_t size; /* number of bytes free */ 97 size_t size; /* number of bytes free */
98}; 98};
99 99
100/* 100/*
@@ -145,7 +145,7 @@ struct pgfree {
145 145
146/* fd of /dev/zero */ 146/* fd of /dev/zero */
147#ifdef USE_DEV_ZERO 147#ifdef USE_DEV_ZERO
148static int fdzero; 148static int fdzero;
149#define MMAP_FD fdzero 149#define MMAP_FD fdzero
150#define INIT_MMAP() \ 150#define INIT_MMAP() \
151 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \ 151 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
@@ -163,102 +163,106 @@ static unsigned int malloc_cache = 16;
163 163
164/* Structure used for linking discrete directory pages. */ 164/* Structure used for linking discrete directory pages. */
165struct pdinfo { 165struct pdinfo {
166 struct pginfo **base; 166 struct pginfo **base;
167 struct pdinfo *prev; 167 struct pdinfo *prev;
168 struct pdinfo *next; 168 struct pdinfo *next;
169 u_long dirnum; 169 u_long dirnum;
170}; 170};
171static struct pdinfo *last_dir; /* Caches to the last and previous */ 171static struct pdinfo *last_dir; /* Caches to the last and previous */
172static struct pdinfo *prev_dir; /* referenced directory pages. */ 172static struct pdinfo *prev_dir; /* referenced directory pages. */
173 173
174static size_t pdi_off; 174static size_t pdi_off;
175static u_long pdi_mod; 175static u_long pdi_mod;
176#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *))) 176#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
177#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1)) 177#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
178#define PI_IDX(index) ((index) / pdi_mod) 178#define PI_IDX(index) ((index) / pdi_mod)
179#define PI_OFF(index) ((index) % pdi_mod) 179#define PI_OFF(index) ((index) % pdi_mod)
180 180
181/* The last index in the page directory we care about */ 181/* The last index in the page directory we care about */
182static u_long last_index; 182static u_long last_index;
183 183
184/* Pointer to page directory. Allocated "as if with" malloc */ 184/* Pointer to page directory. Allocated "as if with" malloc */
185static struct pginfo **page_dir; 185static struct pginfo **page_dir;
186 186
187/* Free pages line up here */ 187/* Free pages line up here */
188static struct pgfree free_list; 188static struct pgfree free_list;
189 189
190/* Abort(), user doesn't handle problems. */ 190/* Abort(), user doesn't handle problems. */
191static int malloc_abort = 2; 191static int malloc_abort = 2;
192 192
193/* Are we trying to die ? */ 193/* Are we trying to die ? */
194static int suicide; 194static int suicide;
195 195
196#ifdef MALLOC_STATS 196#ifdef MALLOC_STATS
197/* dump statistics */ 197/* dump statistics */
198static int malloc_stats; 198static int malloc_stats;
199#endif 199#endif
200 200
201/* avoid outputting warnings? */ 201/* avoid outputting warnings? */
202static int malloc_silent; 202static int malloc_silent;
203 203
204/* always realloc ? */ 204/* always realloc ? */
205static int malloc_realloc; 205static int malloc_realloc;
206 206
207/* mprotect free pages PROT_NONE? */ 207/* mprotect free pages PROT_NONE? */
208static int malloc_freeprot; 208static int malloc_freeprot;
209 209
210/* use guard pages after allocations? */ 210/* use guard pages after allocations? */
211static int malloc_guard = 0; 211static int malloc_guard = 0;
212static int malloc_guarded; 212static int malloc_guarded;
213/* align pointers to end of page? */ 213/* align pointers to end of page? */
214static int malloc_ptrguard; 214static int malloc_ptrguard;
215 215
216#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE)) 216#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
217/* pass the kernel a hint on free pages ? */ 217/* pass the kernel a hint on free pages ? */
218static int malloc_hint; 218static int malloc_hint;
219#endif 219#endif
220 220
221/* xmalloc behaviour ? */ 221/* xmalloc behaviour ? */
222static int malloc_xmalloc; 222static int malloc_xmalloc;
223 223
224/* zero fill ? */ 224/* zero fill ? */
225static int malloc_zero; 225static int malloc_zero;
226 226
227/* junk fill ? */ 227/* junk fill ? */
228static int malloc_junk; 228static int malloc_junk;
229 229
230#ifdef __FreeBSD__ 230#ifdef __FreeBSD__
231/* utrace ? */ 231/* utrace ? */
232static int malloc_utrace; 232static int malloc_utrace;
233 233
234struct ut { void *p; size_t s; void *r; }; 234struct ut {
235 void *p;
236 size_t s;
237 void *r;
238};
235 239
236void utrace(struct ut *, int); 240void utrace(struct ut *, int);
237 241
238#define UTRACE(a, b, c) \ 242#define UTRACE(a, b, c) \
239 if (malloc_utrace) \ 243 if (malloc_utrace) \
240 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);} 244 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
241#else /* !__FreeBSD__ */ 245#else /* !__FreeBSD__ */
242#define UTRACE(a,b,c) 246#define UTRACE(a,b,c)
243#endif 247#endif
244 248
245/* Status of malloc. */ 249/* Status of malloc. */
246static int malloc_active; 250static int malloc_active;
247 251
248/* Allocated memory. */ 252/* Allocated memory. */
249static size_t malloc_used; 253static size_t malloc_used;
250 254
251/* My last break. */ 255/* My last break. */
252static void *malloc_brk; 256static void *malloc_brk;
253 257
254/* One location cache for free-list holders. */ 258/* One location cache for free-list holders. */
255static struct pgfree *px; 259static struct pgfree *px;
256 260
257/* Compile-time options. */ 261/* Compile-time options. */
258char *malloc_options; 262char *malloc_options;
259 263
260/* Name of the current public function. */ 264/* Name of the current public function. */
261static char *malloc_func; 265static char *malloc_func;
262 266
263/* Macro for mmap. */ 267/* Macro for mmap. */
264#define MMAP(size) \ 268#define MMAP(size) \
@@ -268,288 +272,290 @@ static char *malloc_func;
268/* 272/*
269 * Necessary function declarations. 273 * Necessary function declarations.
270 */ 274 */
271static void *imalloc(size_t size); 275static void *imalloc(size_t size);
272static void ifree(void *ptr); 276static void ifree(void *ptr);
273static void *irealloc(void *ptr, size_t size); 277static void *irealloc(void *ptr, size_t size);
274static void *malloc_bytes(size_t size); 278static void *malloc_bytes(size_t size);
275 279
276 280
277/* 281/*
278 * Function for page directory lookup. 282 * Function for page directory lookup.
279 */ 283 */
280static int 284static int
281pdir_lookup(u_long index, struct pdinfo **pdi) 285pdir_lookup(u_long index, struct pdinfo ** pdi)
282{ 286{
283 struct pdinfo *spi; 287 struct pdinfo *spi;
284 u_long pidx = PI_IDX(index); 288 u_long pidx = PI_IDX(index);
285 289
286 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx) 290 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
287 *pdi = last_dir; 291 *pdi = last_dir;
288 else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx) 292 else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
289 *pdi = prev_dir; 293 *pdi = prev_dir;
290 else if (last_dir != NULL && prev_dir != NULL) { 294 else if (last_dir != NULL && prev_dir != NULL) {
291 if ((PD_IDX(last_dir->dirnum) > pidx) ? 295 if ((PD_IDX(last_dir->dirnum) > pidx) ?
292 (PD_IDX(last_dir->dirnum) - pidx):(pidx - PD_IDX(last_dir->dirnum)) 296 (PD_IDX(last_dir->dirnum) - pidx) : (pidx - PD_IDX(last_dir->dirnum))
293 < (PD_IDX(prev_dir->dirnum) > pidx) ? 297 < (PD_IDX(prev_dir->dirnum) > pidx) ?
294 (PD_IDX(prev_dir->dirnum) - pidx):(pidx - PD_IDX(prev_dir->dirnum))) 298 (PD_IDX(prev_dir->dirnum) - pidx) : (pidx - PD_IDX(prev_dir->dirnum)))
295 *pdi = last_dir; 299 *pdi = last_dir;
296 else 300 else
297 *pdi = prev_dir; 301 *pdi = prev_dir;
298 302
299 if (PD_IDX((*pdi)->dirnum) > pidx) { 303 if (PD_IDX((*pdi)->dirnum) > pidx) {
300 for (spi=(*pdi)->prev;spi!=NULL && PD_IDX(spi->dirnum)>pidx; 304 for (spi = (*pdi)->prev; spi != NULL && PD_IDX(spi->dirnum) > pidx;
301 spi=spi->prev) 305 spi = spi->prev)
302 *pdi = spi; 306 *pdi = spi;
303 if (spi != NULL) 307 if (spi != NULL)
304 *pdi = spi; 308 *pdi = spi;
305 } else 309 } else
306 for (spi=(*pdi)->next;spi!=NULL && PD_IDX(spi->dirnum)<=pidx; 310 for (spi = (*pdi)->next; spi != NULL && PD_IDX(spi->dirnum) <= pidx;
307 spi=spi->next) 311 spi = spi->next)
308 *pdi = spi; 312 *pdi = spi;
309 } else { 313 } else {
310 *pdi = (struct pdinfo *)((caddr_t)page_dir + pdi_off); 314 *pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
311 for (spi=*pdi;spi!=NULL && PD_IDX(spi->dirnum)<=pidx;spi=spi->next) 315 for (spi = *pdi; spi != NULL && PD_IDX(spi->dirnum) <= pidx; spi = spi->next)
312 *pdi = spi; 316 *pdi = spi;
313 } 317 }
314 318
315 return ((PD_IDX((*pdi)->dirnum) == pidx)?0:(PD_IDX((*pdi)->dirnum) > pidx)?1:-1); 319 return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 : (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1);
316} 320}
317 321
318 322
319#ifdef MALLOC_STATS 323#ifdef MALLOC_STATS
320void 324void
321malloc_dump(FILE *fd) 325malloc_dump(FILE * fd)
322{ 326{
323 struct pginfo **pd; 327 struct pginfo **pd;
324 struct pgfree *pf; 328 struct pgfree *pf;
325 struct pdinfo *pi; 329 struct pdinfo *pi;
326 int j; 330 int j;
327 331
328 pd = page_dir; 332 pd = page_dir;
329 pi = (struct pdinfo *)((caddr_t)pd + pdi_off); 333 pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
330 334
331 /* print out all the pages */ 335 /* print out all the pages */
332 for(j=0;j<=last_index;) { 336 for (j = 0; j <= last_index;) {
333 fprintf(fd, "%08lx %5d ", j << malloc_pageshift, j); 337 fprintf(fd, "%08lx %5d ", j << malloc_pageshift, j);
334 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) { 338 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
335 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) { 339 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
336 if (!PI_OFF(++j)) { 340 if (!PI_OFF(++j)) {
337 if ((pi = pi->next) == NULL || 341 if ((pi = pi->next) == NULL ||
338 PD_IDX(pi->dirnum) != PI_IDX(j)) break; 342 PD_IDX(pi->dirnum) != PI_IDX(j))
339 pd = pi->base; 343 break;
340 j += pdi_mod; 344 pd = pi->base;
345 j += pdi_mod;
346 }
347 }
348 j--;
349 fprintf(fd, ".. %5d not mine\n", j);
350 } else if (pd[PI_OFF(j)] == MALLOC_FREE) {
351 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
352 if (!PI_OFF(++j)) {
353 if ((pi = pi->next) == NULL ||
354 PD_IDX(pi->dirnum) != PI_IDX(j))
355 break;
356 pd = pi->base;
357 j += pdi_mod;
358 }
359 }
360 j--;
361 fprintf(fd, ".. %5d free\n", j);
362 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
363 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
364 if (!PI_OFF(++j)) {
365 if ((pi = pi->next) == NULL ||
366 PD_IDX(pi->dirnum) != PI_IDX(j))
367 break;
368 pd = pi->base;
369 j += pdi_mod;
370 }
371 }
372 j--;
373 fprintf(fd, ".. %5d in use\n", j);
374 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
375 fprintf(fd, "(%p)\n", pd[PI_OFF(j)]);
376 } else {
377 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
378 pd[PI_OFF(j)], pd[PI_OFF(j)]->free, pd[PI_OFF(j)]->total,
379 pd[PI_OFF(j)]->size, pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
341 } 380 }
342 }
343 j--;
344 fprintf(fd, ".. %5d not mine\n", j);
345 } else if (pd[PI_OFF(j)] == MALLOC_FREE) {
346 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
347 if (!PI_OFF(++j)) { 381 if (!PI_OFF(++j)) {
348 if ((pi = pi->next) == NULL || 382 if ((pi = pi->next) == NULL)
349 PD_IDX(pi->dirnum) != PI_IDX(j)) break; 383 break;
350 pd = pi->base; 384 pd = pi->base;
351 j += pdi_mod; 385 j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
352 } 386 }
353 }
354 j--;
355 fprintf(fd, ".. %5d free\n", j);
356 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
357 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
358 if (!PI_OFF(++j)) {
359 if ((pi = pi->next) == NULL ||
360 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
361 pd = pi->base;
362 j += pdi_mod;
363 }
364 }
365 j--;
366 fprintf(fd, ".. %5d in use\n", j);
367 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
368 fprintf(fd, "(%p)\n", pd[PI_OFF(j)]);
369 } else {
370 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
371 pd[PI_OFF(j)], pd[PI_OFF(j)]->free, pd[PI_OFF(j)]->total,
372 pd[PI_OFF(j)]->size, pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
373 } 387 }
374 if (!PI_OFF(++j)) { 388
375 if ((pi = pi->next) == NULL) 389 for (pf = free_list.next; pf; pf = pf->next) {
376 break; 390 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
377 pd = pi->base; 391 pf, pf->page, pf->page + pf->size, pf->size,
378 j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod; 392 pf->prev, pf->next);
379 } 393 if (pf == pf->next) {
380 } 394 fprintf(fd, "Free_list loops\n");
381 395 break;
382 for(pf=free_list.next; pf; pf=pf->next) { 396 }
383 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
384 pf, pf->page, pf->page + pf->size, pf->size,
385 pf->prev, pf->next);
386 if (pf == pf->next) {
387 fprintf(fd, "Free_list loops\n");
388 break;
389 } 397 }
390 } 398
391 399 /* print out various info */
392 /* print out various info */ 400 fprintf(fd, "Minsize\t%d\n", malloc_minsize);
393 fprintf(fd, "Minsize\t%d\n", malloc_minsize); 401 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
394 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize); 402 fprintf(fd, "Pagesize\t%lu\n", (u_long) malloc_pagesize);
395 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize); 403 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
396 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift); 404 fprintf(fd, "In use\t%lu\n", (u_long) malloc_used);
397 fprintf(fd, "In use\t%lu\n", (u_long)malloc_used); 405 fprintf(fd, "Guarded\t%lu\n", (u_long) malloc_guarded);
398 fprintf(fd, "Guarded\t%lu\n", (u_long)malloc_guarded);
399} 406}
400#endif /* MALLOC_STATS */ 407#endif /* MALLOC_STATS */
401 408
402extern char *__progname; 409extern char *__progname;
403 410
404static void 411static void
405wrterror(char *p) 412wrterror(char *p)
406{ 413{
407 char *q = " error: "; 414 char *q = " error: ";
408 struct iovec iov[4]; 415 struct iovec iov[4];
409 416
410 iov[0].iov_base = __progname; 417 iov[0].iov_base = __progname;
411 iov[0].iov_len = strlen(__progname); 418 iov[0].iov_len = strlen(__progname);
412 iov[1].iov_base = malloc_func; 419 iov[1].iov_base = malloc_func;
413 iov[1].iov_len = strlen(malloc_func); 420 iov[1].iov_len = strlen(malloc_func);
414 iov[2].iov_base = q; 421 iov[2].iov_base = q;
415 iov[2].iov_len = strlen(q); 422 iov[2].iov_len = strlen(q);
416 iov[3].iov_base = p; 423 iov[3].iov_base = p;
417 iov[3].iov_len = strlen(p); 424 iov[3].iov_len = strlen(p);
418 writev(STDERR_FILENO, iov, 4); 425 writev(STDERR_FILENO, iov, 4);
419 426
420 suicide = 1; 427 suicide = 1;
421#ifdef MALLOC_STATS 428#ifdef MALLOC_STATS
422 if (malloc_stats) 429 if (malloc_stats)
423 malloc_dump(stderr); 430 malloc_dump(stderr);
424#endif /* MALLOC_STATS */ 431#endif /* MALLOC_STATS */
425 malloc_active--; 432 malloc_active--;
426 if (malloc_abort) 433 if (malloc_abort)
427 abort(); 434 abort();
428} 435}
429 436
430static void 437static void
431wrtwarning(char *p) 438wrtwarning(char *p)
432{ 439{
433 char *q = " warning: "; 440 char *q = " warning: ";
434 struct iovec iov[4]; 441 struct iovec iov[4];
435 442
436 if (malloc_abort) 443 if (malloc_abort)
437 wrterror(p); 444 wrterror(p);
438 else if (malloc_silent) 445 else if (malloc_silent)
439 return; 446 return;
440 447
441 iov[0].iov_base = __progname; 448 iov[0].iov_base = __progname;
442 iov[0].iov_len = strlen(__progname); 449 iov[0].iov_len = strlen(__progname);
443 iov[1].iov_base = malloc_func; 450 iov[1].iov_base = malloc_func;
444 iov[1].iov_len = strlen(malloc_func); 451 iov[1].iov_len = strlen(malloc_func);
445 iov[2].iov_base = q; 452 iov[2].iov_base = q;
446 iov[2].iov_len = strlen(q); 453 iov[2].iov_len = strlen(q);
447 iov[3].iov_base = p; 454 iov[3].iov_base = p;
448 iov[3].iov_len = strlen(p); 455 iov[3].iov_len = strlen(p);
449 writev(STDERR_FILENO, iov, 4); 456 writev(STDERR_FILENO, iov, 4);
450} 457}
451 458
452#ifdef MALLOC_STATS 459#ifdef MALLOC_STATS
453static void 460static void
454malloc_exit(void) 461malloc_exit(void)
455{ 462{
456 FILE *fd = fopen("malloc.out", "a"); 463 FILE *fd = fopen("malloc.out", "a");
457 char *q = "malloc() warning: Couldn't dump stats\n"; 464 char *q = "malloc() warning: Couldn't dump stats\n";
458 if (fd != NULL) { 465 if (fd != NULL) {
459 malloc_dump(fd); 466 malloc_dump(fd);
460 fclose(fd); 467 fclose(fd);
461 } else 468 } else
462 write(STDERR_FILENO, q, strlen(q)); 469 write(STDERR_FILENO, q, strlen(q));
463} 470}
464#endif /* MALLOC_STATS */ 471#endif /* MALLOC_STATS */
465 472
466 473
467/* 474/*
468 * Allocate a number of pages from the OS 475 * Allocate a number of pages from the OS
469 */ 476 */
470static void * 477static void *
471map_pages(size_t pages) 478map_pages(size_t pages)
472{ 479{
473 struct pdinfo *pi, *spi; 480 struct pdinfo *pi, *spi;
474 struct pginfo **pd; 481 struct pginfo **pd;
475 u_long idx, pidx, lidx; 482 u_long idx, pidx, lidx;
476 void *result, *tail; 483 void *result, *tail;
477 u_long index, lindex; 484 u_long index, lindex;
478 485
479 pages <<= malloc_pageshift; 486 pages <<= malloc_pageshift;
480 result = MMAP(pages + malloc_guard); 487 result = MMAP(pages + malloc_guard);
481 if (result == MAP_FAILED) { 488 if (result == MAP_FAILED) {
482 errno = ENOMEM;
483#ifdef MALLOC_EXTRA_SANITY
484 wrtwarning("(ES): map_pages fails\n");
485#endif /* MALLOC_EXTRA_SANITY */
486 return (NULL);
487 }
488 index = ptr2index(result);
489 tail = result + pages + malloc_guard;
490 lindex = ptr2index(tail) - 1;
491 if (malloc_guard)
492 mprotect(result + pages, malloc_guard, PROT_NONE);
493
494 pidx = PI_IDX(index);
495 lidx = PI_IDX(lindex);
496
497 if (tail > malloc_brk) {
498 malloc_brk = tail;
499 last_index = lindex;
500 }
501
502 /* Insert directory pages, if needed. */
503 pdir_lookup(index, &pi);
504
505 for (idx=pidx,spi=pi;idx<=lidx;idx++) {
506 if (pi == NULL || PD_IDX(pi->dirnum) != idx) {
507 if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) {
508 errno = ENOMEM; 489 errno = ENOMEM;
509 munmap(result, tail - result);
510#ifdef MALLOC_EXTRA_SANITY 490#ifdef MALLOC_EXTRA_SANITY
511 wrtwarning("(ES): map_pages fails\n"); 491 wrtwarning("(ES): map_pages fails\n");
512#endif /* MALLOC_EXTRA_SANITY */ 492#endif /* MALLOC_EXTRA_SANITY */
513 return (NULL); 493 return (NULL);
514 }
515 memset(pd, 0, malloc_pagesize);
516 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
517 pi->base = pd;
518 pi->prev = spi;
519 pi->next = spi->next;
520 pi->dirnum = idx * (malloc_pagesize/sizeof(struct pginfo *));
521
522 if (spi->next != NULL)
523 spi->next->prev = pi;
524 spi->next = pi;
525 } 494 }
526 if (idx > pidx && idx < lidx) { 495 index = ptr2index(result);
527 pi->dirnum += pdi_mod; 496 tail = result + pages + malloc_guard;
528 } else if (idx == pidx) { 497 lindex = ptr2index(tail) - 1;
529 if (pidx == lidx) { 498 if (malloc_guard)
530 pi->dirnum += (tail - result) >> malloc_pageshift; 499 mprotect(result + pages, malloc_guard, PROT_NONE);
531 } else { 500
532 pi->dirnum += pdi_mod - PI_OFF(index); 501 pidx = PI_IDX(index);
533 } 502 lidx = PI_IDX(lindex);
534 } else { 503
535 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1; 504 if (tail > malloc_brk) {
505 malloc_brk = tail;
506 last_index = lindex;
536 } 507 }
508 /* Insert directory pages, if needed. */
509 pdir_lookup(index, &pi);
510
511 for (idx = pidx, spi = pi; idx <= lidx; idx++) {
512 if (pi == NULL || PD_IDX(pi->dirnum) != idx) {
513 if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) {
514 errno = ENOMEM;
515 munmap(result, tail - result);
537#ifdef MALLOC_EXTRA_SANITY 516#ifdef MALLOC_EXTRA_SANITY
538 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) { 517 wrtwarning("(ES): map_pages fails\n");
539 wrterror("(ES): pages directory overflow\n"); 518#endif /* MALLOC_EXTRA_SANITY */
540 errno = EFAULT; 519 return (NULL);
541 return (NULL); 520 }
542 } 521 memset(pd, 0, malloc_pagesize);
543#endif /* MALLOC_EXTRA_SANITY */ 522 pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
544 if (idx == pidx && pi != last_dir) { 523 pi->base = pd;
545 prev_dir = last_dir; 524 pi->prev = spi;
546 last_dir = pi; 525 pi->next = spi->next;
526 pi->dirnum = idx * (malloc_pagesize / sizeof(struct pginfo *));
527
528 if (spi->next != NULL)
529 spi->next->prev = pi;
530 spi->next = pi;
531 }
532 if (idx > pidx && idx < lidx) {
533 pi->dirnum += pdi_mod;
534 } else if (idx == pidx) {
535 if (pidx == lidx) {
536 pi->dirnum += (tail - result) >> malloc_pageshift;
537 } else {
538 pi->dirnum += pdi_mod - PI_OFF(index);
539 }
540 } else {
541 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
542 }
543#ifdef MALLOC_EXTRA_SANITY
544 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) {
545 wrterror("(ES): pages directory overflow\n");
546 errno = EFAULT;
547 return (NULL);
548 }
549#endif /* MALLOC_EXTRA_SANITY */
550 if (idx == pidx && pi != last_dir) {
551 prev_dir = last_dir;
552 last_dir = pi;
553 }
554 spi = pi;
555 pi = spi->next;
547 } 556 }
548 spi = pi;
549 pi = spi->next;
550 }
551 557
552 return (result); 558 return (result);
553} 559}
554 560
555 561
@@ -559,315 +565,363 @@ map_pages(size_t pages)
559static void 565static void
560malloc_init(void) 566malloc_init(void)
561{ 567{
562 char *p, b[64]; 568 char *p, b[64];
563 int i, j; 569 int i, j;
564 int save_errno = errno; 570 int save_errno = errno;
565 571
566 _MALLOC_LOCK_INIT(); 572 _MALLOC_LOCK_INIT();
567 573
568 INIT_MMAP(); 574 INIT_MMAP();
569 575
570#ifdef MALLOC_EXTRA_SANITY 576#ifdef MALLOC_EXTRA_SANITY
571 malloc_junk = 1; 577 malloc_junk = 1;
572#endif /* MALLOC_EXTRA_SANITY */ 578#endif /* MALLOC_EXTRA_SANITY */
573 579
574 for (i = 0; i < 3; i++) { 580 for (i = 0; i < 3; i++) {
575 switch (i) { 581 switch (i) {
576 case 0: 582 case 0:
577 j = readlink("/etc/malloc.conf", b, sizeof b - 1); 583 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
578 if (j <= 0) 584 if (j <= 0)
579 continue; 585 continue;
580 b[j] = '\0'; 586 b[j] = '\0';
581 p = b; 587 p = b;
582 break; 588 break;
583 589
584 case 1: 590 case 1:
585 if (issetugid() == 0) 591 if (issetugid() == 0)
586 p = getenv("MALLOC_OPTIONS"); 592 p = getenv("MALLOC_OPTIONS");
587 else 593 else
588 continue; 594 continue;
589 break; 595 break;
590 596
591 case 2: 597 case 2:
592 p = malloc_options; 598 p = malloc_options;
593 break; 599 break;
594 600
595 default: p = NULL; 601 default:
596 } 602 p = NULL;
597 for (; p != NULL && *p != '\0'; p++) { 603 }
598 switch (*p) { 604 for (; p != NULL && *p != '\0'; p++) {
599 case '>': malloc_cache <<= 1; break; 605 switch (*p) {
600 case '<': malloc_cache >>= 1; break; 606 case '>':
601 case 'a': malloc_abort = 0; break; 607 malloc_cache <<= 1;
602 case 'A': malloc_abort = 1; break; 608 break;
609 case '<':
610 malloc_cache >>= 1;
611 break;
612 case 'a':
613 malloc_abort = 0;
614 break;
615 case 'A':
616 malloc_abort = 1;
617 break;
603#ifdef MALLOC_STATS 618#ifdef MALLOC_STATS
604 case 'd': malloc_stats = 0; break; 619 case 'd':
605 case 'D': malloc_stats = 1; break; 620 malloc_stats = 0;
606#endif /* MALLOC_STATS */ 621 break;
607 case 'f': malloc_freeprot = 0; break; 622 case 'D':
608 case 'F': malloc_freeprot = 1; break; 623 malloc_stats = 1;
609 case 'g': malloc_guard = 0; break; 624 break;
610 case 'G': malloc_guard = malloc_pagesize; break; 625#endif /* MALLOC_STATS */
626 case 'f':
627 malloc_freeprot = 0;
628 break;
629 case 'F':
630 malloc_freeprot = 1;
631 break;
632 case 'g':
633 malloc_guard = 0;
634 break;
635 case 'G':
636 malloc_guard = malloc_pagesize;
637 break;
611#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE)) 638#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
612 case 'h': malloc_hint = 0; break; 639 case 'h':
613 case 'H': malloc_hint = 1; break; 640 malloc_hint = 0;
614#endif /* __FreeBSD__ */ 641 break;
615 case 'j': malloc_junk = 0; break; 642 case 'H':
616 case 'J': malloc_junk = 1; break; 643 malloc_hint = 1;
617 case 'n': malloc_silent = 0; break; 644 break;
618 case 'N': malloc_silent = 1; break; 645#endif /* __FreeBSD__ */
619 case 'p': malloc_ptrguard = 0; break; 646 case 'j':
620 case 'P': malloc_ptrguard = 1; break; 647 malloc_junk = 0;
621 case 'r': malloc_realloc = 0; break; 648 break;
622 case 'R': malloc_realloc = 1; break; 649 case 'J':
650 malloc_junk = 1;
651 break;
652 case 'n':
653 malloc_silent = 0;
654 break;
655 case 'N':
656 malloc_silent = 1;
657 break;
658 case 'p':
659 malloc_ptrguard = 0;
660 break;
661 case 'P':
662 malloc_ptrguard = 1;
663 break;
664 case 'r':
665 malloc_realloc = 0;
666 break;
667 case 'R':
668 malloc_realloc = 1;
669 break;
623#ifdef __FreeBSD__ 670#ifdef __FreeBSD__
624 case 'u': malloc_utrace = 0; break; 671 case 'u':
625 case 'U': malloc_utrace = 1; break; 672 malloc_utrace = 0;
626#endif /* __FreeBSD__ */ 673 break;
627 case 'x': malloc_xmalloc = 0; break; 674 case 'U':
628 case 'X': malloc_xmalloc = 1; break; 675 malloc_utrace = 1;
629 case 'z': malloc_zero = 0; break; 676 break;
630 case 'Z': malloc_zero = 1; break; 677#endif /* __FreeBSD__ */
631 default: 678 case 'x':
632 j = malloc_abort; 679 malloc_xmalloc = 0;
633 malloc_abort = 0; 680 break;
634 wrtwarning("unknown char in MALLOC_OPTIONS\n"); 681 case 'X':
635 malloc_abort = j; 682 malloc_xmalloc = 1;
636 break; 683 break;
637 } 684 case 'z':
685 malloc_zero = 0;
686 break;
687 case 'Z':
688 malloc_zero = 1;
689 break;
690 default:
691 j = malloc_abort;
692 malloc_abort = 0;
693 wrtwarning("unknown char in MALLOC_OPTIONS\n");
694 malloc_abort = j;
695 break;
696 }
697 }
638 } 698 }
639 }
640 699
641 UTRACE(0, 0, 0); 700 UTRACE(0, 0, 0);
642 701
643 /* 702 /*
644 * We want junk in the entire allocation, and zero only in the part 703 * We want junk in the entire allocation, and zero only in the part
645 * the user asked for. 704 * the user asked for.
646 */ 705 */
647 if (malloc_zero) 706 if (malloc_zero)
648 malloc_junk=1; 707 malloc_junk = 1;
649 708
650#ifdef MALLOC_STATS 709#ifdef MALLOC_STATS
651 if (malloc_stats && (atexit(malloc_exit) == -1)) 710 if (malloc_stats && (atexit(malloc_exit) == -1))
652 wrtwarning("atexit(2) failed. Will not be able to dump malloc stats on exit\n"); 711 wrtwarning("atexit(2) failed. Will not be able to dump malloc stats on exit\n");
653#endif /* MALLOC_STATS */ 712#endif /* MALLOC_STATS */
654 713
655 /* Allocate one page for the page directory. */ 714 /* Allocate one page for the page directory. */
656 page_dir = (struct pginfo **) MMAP(malloc_pagesize); 715 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
657 716
658 if (page_dir == MAP_FAILED) { 717 if (page_dir == MAP_FAILED) {
659 wrterror("mmap(2) failed, check limits\n"); 718 wrterror("mmap(2) failed, check limits\n");
660 errno = ENOMEM; 719 errno = ENOMEM;
661 return; 720 return;
662 } 721 }
663 722 pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1);
664 pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1); 723 pdi_mod = pdi_off / sizeof(struct pginfo *);
665 pdi_mod = pdi_off / sizeof(struct pginfo *);
666 724
667 last_dir = (struct pdinfo *)((caddr_t)page_dir + pdi_off); 725 last_dir = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
668 last_dir->base = page_dir; 726 last_dir->base = page_dir;
669 last_dir->prev = last_dir->next = NULL; 727 last_dir->prev = last_dir->next = NULL;
670 last_dir->dirnum = malloc_pageshift; 728 last_dir->dirnum = malloc_pageshift;
671 729
672 /* Been here, done that. */ 730 /* Been here, done that. */
673 malloc_started++; 731 malloc_started++;
674 732
675 /* Recalculate the cache size in bytes, and make sure it's nonzero. */ 733 /* Recalculate the cache size in bytes, and make sure it's nonzero. */
676 734
677 if (!malloc_cache) 735 if (!malloc_cache)
678 malloc_cache++; 736 malloc_cache++;
679 737
680 malloc_cache <<= malloc_pageshift; 738 malloc_cache <<= malloc_pageshift;
681 739
682 errno = save_errno; 740 errno = save_errno;
683} 741}
684 742
685/* 743/*
686 * Allocate a number of complete pages 744 * Allocate a number of complete pages
687 */ 745 */
688static void * 746static void *
689malloc_pages(size_t size) 747malloc_pages(size_t size)
690{ 748{
691 void *p, *delay_free = NULL; 749 void *p, *delay_free = NULL;
692 int i; 750 int i;
693 struct rlimit rl; 751 struct rlimit rl;
694 struct pginfo **pd; 752 struct pginfo **pd;
695 struct pdinfo *pi; 753 struct pdinfo *pi;
696 u_long pidx; 754 u_long pidx;
697 void *tp; 755 void *tp;
698 struct pgfree *pf; 756 struct pgfree *pf;
699 u_long index; 757 u_long index;
700 int m; 758 int m;
701 759
702 size = pageround(size) + malloc_guard; 760 size = pageround(size) + malloc_guard;
703 761
704 p = NULL; 762 p = NULL;
705 /* Look for free pages before asking for more */ 763 /* Look for free pages before asking for more */
706 for (pf = free_list.next; pf; pf = pf->next) { 764 for (pf = free_list.next; pf; pf = pf->next) {
707 765
708#ifdef MALLOC_EXTRA_SANITY 766#ifdef MALLOC_EXTRA_SANITY
709 if (pf->size & malloc_pagemask) { 767 if (pf->size & malloc_pagemask) {
710 wrterror("(ES): junk length entry on free_list\n"); 768 wrterror("(ES): junk length entry on free_list\n");
711 errno = EFAULT; 769 errno = EFAULT;
712 return (NULL); 770 return (NULL);
713 } 771 }
714 if (!pf->size) { 772 if (!pf->size) {
715 wrterror("(ES): zero length entry on free_list\n"); 773 wrterror("(ES): zero length entry on free_list\n");
716 errno = EFAULT; 774 errno = EFAULT;
717 return (NULL); 775 return (NULL);
718 } 776 }
719 if (pf->page > (pf->page + pf->size)) { 777 if (pf->page > (pf->page + pf->size)) {
720 wrterror("(ES): sick entry on free_list\n"); 778 wrterror("(ES): sick entry on free_list\n");
721 errno = EFAULT; 779 errno = EFAULT;
722 return (NULL); 780 return (NULL);
723 } 781 }
724 if ((pi = pf->pdir) == NULL) { 782 if ((pi = pf->pdir) == NULL) {
725 wrterror("(ES): invalid page directory on free-list\n"); 783 wrterror("(ES): invalid page directory on free-list\n");
726 errno = EFAULT; 784 errno = EFAULT;
727 return (NULL); 785 return (NULL);
728 } 786 }
729 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) { 787 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
730 wrterror("(ES): directory index mismatch on free-list\n"); 788 wrterror("(ES): directory index mismatch on free-list\n");
731 errno = EFAULT; 789 errno = EFAULT;
732 return (NULL); 790 return (NULL);
733 } 791 }
734 pd = pi->base; 792 pd = pi->base;
735 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) { 793 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
736 wrterror("(ES): non-free first page on free-list\n"); 794 wrterror("(ES): non-free first page on free-list\n");
737 errno = EFAULT; 795 errno = EFAULT;
738 return (NULL); 796 return (NULL);
739 } 797 }
740 pidx = PI_IDX(ptr2index((pf->page)+(pf->size))-1); 798 pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1);
741 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next); 799 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; pi = pi->next);
742 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 800 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
743 wrterror("(ES): last page not referenced in page directory\n"); 801 wrterror("(ES): last page not referenced in page directory\n");
744 errno = EFAULT; 802 errno = EFAULT;
745 return (NULL); 803 return (NULL);
746 } 804 }
747 pd = pi->base; 805 pd = pi->base;
748 if (pd[PI_OFF(ptr2index((pf->page)+(pf->size))-1)] != MALLOC_FREE) { 806 if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) {
749 wrterror("(ES): non-free last page on free-list\n"); 807 wrterror("(ES): non-free last page on free-list\n");
750 errno = EFAULT; 808 errno = EFAULT;
751 return (NULL); 809 return (NULL);
752 } 810 }
753#endif /* MALLOC_EXTRA_SANITY */ 811#endif /* MALLOC_EXTRA_SANITY */
754 812
755 if (pf->size < size) 813 if (pf->size < size)
756 continue; 814 continue;
757 815
758 if (pf->size == size) { 816 if (pf->size == size) {
759 p = pf->page; 817 p = pf->page;
760 pi = pf->pdir; 818 pi = pf->pdir;
761 if (pf->next != NULL) 819 if (pf->next != NULL)
762 pf->next->prev = pf->prev; 820 pf->next->prev = pf->prev;
763 pf->prev->next = pf->next; 821 pf->prev->next = pf->next;
764 delay_free = pf; 822 delay_free = pf;
765 break; 823 break;
766 } 824 }
767 825 p = pf->page;
768 p = pf->page; 826 pf->page = (char *) pf->page + size;
769 pf->page = (char *)pf->page + size; 827 pf->size -= size;
770 pf->size -= size; 828 pidx = PI_IDX(ptr2index(pf->page));
771 pidx = PI_IDX(ptr2index(pf->page)); 829 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; pi = pi->next);
772 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next); 830 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
773 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 831 wrterror("(ES): hole in directories\n");
774 wrterror("(ES): hole in directories\n"); 832 errno = EFAULT;
775 errno = EFAULT; 833 return (NULL);
776 return (NULL); 834 }
835 tp = pf->pdir;
836 pf->pdir = pi;
837 pi = tp;
838 break;
777 } 839 }
778 tp = pf->pdir;
779 pf->pdir = pi;
780 pi = tp;
781 break;
782 }
783 840
784 size -= malloc_guard; 841 size -= malloc_guard;
785 842
786#ifdef MALLOC_EXTRA_SANITY 843#ifdef MALLOC_EXTRA_SANITY
787 if (p != NULL && pi != NULL) { 844 if (p != NULL && pi != NULL) {
788 pidx = PD_IDX(pi->dirnum); 845 pidx = PD_IDX(pi->dirnum);
789 pd = pi->base; 846 pd = pi->base;
790 } 847 }
791 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) { 848 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
792 wrterror("(ES): allocated non-free page on free-list\n"); 849 wrterror("(ES): allocated non-free page on free-list\n");
793 errno = EFAULT; 850 errno = EFAULT;
794 return (NULL); 851 return (NULL);
795 } 852 }
796#endif /* MALLOC_EXTRA_SANITY */ 853#endif /* MALLOC_EXTRA_SANITY */
797 854
798 if (p != NULL && (malloc_guard || malloc_freeprot)) 855 if (p != NULL && (malloc_guard || malloc_freeprot))
799 mprotect(p, size, PROT_READ|PROT_WRITE); 856 mprotect(p, size, PROT_READ | PROT_WRITE);
800 857
801 size >>= malloc_pageshift; 858 size >>= malloc_pageshift;
802 859
803 /* Map new pages */ 860 /* Map new pages */
804 if (p == NULL) 861 if (p == NULL)
805 p = map_pages(size); 862 p = map_pages(size);
806 863
807 if (p != NULL) { 864 if (p != NULL) {
808 865
809 index = ptr2index(p); 866 index = ptr2index(p);
810 pidx = PI_IDX(index); 867 pidx = PI_IDX(index);
811 pdir_lookup(index, &pi); 868 pdir_lookup(index, &pi);
812#ifdef MALLOC_EXTRA_SANITY
813 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
814 wrterror("(ES): mapped pages not found in directory\n");
815 errno = EFAULT;
816 return (NULL);
817 }
818#endif /* MALLOC_EXTRA_SANITY */
819 if (pi != last_dir) {
820 prev_dir = last_dir;
821 last_dir = pi;
822 }
823 pd = pi->base;
824 pd[PI_OFF(index)] = MALLOC_FIRST;
825 for (i=1;i<size;i++) {
826 if (!PI_OFF(index+i)) {
827 pidx++;
828 pi = pi->next;
829#ifdef MALLOC_EXTRA_SANITY 869#ifdef MALLOC_EXTRA_SANITY
830 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 870 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
831 wrterror("(ES): hole in mapped pages directory\n"); 871 wrterror("(ES): mapped pages not found in directory\n");
832 errno = EFAULT; 872 errno = EFAULT;
833 return (NULL); 873 return (NULL);
874 }
875#endif /* MALLOC_EXTRA_SANITY */
876 if (pi != last_dir) {
877 prev_dir = last_dir;
878 last_dir = pi;
834 } 879 }
835#endif /* MALLOC_EXTRA_SANITY */
836 pd = pi->base; 880 pd = pi->base;
837 } 881 pd[PI_OFF(index)] = MALLOC_FIRST;
838 pd[PI_OFF(index+i)] = MALLOC_FOLLOW; 882 for (i = 1; i < size; i++) {
839 } 883 if (!PI_OFF(index + i)) {
840 if (malloc_guard) { 884 pidx++;
841 if (!PI_OFF(index+i)) { 885 pi = pi->next;
842 pidx++;
843 pi = pi->next;
844#ifdef MALLOC_EXTRA_SANITY 886#ifdef MALLOC_EXTRA_SANITY
845 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 887 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
846 wrterror("(ES): hole in mapped pages directory\n"); 888 wrterror("(ES): hole in mapped pages directory\n");
847 errno = EFAULT; 889 errno = EFAULT;
848 return (NULL); 890 return (NULL);
891 }
892#endif /* MALLOC_EXTRA_SANITY */
893 pd = pi->base;
894 }
895 pd[PI_OFF(index + i)] = MALLOC_FOLLOW;
849 } 896 }
850#endif /* MALLOC_EXTRA_SANITY */ 897 if (malloc_guard) {
851 pd = pi->base; 898 if (!PI_OFF(index + i)) {
852 } 899 pidx++;
853 pd[PI_OFF(index+i)] = MALLOC_FIRST; 900 pi = pi->next;
854 } 901#ifdef MALLOC_EXTRA_SANITY
855 902 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
856 malloc_used += size << malloc_pageshift; 903 wrterror("(ES): hole in mapped pages directory\n");
857 malloc_guarded += malloc_guard; 904 errno = EFAULT;
858 905 return (NULL);
859 if (malloc_junk) 906 }
860 memset(p, SOME_JUNK, size << malloc_pageshift); 907#endif /* MALLOC_EXTRA_SANITY */
861 } 908 pd = pi->base;
862 909 }
863 if (delay_free) { 910 pd[PI_OFF(index + i)] = MALLOC_FIRST;
864 if (px == NULL) 911 }
865 px = delay_free; 912 malloc_used += size << malloc_pageshift;
866 else 913 malloc_guarded += malloc_guard;
867 ifree(delay_free);
868 }
869 914
870 return (p); 915 if (malloc_junk)
916 memset(p, SOME_JUNK, size << malloc_pageshift);
917 }
918 if (delay_free) {
919 if (px == NULL)
920 px = delay_free;
921 else
922 ifree(delay_free);
923 }
924 return (p);
871} 925}
872 926
873/* 927/*
@@ -877,194 +931,191 @@ malloc_pages(size_t size)
877static __inline__ int 931static __inline__ int
878malloc_make_chunks(int bits) 932malloc_make_chunks(int bits)
879{ 933{
880 struct pginfo *bp; 934 struct pginfo *bp;
881 struct pginfo **pd; 935 struct pginfo **pd;
882 struct pdinfo *pi; 936 struct pdinfo *pi;
883 u_long pidx; 937 u_long pidx;
884 void *pp; 938 void *pp;
885 int i, k, l; 939 int i, k, l;
886 940
887 /* Allocate a new bucket */ 941 /* Allocate a new bucket */
888 pp = malloc_pages((size_t)malloc_pagesize); 942 pp = malloc_pages((size_t) malloc_pagesize);
889 if (pp == NULL) 943 if (pp == NULL)
890 return (0); 944 return (0);
891 945
892 /* Find length of admin structure */ 946 /* Find length of admin structure */
893 l = sizeof *bp - sizeof(u_long); 947 l = sizeof *bp - sizeof(u_long);
894 l += sizeof(u_long) * 948 l += sizeof(u_long) *
895 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS); 949 (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS);
896 950
897 /* Don't waste more than two chunks on this */ 951 /* Don't waste more than two chunks on this */
898 /* 952 /*
899 * If we are to allocate a memory protected page for the malloc(0) 953 * If we are to allocate a memory protected page for the malloc(0)
900 * case (when bits=0), it must be from a different page than the 954 * case (when bits=0), it must be from a different page than the
901 * pginfo page. 955 * pginfo page.
902 * --> Treat it like the big chunk alloc, get a second data page. 956 * --> Treat it like the big chunk alloc, get a second data page.
903 */ 957 */
904 if (bits != 0 && (1UL<<(bits)) <= l+l) { 958 if (bits != 0 && (1UL << (bits)) <= l + l) {
905 bp = (struct pginfo *)pp; 959 bp = (struct pginfo *) pp;
906 } else { 960 } else {
907 bp = (struct pginfo *)imalloc(l); 961 bp = (struct pginfo *) imalloc(l);
908 if (bp == NULL) { 962 if (bp == NULL) {
909 ifree(pp); 963 ifree(pp);
910 return (0); 964 return (0);
911 } 965 }
912 }
913
914 /* memory protect the page allocated in the malloc(0) case */
915 if (bits == 0) {
916
917 bp->size = 0;
918 bp->shift = 1;
919 i = malloc_minsize-1;
920 while (i >>= 1)
921 bp->shift++;
922 bp->total = bp->free = malloc_pagesize >> bp->shift;
923 bp->page = pp;
924
925 k = mprotect(pp, malloc_pagesize, PROT_NONE);
926 if (k < 0) {
927 ifree(pp);
928 ifree(bp);
929 return (0);
930 } 966 }
931 } else { 967
932 bp->size = (1UL<<bits); 968 /* memory protect the page allocated in the malloc(0) case */
933 bp->shift = bits; 969 if (bits == 0) {
934 bp->total = bp->free = malloc_pagesize >> bits; 970
935 bp->page = pp; 971 bp->size = 0;
936 } 972 bp->shift = 1;
937 973 i = malloc_minsize - 1;
938 /* set all valid bits in the bitmap */ 974 while (i >>= 1)
939 k = bp->total; 975 bp->shift++;
940 i = 0; 976 bp->total = bp->free = malloc_pagesize >> bp->shift;
941 977 bp->page = pp;
942 /* Do a bunch at a time */ 978
943 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS) 979 k = mprotect(pp, malloc_pagesize, PROT_NONE);
944 bp->bits[i / MALLOC_BITS] = ~0UL; 980 if (k < 0) {
945 981 ifree(pp);
946 for(; i < k; i++) 982 ifree(bp);
947 bp->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS); 983 return (0);
948 984 }
949 if (bp == bp->page) { 985 } else {
950 /* Mark the ones we stole for ourselves */ 986 bp->size = (1UL << bits);
951 for(i=0;l > 0;i++) { 987 bp->shift = bits;
952 bp->bits[i/MALLOC_BITS] &= ~(1UL<<(i%MALLOC_BITS)); 988 bp->total = bp->free = malloc_pagesize >> bits;
953 bp->free--; 989 bp->page = pp;
954 bp->total--;
955 l -= (1 << bits);
956 } 990 }
957 }
958 991
959 /* MALLOC_LOCK */ 992 /* set all valid bits in the bitmap */
993 k = bp->total;
994 i = 0;
995
996 /* Do a bunch at a time */
997 for (; k - i >= MALLOC_BITS; i += MALLOC_BITS)
998 bp->bits[i / MALLOC_BITS] = ~0UL;
999
1000 for (; i < k; i++)
1001 bp->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
960 1002
961 pidx = PI_IDX(ptr2index(pp)); 1003 if (bp == bp->page) {
962 pdir_lookup(ptr2index(pp), &pi); 1004 /* Mark the ones we stole for ourselves */
1005 for (i = 0; l > 0; i++) {
1006 bp->bits[i / MALLOC_BITS] &= ~(1UL << (i % MALLOC_BITS));
1007 bp->free--;
1008 bp->total--;
1009 l -= (1 << bits);
1010 }
1011 }
1012 /* MALLOC_LOCK */
1013
1014 pidx = PI_IDX(ptr2index(pp));
1015 pdir_lookup(ptr2index(pp), &pi);
963#ifdef MALLOC_EXTRA_SANITY 1016#ifdef MALLOC_EXTRA_SANITY
964 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1017 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
965 wrterror("(ES): mapped pages not found in directory\n"); 1018 wrterror("(ES): mapped pages not found in directory\n");
966 errno = EFAULT; 1019 errno = EFAULT;
967 return (0); 1020 return (0);
968 } 1021 }
969#endif /* MALLOC_EXTRA_SANITY */ 1022#endif /* MALLOC_EXTRA_SANITY */
970 if (pi != last_dir) { 1023 if (pi != last_dir) {
971 prev_dir = last_dir; 1024 prev_dir = last_dir;
972 last_dir = pi; 1025 last_dir = pi;
973 } 1026 }
974 pd = pi->base; 1027 pd = pi->base;
975 pd[PI_OFF(ptr2index(pp))] = bp; 1028 pd[PI_OFF(ptr2index(pp))] = bp;
976 1029
977 bp->next = page_dir[bits]; 1030 bp->next = page_dir[bits];
978 page_dir[bits] = bp; 1031 page_dir[bits] = bp;
979 1032
980 /* MALLOC_UNLOCK */ 1033 /* MALLOC_UNLOCK */
981 1034
982 return (1); 1035 return (1);
983} 1036}
984 1037
985/* 1038/*
986 * Allocate a fragment 1039 * Allocate a fragment
987 */ 1040 */
988static void * 1041static void *
989malloc_bytes(size_t size) 1042malloc_bytes(size_t size)
990{ 1043{
991 int i,j; 1044 int i, j;
992 u_long u; 1045 u_long u;
993 struct pginfo *bp; 1046 struct pginfo *bp;
994 int k; 1047 int k;
995 u_long *lp; 1048 u_long *lp;
996 1049
997 /* Don't bother with anything less than this */ 1050 /* Don't bother with anything less than this */
998 /* unless we have a malloc(0) requests */ 1051 /* unless we have a malloc(0) requests */
999 if (size != 0 && size < malloc_minsize) 1052 if (size != 0 && size < malloc_minsize)
1000 size = malloc_minsize; 1053 size = malloc_minsize;
1001 1054
1002 /* Find the right bucket */ 1055 /* Find the right bucket */
1003 if (size == 0) 1056 if (size == 0)
1004 j=0; 1057 j = 0;
1005 else { 1058 else {
1006 j = 1; 1059 j = 1;
1007 i = size-1; 1060 i = size - 1;
1008 while (i >>= 1) 1061 while (i >>= 1)
1009 j++; 1062 j++;
1010 } 1063 }
1011 1064
1012 /* If it's empty, make a page more of that size chunks */ 1065 /* If it's empty, make a page more of that size chunks */
1013 if (page_dir[j] == NULL && !malloc_make_chunks(j)) 1066 if (page_dir[j] == NULL && !malloc_make_chunks(j))
1014 return (NULL);
1015
1016 bp = page_dir[j];
1017
1018 /* Find first word of bitmap which isn't empty */
1019 for (lp = bp->bits; !*lp; lp++)
1020 ;
1021
1022 /* Find that bit, and tweak it */
1023 u = 1;
1024 k = 0;
1025 while (!(*lp & u)) {
1026 u += u;
1027 k++;
1028 }
1029
1030 if (malloc_guard) {
1031 /* Walk to a random position. */
1032 i = arc4random() % bp->free;
1033 while (i > 0) {
1034 u += u;
1035 k++;
1036 if (k >= MALLOC_BITS) {
1037 lp++;
1038 u = 1;
1039 k = 0;
1040 }
1041#ifdef MALLOC_EXTRA_SANITY
1042 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
1043 wrterror("chunk overflow\n");
1044 errno = EFAULT;
1045 return (NULL); 1067 return (NULL);
1046 } 1068
1047#endif /* MALLOC_EXTRA_SANITY */ 1069 bp = page_dir[j];
1048 if (*lp & u) 1070
1049 i--; 1071 /* Find first word of bitmap which isn't empty */
1072 for (lp = bp->bits; !*lp; lp++);
1073
1074 /* Find that bit, and tweak it */
1075 u = 1;
1076 k = 0;
1077 while (!(*lp & u)) {
1078 u += u;
1079 k++;
1050 } 1080 }
1051 }
1052 *lp ^= u;
1053 1081
1054 /* If there are no more free, remove from free-list */ 1082 if (malloc_guard) {
1055 if (!--bp->free) { 1083 /* Walk to a random position. */
1056 page_dir[j] = bp->next; 1084 i = arc4random() % bp->free;
1057 bp->next = NULL; 1085 while (i > 0) {
1058 } 1086 u += u;
1087 k++;
1088 if (k >= MALLOC_BITS) {
1089 lp++;
1090 u = 1;
1091 k = 0;
1092 }
1093#ifdef MALLOC_EXTRA_SANITY
1094 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
1095 wrterror("chunk overflow\n");
1096 errno = EFAULT;
1097 return (NULL);
1098 }
1099#endif /* MALLOC_EXTRA_SANITY */
1100 if (*lp & u)
1101 i--;
1102 }
1103 }
1104 *lp ^= u;
1059 1105
1060 /* Adjust to the real offset of that chunk */ 1106 /* If there are no more free, remove from free-list */
1061 k += (lp-bp->bits)*MALLOC_BITS; 1107 if (!--bp->free) {
1062 k <<= bp->shift; 1108 page_dir[j] = bp->next;
1109 bp->next = NULL;
1110 }
1111 /* Adjust to the real offset of that chunk */
1112 k += (lp - bp->bits) * MALLOC_BITS;
1113 k <<= bp->shift;
1063 1114
1064 if (malloc_junk && bp->size != 0) 1115 if (malloc_junk && bp->size != 0)
1065 memset((char *)bp->page + k, SOME_JUNK, bp->size); 1116 memset((char *) bp->page + k, SOME_JUNK, bp->size);
1066 1117
1067 return ((u_char *)bp->page + k); 1118 return ((u_char *) bp->page + k);
1068} 1119}
1069 1120
1070/* 1121/*
@@ -1077,190 +1128,179 @@ malloc_bytes(size_t size)
1077/* 1128/*
1078 * Allocate a piece of memory 1129 * Allocate a piece of memory
1079 */ 1130 */
1080static void * 1131static void *
1081imalloc(size_t size) 1132imalloc(size_t size)
1082{ 1133{
1083 void *result; 1134 void *result;
1084 int ptralloc = 0; 1135 int ptralloc = 0;
1085 1136
1086 if (!malloc_started) 1137 if (!malloc_started)
1087 malloc_init(); 1138 malloc_init();
1088 1139
1089 if (suicide) 1140 if (suicide)
1090 abort(); 1141 abort();
1091 1142
1092 if (malloc_ptrguard && size == PTR_SIZE) { 1143 if (malloc_ptrguard && size == PTR_SIZE) {
1093 ptralloc = 1; 1144 ptralloc = 1;
1094 size = malloc_pagesize; 1145 size = malloc_pagesize;
1095 } 1146 }
1096 1147 if ((size + malloc_pagesize) < size) { /* Check for overflow */
1097 if ((size + malloc_pagesize) < size) { /* Check for overflow */ 1148 result = NULL;
1098 result = NULL; 1149 errno = ENOMEM;
1099 errno = ENOMEM; 1150 } else if (size <= malloc_maxsize)
1100 } 1151 result = malloc_bytes(size);
1101 else if (size <= malloc_maxsize) 1152 else
1102 result = malloc_bytes(size); 1153 result = malloc_pages(size);
1103 else 1154
1104 result = malloc_pages(size); 1155 if (malloc_abort == 1 && result == NULL)
1105 1156 wrterror("allocation failed\n");
1106 if (malloc_abort == 1 && result == NULL) 1157
1107 wrterror("allocation failed\n"); 1158 if (malloc_zero && result != NULL)
1108 1159 memset(result, 0, size);
1109 if (malloc_zero && result != NULL) 1160
1110 memset(result, 0, size); 1161 if (result && ptralloc)
1111 1162 return ((char *) result + PTR_GAP);
1112 if (result && ptralloc) 1163 return (result);
1113 return ((char *)result + PTR_GAP);
1114 return (result);
1115} 1164}
1116 1165
1117/* 1166/*
1118 * Change the size of an allocation. 1167 * Change the size of an allocation.
1119 */ 1168 */
1120static void * 1169static void *
1121irealloc(void *ptr, size_t size) 1170irealloc(void *ptr, size_t size)
1122{ 1171{
1123 void *p; 1172 void *p;
1124 u_long osize, index, i; 1173 u_long osize, index, i;
1125 struct pginfo **mp; 1174 struct pginfo **mp;
1126 struct pginfo **pd; 1175 struct pginfo **pd;
1127 struct pdinfo *pi; 1176 struct pdinfo *pi;
1128 u_long pidx; 1177 u_long pidx;
1129 1178
1130 if (suicide) 1179 if (suicide)
1131 abort(); 1180 abort();
1132 1181
1133 if (!malloc_started) { 1182 if (!malloc_started) {
1134 wrtwarning("malloc() has never been called\n"); 1183 wrtwarning("malloc() has never been called\n");
1135 return (NULL); 1184 return (NULL);
1136 }
1137
1138 if (malloc_ptrguard && PTR_ALIGNED(ptr)) {
1139 if (size <= PTR_SIZE) {
1140 return (ptr);
1141 } else {
1142 p = imalloc(size);
1143 if (p)
1144 memcpy(p, ptr, PTR_SIZE);
1145 ifree(ptr);
1146 return (p);
1147 } 1185 }
1148 } 1186 if (malloc_ptrguard && PTR_ALIGNED(ptr)) {
1149 1187 if (size <= PTR_SIZE) {
1150 index = ptr2index(ptr); 1188 return (ptr);
1151 1189 } else {
1152 if (index < malloc_pageshift) { 1190 p = imalloc(size);
1153 wrtwarning("junk pointer, too low to make sense\n"); 1191 if (p)
1154 return (NULL); 1192 memcpy(p, ptr, PTR_SIZE);
1155 } 1193 ifree(ptr);
1156 1194 return (p);
1157 if (index > last_index) { 1195 }
1158 wrtwarning("junk pointer, too high to make sense\n");
1159 return (NULL);
1160 }
1161
1162 pidx = PI_IDX(index);
1163 pdir_lookup(index, &pi);
1164#ifdef MALLOC_EXTRA_SANITY
1165 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1166 wrterror("(ES): mapped pages not found in directory\n");
1167 errno = EFAULT;
1168 return (NULL);
1169 }
1170#endif /* MALLOC_EXTRA_SANITY */
1171 if (pi != last_dir) {
1172 prev_dir = last_dir;
1173 last_dir = pi;
1174 }
1175
1176 pd = pi->base;
1177 mp = &pd[PI_OFF(index)];
1178
1179 if (*mp == MALLOC_FIRST) { /* Page allocation */
1180
1181 /* Check the pointer */
1182 if ((u_long)ptr & malloc_pagemask) {
1183 wrtwarning("modified (page-) pointer\n");
1184 return (NULL);
1185 } 1196 }
1197 index = ptr2index(ptr);
1186 1198
1187 /* Find the size in bytes */ 1199 if (index < malloc_pageshift) {
1188 i = index; 1200 wrtwarning("junk pointer, too low to make sense\n");
1189 if (!PI_OFF(++i)) { 1201 return (NULL);
1190 pi = pi->next;
1191 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1192 pi = NULL;
1193 if (pi != NULL)
1194 pd = pi->base;
1195 } 1202 }
1196 for (osize = malloc_pagesize; 1203 if (index > last_index) {
1197 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) { 1204 wrtwarning("junk pointer, too high to make sense\n");
1198 osize += malloc_pagesize; 1205 return (NULL);
1199 if (!PI_OFF(++i)) {
1200 pi = pi->next;
1201 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1202 pi = NULL;
1203 if (pi != NULL)
1204 pd = pi->base;
1205 }
1206 } 1206 }
1207 1207 pidx = PI_IDX(index);
1208 if (!malloc_realloc && /* Unless we have to, */ 1208 pdir_lookup(index, &pi);
1209 size <= osize && /* .. or are too small, */ 1209#ifdef MALLOC_EXTRA_SANITY
1210 size > (osize - malloc_pagesize)) { /* .. or can free a page, */ 1210 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1211 if (malloc_junk) 1211 wrterror("(ES): mapped pages not found in directory\n");
1212 memset((char *)ptr + size, SOME_JUNK, osize-size); 1212 errno = EFAULT;
1213 return (ptr); /* ..don't do anything else. */ 1213 return (NULL);
1214 } 1214 }
1215 1215#endif /* MALLOC_EXTRA_SANITY */
1216 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */ 1216 if (pi != last_dir) {
1217 1217 prev_dir = last_dir;
1218 /* Check the pointer for sane values */ 1218 last_dir = pi;
1219 if ((u_long)ptr & ((1UL<<((*mp)->shift))-1)) {
1220 wrtwarning("modified (chunk-) pointer\n");
1221 return (NULL);
1222 } 1219 }
1220 pd = pi->base;
1221 mp = &pd[PI_OFF(index)];
1223 1222
1224 /* Find the chunk index in the page */ 1223 if (*mp == MALLOC_FIRST) { /* Page allocation */
1225 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
1226 1224
1227 /* Verify that it isn't a free chunk already */ 1225 /* Check the pointer */
1228 if ((*mp)->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) { 1226 if ((u_long) ptr & malloc_pagemask) {
1229 wrtwarning("chunk is already free\n"); 1227 wrtwarning("modified (page-) pointer\n");
1230 return (NULL); 1228 return (NULL);
1231 } 1229 }
1230 /* Find the size in bytes */
1231 i = index;
1232 if (!PI_OFF(++i)) {
1233 pi = pi->next;
1234 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1235 pi = NULL;
1236 if (pi != NULL)
1237 pd = pi->base;
1238 }
1239 for (osize = malloc_pagesize;
1240 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
1241 osize += malloc_pagesize;
1242 if (!PI_OFF(++i)) {
1243 pi = pi->next;
1244 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1245 pi = NULL;
1246 if (pi != NULL)
1247 pd = pi->base;
1248 }
1249 }
1232 1250
1233 osize = (*mp)->size; 1251 if (!malloc_realloc && /* Unless we have to, */
1252 size <= osize && /* .. or are too small, */
1253 size > (osize - malloc_pagesize)) { /* .. or can free a
1254 * page, */
1255 if (malloc_junk)
1256 memset((char *) ptr + size, SOME_JUNK, osize - size);
1257 return (ptr); /* ..don't do anything else. */
1258 }
1259 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
1234 1260
1235 if (!malloc_realloc && /* Unless we have to, */ 1261 /* Check the pointer for sane values */
1236 size <= osize && /* ..or are too small, */ 1262 if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) {
1237 (size > osize/2 || /* ..or could use a smaller size, */ 1263 wrtwarning("modified (chunk-) pointer\n");
1238 osize == malloc_minsize)) { /* ..(if there is one) */ 1264 return (NULL);
1239 if (malloc_junk) 1265 }
1240 memset((char *)ptr + size, SOME_JUNK, osize-size); 1266 /* Find the chunk index in the page */
1241 return (ptr); /* ..don't do anything else. */ 1267 i = ((u_long) ptr & malloc_pagemask) >> (*mp)->shift;
1242 }
1243 1268
1244 } else { 1269 /* Verify that it isn't a free chunk already */
1245 wrtwarning("irealloc: pointer to wrong page\n"); 1270 if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1246 return (NULL); 1271 wrtwarning("chunk is already free\n");
1247 } 1272 return (NULL);
1248 1273 }
1249 p = imalloc(size); 1274 osize = (*mp)->size;
1250 1275
1251 if (p != NULL) { 1276 if (!malloc_realloc && /* Unless we have to, */
1252 /* copy the lesser of the two sizes, and free the old one */ 1277 size <= osize && /* ..or are too small, */
1253 /* Don't move from/to 0 sized region !!! */ 1278 (size > osize / 2 || /* ..or could use a smaller
1254 if (osize != 0 && size != 0) { 1279 * size, */
1255 if (osize < size) 1280 osize == malloc_minsize)) { /* ..(if there is one) */
1256 memcpy(p, ptr, osize); 1281 if (malloc_junk)
1257 else 1282 memset((char *) ptr + size, SOME_JUNK, osize - size);
1258 memcpy(p, ptr, size); 1283 return (ptr); /* ..don't do anything else. */
1284 }
1285 } else {
1286 wrtwarning("irealloc: pointer to wrong page\n");
1287 return (NULL);
1259 } 1288 }
1260 ifree(ptr);
1261 }
1262 1289
1263 return (p); 1290 p = imalloc(size);
1291
1292 if (p != NULL) {
1293 /* copy the lesser of the two sizes, and free the old one */
1294 /* Don't move from/to 0 sized region !!! */
1295 if (osize != 0 && size != 0) {
1296 if (osize < size)
1297 memcpy(p, ptr, osize);
1298 else
1299 memcpy(p, ptr, size);
1300 }
1301 ifree(ptr);
1302 }
1303 return (p);
1264} 1304}
1265 1305
1266/* 1306/*
@@ -1268,295 +1308,298 @@ irealloc(void *ptr, size_t size)
1268 */ 1308 */
1269 1309
1270static __inline__ void 1310static __inline__ void
1271free_pages(void *ptr, u_long index, struct pginfo *info) 1311free_pages(void *ptr, u_long index, struct pginfo * info)
1272{ 1312{
1273 u_long i, l, cachesize = 0; 1313 u_long i, l, cachesize = 0;
1274 struct pginfo **pd; 1314 struct pginfo **pd;
1275 struct pdinfo *pi, *spi; 1315 struct pdinfo *pi, *spi;
1276 u_long pidx, lidx; 1316 u_long pidx, lidx;
1277 struct pgfree *pf, *pt=NULL; 1317 struct pgfree *pf, *pt = NULL;
1278 void *tail; 1318 void *tail;
1279 1319
1280 if (info == MALLOC_FREE) { 1320 if (info == MALLOC_FREE) {
1281 wrtwarning("page is already free\n"); 1321 wrtwarning("page is already free\n");
1282 return; 1322 return;
1283 } 1323 }
1284 1324 if (info != MALLOC_FIRST) {
1285 if (info != MALLOC_FIRST) { 1325 wrtwarning("free_pages: pointer to wrong page\n");
1286 wrtwarning("free_pages: pointer to wrong page\n"); 1326 return;
1287 return; 1327 }
1288 } 1328 if ((u_long) ptr & malloc_pagemask) {
1329 wrtwarning("modified (page-) pointer\n");
1330 return;
1331 }
1332 /* Count how many pages and mark them free at the same time */
1333 pidx = PI_IDX(index);
1334 pdir_lookup(index, &pi);
1335#ifdef MALLOC_EXTRA_SANITY
1336 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1337 wrterror("(ES): mapped pages not found in directory\n");
1338 errno = EFAULT;
1339 return;
1340 }
1341#endif /* MALLOC_EXTRA_SANITY */
1289 1342
1290 if ((u_long)ptr & malloc_pagemask) { 1343 spi = pi; /* Save page index for start of region. */
1291 wrtwarning("modified (page-) pointer\n");
1292 return;
1293 }
1294 1344
1295 /* Count how many pages and mark them free at the same time */ 1345 pd = pi->base;
1296 pidx = PI_IDX(index); 1346 pd[PI_OFF(index)] = MALLOC_FREE;
1297 pdir_lookup(index, &pi); 1347 i = 1;
1298#ifdef MALLOC_EXTRA_SANITY 1348 if (!PI_OFF(index + i)) {
1299 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1349 pi = pi->next;
1300 wrterror("(ES): mapped pages not found in directory\n"); 1350 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i))
1301 errno = EFAULT; 1351 pi = NULL;
1302 return; 1352 else
1303 } 1353 pd = pi->base;
1304#endif /* MALLOC_EXTRA_SANITY */ 1354 }
1305 1355 while (pi != NULL && pd[PI_OFF(index + i)] == MALLOC_FOLLOW) {
1306 spi = pi; /* Save page index for start of region. */ 1356 pd[PI_OFF(index + i)] = MALLOC_FREE;
1307 1357 i++;
1308 pd = pi->base; 1358 if (!PI_OFF(index + i)) {
1309 pd[PI_OFF(index)] = MALLOC_FREE; 1359 if ((pi = pi->next) == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i))
1310 i = 1; 1360 pi = NULL;
1311 if (!PI_OFF(index+i)) { 1361 else
1312 pi = pi->next; 1362 pd = pi->base;
1313 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i)) 1363 }
1314 pi = NULL;
1315 else
1316 pd = pi->base;
1317 }
1318 while (pi != NULL && pd[PI_OFF(index+i)] == MALLOC_FOLLOW) {
1319 pd[PI_OFF(index+i)] = MALLOC_FREE;
1320 i++;
1321 if (!PI_OFF(index+i)) {
1322 if ((pi=pi->next) == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1323 pi = NULL;
1324 else
1325 pd = pi->base;
1326 } 1364 }
1327 }
1328 1365
1329 l = i << malloc_pageshift; 1366 l = i << malloc_pageshift;
1330 1367
1331 if (malloc_junk) 1368 if (malloc_junk)
1332 memset(ptr, SOME_JUNK, l); 1369 memset(ptr, SOME_JUNK, l);
1333 1370
1334 malloc_used -= l; 1371 malloc_used -= l;
1335 malloc_guarded -= malloc_guard; 1372 malloc_guarded -= malloc_guard;
1336 if (malloc_guard) { 1373 if (malloc_guard) {
1337#ifdef MALLOC_EXTRA_SANITY 1374#ifdef MALLOC_EXTRA_SANITY
1338 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i)) { 1375 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) {
1339 wrterror("(ES): hole in mapped pages directory\n"); 1376 wrterror("(ES): hole in mapped pages directory\n");
1340 errno = EFAULT; 1377 errno = EFAULT;
1341 return; 1378 return;
1379 }
1380#endif /* MALLOC_EXTRA_SANITY */
1381 pd[PI_OFF(index + i)] = MALLOC_FREE;
1382 l += malloc_guard;
1342 } 1383 }
1343#endif /* MALLOC_EXTRA_SANITY */ 1384 tail = (char *) ptr + l;
1344 pd[PI_OFF(index+i)] = MALLOC_FREE;
1345 l += malloc_guard;
1346 }
1347 tail = (char *)ptr + l;
1348 1385
1349#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE)) 1386#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1350 if (malloc_hint) 1387 if (malloc_hint)
1351 madvise(ptr, l, MADV_FREE); 1388 madvise(ptr, l, MADV_FREE);
1352#endif 1389#endif
1353 1390
1354 if (malloc_freeprot) 1391 if (malloc_freeprot)
1355 mprotect(ptr, l, PROT_NONE); 1392 mprotect(ptr, l, PROT_NONE);
1356
1357 /* Add to free-list. */
1358 if (px == NULL)
1359 px = imalloc(sizeof *px); /* This cannot fail... */
1360 px->page = ptr;
1361 px->pdir = spi;
1362 px->size = l;
1363 1393
1364 if (free_list.next == NULL) { 1394 /* Add to free-list. */
1365 1395 if (px == NULL)
1366 /* Nothing on free list, put this at head. */ 1396 px = imalloc(sizeof *px); /* This cannot fail... */
1367 px->next = NULL; 1397 px->page = ptr;
1368 px->prev = &free_list; 1398 px->pdir = spi;
1369 free_list.next = px; 1399 px->size = l;
1370 pf = px;
1371 px = NULL;
1372
1373 } else {
1374
1375 /* Find the right spot, leave pf pointing to the modified entry. */
1376 1400
1377 /* Race ahead here, while calculating cache size. */ 1401 if (free_list.next == NULL) {
1378 for (pf = free_list.next;
1379 (pf->page + pf->size) < ptr && pf->next != NULL;
1380 pf = pf->next)
1381 cachesize += pf->size;
1382 1402
1383 /* Finish cache size calculation. */ 1403 /* Nothing on free list, put this at head. */
1384 pt = pf; 1404 px->next = NULL;
1385 while (pt) { 1405 px->prev = &free_list;
1386 cachesize += pt->size; 1406 free_list.next = px;
1387 pt = pt->next; 1407 pf = px;
1388 } 1408 px = NULL;
1389 1409
1390 if (pf->page > tail) {
1391 /* Insert before entry */
1392 px->next = pf;
1393 px->prev = pf->prev;
1394 pf->prev = px;
1395 px->prev->next = px;
1396 pf = px;
1397 px = NULL;
1398 } else if ((pf->page + pf->size) == ptr ) {
1399 /* Append to the previous entry. */
1400 cachesize -= pf->size;
1401 pf->size += l;
1402 if (pf->next != NULL && (pf->page + pf->size) == pf->next->page ) {
1403 /* And collapse the next too. */
1404 pt = pf->next;
1405 pf->size += pt->size;
1406 pf->next = pt->next;
1407 if (pf->next != NULL)
1408 pf->next->prev = pf;
1409 }
1410 } else if (pf->page == tail) {
1411 /* Prepend to entry. */
1412 cachesize -= pf->size;
1413 pf->size += l;
1414 pf->page = ptr;
1415 pf->pdir = spi;
1416 } else if (pf->next == NULL) {
1417 /* Append at tail of chain. */
1418 px->next = NULL;
1419 px->prev = pf;
1420 pf->next = px;
1421 pf = px;
1422 px = NULL;
1423 } else { 1410 } else {
1424 wrterror("freelist is destroyed\n");
1425 errno = EFAULT;
1426 return;
1427 }
1428 }
1429
1430 if (pf->pdir != last_dir) {
1431 prev_dir = last_dir;
1432 last_dir = pf->pdir;
1433 }
1434
1435 /* Return something to OS ? */
1436 if (pf->size > (malloc_cache - cachesize)) {
1437
1438 /*
1439 * Keep the cache intact. Notice that the '>' above guarantees that
1440 * the pf will always have at least one page afterwards.
1441 */
1442 if (munmap((char *)pf->page + (malloc_cache - cachesize),
1443 pf->size - (malloc_cache - cachesize)) != 0)
1444 goto not_return;
1445 tail = pf->page + pf->size;
1446 lidx = ptr2index(tail) - 1;
1447 pf->size = malloc_cache - cachesize;
1448
1449 index = ptr2index(pf->page + pf->size);
1450 1411
1451 pidx = PI_IDX(index); 1412 /*
1452 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx) 1413 * Find the right spot, leave pf pointing to the modified
1453 prev_dir = NULL; /* Will be wiped out below ! */ 1414 * entry.
1454 1415 */
1455 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next); 1416
1456 1417 /* Race ahead here, while calculating cache size. */
1457 spi = pi; 1418 for (pf = free_list.next;
1458 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) { 1419 (pf->page + pf->size) < ptr && pf->next != NULL;
1459 pd = pi->base; 1420 pf = pf->next)
1421 cachesize += pf->size;
1422
1423 /* Finish cache size calculation. */
1424 pt = pf;
1425 while (pt) {
1426 cachesize += pt->size;
1427 pt = pt->next;
1428 }
1460 1429
1461 for(i=index;i <= lidx;) { 1430 if (pf->page > tail) {
1462 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) { 1431 /* Insert before entry */
1463 pd[PI_OFF(i)] = MALLOC_NOT_MINE; 1432 px->next = pf;
1464#ifdef MALLOC_EXTRA_SANITY 1433 px->prev = pf->prev;
1465 if (!PD_OFF(pi->dirnum)) { 1434 pf->prev = px;
1466 wrterror("(ES): pages directory underflow\n"); 1435 px->prev->next = px;
1436 pf = px;
1437 px = NULL;
1438 } else if ((pf->page + pf->size) == ptr) {
1439 /* Append to the previous entry. */
1440 cachesize -= pf->size;
1441 pf->size += l;
1442 if (pf->next != NULL && (pf->page + pf->size) == pf->next->page) {
1443 /* And collapse the next too. */
1444 pt = pf->next;
1445 pf->size += pt->size;
1446 pf->next = pt->next;
1447 if (pf->next != NULL)
1448 pf->next->prev = pf;
1449 }
1450 } else if (pf->page == tail) {
1451 /* Prepend to entry. */
1452 cachesize -= pf->size;
1453 pf->size += l;
1454 pf->page = ptr;
1455 pf->pdir = spi;
1456 } else if (pf->next == NULL) {
1457 /* Append at tail of chain. */
1458 px->next = NULL;
1459 px->prev = pf;
1460 pf->next = px;
1461 pf = px;
1462 px = NULL;
1463 } else {
1464 wrterror("freelist is destroyed\n");
1467 errno = EFAULT; 1465 errno = EFAULT;
1468 return; 1466 return;
1469 }
1470#endif /* MALLOC_EXTRA_SANITY */
1471 pi->dirnum--;
1472 } 1467 }
1473#ifdef MALLOC_EXTRA_SANITY
1474 else
1475 wrtwarning("(ES): page already unmapped\n");
1476#endif /* MALLOC_EXTRA_SANITY */
1477 i++;
1478 if (!PI_OFF(i)) {
1479 /* If no page in that dir, free directory page. */
1480 if (!PD_OFF(pi->dirnum)) {
1481 /* Remove from list. */
1482 if (spi == pi) /* Update spi only if first. */
1483 spi = pi->prev;
1484 if (pi->prev != NULL)
1485 pi->prev->next = pi->next;
1486 if (pi->next != NULL)
1487 pi->next->prev = pi->prev;
1488 pi = pi->next;
1489 munmap(pd, malloc_pagesize);
1490 } else
1491 pi = pi->next;
1492 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(i))
1493 break;
1494 pd = pi->base;
1495 }
1496 }
1497 if (pi && !PD_OFF(pi->dirnum)) {
1498 /* Resulting page dir is now empty. */
1499 /* Remove from list. */
1500 if (spi == pi) /* Update spi only if first. */
1501 spi = pi->prev;
1502 if (pi->prev != NULL)
1503 pi->prev->next = pi->next;
1504 if (pi->next != NULL)
1505 pi->next->prev = pi->prev;
1506 pi = pi->next;
1507 munmap(pd, malloc_pagesize);
1508 }
1509 } 1468 }
1510 1469
1511 if (pi == NULL && malloc_brk == tail) { 1470 if (pf->pdir != last_dir) {
1512 /* Resize down the malloc upper boundary. */ 1471 prev_dir = last_dir;
1513 last_index = index - 1; 1472 last_dir = pf->pdir;
1514 malloc_brk = index2ptr(index);
1515 } 1473 }
1516 1474 /* Return something to OS ? */
1517 /* XXX: We could realloc/shrink the pagedir here I guess. */ 1475 if (pf->size > (malloc_cache - cachesize)) {
1518 if (pf->size == 0) { /* Remove from free-list as well. */ 1476
1519 if (px) 1477 /*
1520 ifree(px); 1478 * Keep the cache intact. Notice that the '>' above guarantees that
1521 if ((px = pf->prev) != &free_list) { 1479 * the pf will always have at least one page afterwards.
1522 if (pi == NULL && last_index == (index - 1)) { 1480 */
1523 if (spi == NULL) { 1481 if (munmap((char *) pf->page + (malloc_cache - cachesize),
1524 malloc_brk = NULL; 1482 pf->size - (malloc_cache - cachesize)) != 0)
1525 i = 11; 1483 goto not_return;
1526 } else { 1484 tail = pf->page + pf->size;
1527 pd = spi->base; 1485 lidx = ptr2index(tail) - 1;
1528 if (PD_IDX(spi->dirnum) < pidx) 1486 pf->size = malloc_cache - cachesize;
1529 index = ((PD_IDX(spi->dirnum) + 1) * pdi_mod) - 1; 1487
1530 for (pi=spi,i=index;pd[PI_OFF(i)]==MALLOC_NOT_MINE;i--) 1488 index = ptr2index(pf->page + pf->size);
1489
1490 pidx = PI_IDX(index);
1491 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
1492 prev_dir = NULL; /* Will be wiped out below ! */
1493
1494 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx; pi = pi->next);
1495
1496 spi = pi;
1497 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
1498 pd = pi->base;
1499
1500 for (i = index; i <= lidx;) {
1501 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
1502 pd[PI_OFF(i)] = MALLOC_NOT_MINE;
1531#ifdef MALLOC_EXTRA_SANITY 1503#ifdef MALLOC_EXTRA_SANITY
1532 if (!PI_OFF(i)) { /* Should never enter here. */ 1504 if (!PD_OFF(pi->dirnum)) {
1533 pi = pi->prev; 1505 wrterror("(ES): pages directory underflow\n");
1534 if (pi == NULL || i == 0) 1506 errno = EFAULT;
1535 break; 1507 return;
1536 pd = pi->base; 1508 }
1537 i = (PD_IDX(pi->dirnum) + 1) * pdi_mod; 1509#endif /* MALLOC_EXTRA_SANITY */
1538 } 1510 pi->dirnum--;
1539#else /* !MALLOC_EXTRA_SANITY */ 1511 }
1540 { } 1512#ifdef MALLOC_EXTRA_SANITY
1541#endif /* MALLOC_EXTRA_SANITY */ 1513 else
1542 malloc_brk = index2ptr(i + 1); 1514 wrtwarning("(ES): page already unmapped\n");
1543 } 1515#endif /* MALLOC_EXTRA_SANITY */
1544 last_index = i; 1516 i++;
1517 if (!PI_OFF(i)) {
1518 /*
1519 * If no page in that dir, free
1520 * directory page.
1521 */
1522 if (!PD_OFF(pi->dirnum)) {
1523 /* Remove from list. */
1524 if (spi == pi) /* Update spi only if
1525 * first. */
1526 spi = pi->prev;
1527 if (pi->prev != NULL)
1528 pi->prev->next = pi->next;
1529 if (pi->next != NULL)
1530 pi->next->prev = pi->prev;
1531 pi = pi->next;
1532 munmap(pd, malloc_pagesize);
1533 } else
1534 pi = pi->next;
1535 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(i))
1536 break;
1537 pd = pi->base;
1538 }
1539 }
1540 if (pi && !PD_OFF(pi->dirnum)) {
1541 /* Resulting page dir is now empty. */
1542 /* Remove from list. */
1543 if (spi == pi) /* Update spi only if first. */
1544 spi = pi->prev;
1545 if (pi->prev != NULL)
1546 pi->prev->next = pi->next;
1547 if (pi->next != NULL)
1548 pi->next->prev = pi->prev;
1549 pi = pi->next;
1550 munmap(pd, malloc_pagesize);
1551 }
1552 }
1553 if (pi == NULL && malloc_brk == tail) {
1554 /* Resize down the malloc upper boundary. */
1555 last_index = index - 1;
1556 malloc_brk = index2ptr(index);
1557 }
1558 /* XXX: We could realloc/shrink the pagedir here I guess. */
1559 if (pf->size == 0) { /* Remove from free-list as well. */
1560 if (px)
1561 ifree(px);
1562 if ((px = pf->prev) != &free_list) {
1563 if (pi == NULL && last_index == (index - 1)) {
1564 if (spi == NULL) {
1565 malloc_brk = NULL;
1566 i = 11;
1567 } else {
1568 pd = spi->base;
1569 if (PD_IDX(spi->dirnum) < pidx)
1570 index = ((PD_IDX(spi->dirnum) + 1) * pdi_mod) - 1;
1571 for (pi = spi, i = index; pd[PI_OFF(i)] == MALLOC_NOT_MINE; i--)
1572#ifdef MALLOC_EXTRA_SANITY
1573 if (!PI_OFF(i)) { /* Should never enter
1574 * here. */
1575 pi = pi->prev;
1576 if (pi == NULL || i == 0)
1577 break;
1578 pd = pi->base;
1579 i = (PD_IDX(pi->dirnum) + 1) * pdi_mod;
1580 }
1581#else /* !MALLOC_EXTRA_SANITY */
1582 {
1583 }
1584#endif /* MALLOC_EXTRA_SANITY */
1585 malloc_brk = index2ptr(i + 1);
1586 }
1587 last_index = i;
1588 }
1589 if ((px->next = pf->next) != NULL)
1590 px->next->prev = px;
1591 } else {
1592 if ((free_list.next = pf->next) != NULL)
1593 free_list.next->prev = &free_list;
1594 }
1595 px = pf;
1596 last_dir = prev_dir;
1597 prev_dir = NULL;
1545 } 1598 }
1546 if ((px->next = pf->next) != NULL)
1547 px->next->prev = px;
1548 } else {
1549 if ((free_list.next = pf->next) != NULL)
1550 free_list.next->prev = &free_list;
1551 }
1552 px = pf;
1553 last_dir = prev_dir;
1554 prev_dir = NULL;
1555 } 1599 }
1556 }
1557not_return: 1600not_return:
1558 if (pt != NULL) 1601 if (pt != NULL)
1559 ifree(pt); 1602 ifree(pt);
1560} 1603}
1561 1604
1562/* 1605/*
@@ -1565,159 +1608,150 @@ not_return:
1565 1608
1566/* ARGSUSED */ 1609/* ARGSUSED */
1567static __inline__ void 1610static __inline__ void
1568free_bytes(void *ptr, int index, struct pginfo *info) 1611free_bytes(void *ptr, int index, struct pginfo * info)
1569{ 1612{
1570 int i; 1613 int i;
1571 struct pginfo **mp; 1614 struct pginfo **mp;
1572 struct pginfo **pd; 1615 struct pginfo **pd;
1573 struct pdinfo *pi; 1616 struct pdinfo *pi;
1574 u_long pidx; 1617 u_long pidx;
1575 void *vp; 1618 void *vp;
1576 1619
1577 /* Find the chunk number on the page */ 1620 /* Find the chunk number on the page */
1578 i = ((u_long)ptr & malloc_pagemask) >> info->shift; 1621 i = ((u_long) ptr & malloc_pagemask) >> info->shift;
1579 1622
1580 if ((u_long)ptr & ((1UL<<(info->shift))-1)) { 1623 if ((u_long) ptr & ((1UL << (info->shift)) - 1)) {
1581 wrtwarning("modified (chunk-) pointer\n"); 1624 wrtwarning("modified (chunk-) pointer\n");
1582 return; 1625 return;
1583 } 1626 }
1584 1627 if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1585 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) { 1628 wrtwarning("chunk is already free\n");
1586 wrtwarning("chunk is already free\n"); 1629 return;
1587 return; 1630 }
1588 } 1631 if (malloc_junk && info->size != 0)
1589 1632 memset(ptr, SOME_JUNK, info->size);
1590 if (malloc_junk && info->size != 0)
1591 memset(ptr, SOME_JUNK, info->size);
1592
1593 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1594 info->free++;
1595 1633
1596 if (info->size != 0) 1634 info->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
1597 mp = page_dir + info->shift; 1635 info->free++;
1598 else
1599 mp = page_dir;
1600 1636
1601 if (info->free == 1) { 1637 if (info->size != 0)
1638 mp = page_dir + info->shift;
1639 else
1640 mp = page_dir;
1602 1641
1603 /* Page became non-full */ 1642 if (info->free == 1) {
1604 1643
1605 /* Insert in address order */ 1644 /* Page became non-full */
1606 while (*mp != NULL && (*mp)->next != NULL &&
1607 (*mp)->next->page < info->page)
1608 mp = &(*mp)->next;
1609 info->next = *mp;
1610 *mp = info;
1611 return;
1612 }
1613 1645
1614 if (info->free != info->total) 1646 /* Insert in address order */
1615 return; 1647 while (*mp != NULL && (*mp)->next != NULL &&
1648 (*mp)->next->page < info->page)
1649 mp = &(*mp)->next;
1650 info->next = *mp;
1651 *mp = info;
1652 return;
1653 }
1654 if (info->free != info->total)
1655 return;
1616 1656
1617 /* Find & remove this page in the queue */ 1657 /* Find & remove this page in the queue */
1618 while (*mp != info) { 1658 while (*mp != info) {
1619 mp = &((*mp)->next); 1659 mp = &((*mp)->next);
1620#ifdef MALLOC_EXTRA_SANITY 1660#ifdef MALLOC_EXTRA_SANITY
1621 if (!*mp) { 1661 if (!*mp) {
1622 wrterror("(ES): Not on queue\n"); 1662 wrterror("(ES): Not on queue\n");
1623 errno = EFAULT; 1663 errno = EFAULT;
1624 return; 1664 return;
1665 }
1666#endif /* MALLOC_EXTRA_SANITY */
1625 } 1667 }
1626#endif /* MALLOC_EXTRA_SANITY */ 1668 *mp = info->next;
1627 }
1628 *mp = info->next;
1629 1669
1630 /* Free the page & the info structure if need be */ 1670 /* Free the page & the info structure if need be */
1631 pidx = PI_IDX(ptr2index(info->page)); 1671 pidx = PI_IDX(ptr2index(info->page));
1632 pdir_lookup(ptr2index(info->page), &pi); 1672 pdir_lookup(ptr2index(info->page), &pi);
1633#ifdef MALLOC_EXTRA_SANITY 1673#ifdef MALLOC_EXTRA_SANITY
1634 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1674 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1635 wrterror("(ES): mapped pages not found in directory\n"); 1675 wrterror("(ES): mapped pages not found in directory\n");
1636 errno = EFAULT; 1676 errno = EFAULT;
1637 return; 1677 return;
1638 } 1678 }
1639#endif /* MALLOC_EXTRA_SANITY */ 1679#endif /* MALLOC_EXTRA_SANITY */
1640 if (pi != last_dir) { 1680 if (pi != last_dir) {
1641 prev_dir = last_dir; 1681 prev_dir = last_dir;
1642 last_dir = pi; 1682 last_dir = pi;
1643 } 1683 }
1644 1684 pd = pi->base;
1645 pd = pi->base; 1685 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
1646 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST; 1686
1647 1687 /* If the page was mprotected, unprotect it before releasing it */
1648 /* If the page was mprotected, unprotect it before releasing it */ 1688 if (info->size == 0) {
1649 if (info->size == 0) { 1689 mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE);
1650 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE); 1690 /* Do we have to care if mprotect succeeds here ? */
1651 /* Do we have to care if mprotect succeeds here ? */ 1691 }
1652 } 1692 vp = info->page; /* Order is important ! */
1653 1693 if (vp != (void *) info)
1654 vp = info->page; /* Order is important ! */ 1694 ifree(info);
1655 if(vp != (void*)info) 1695 ifree(vp);
1656 ifree(info);
1657 ifree(vp);
1658} 1696}
1659 1697
1660static void 1698static void
1661ifree(void *ptr) 1699ifree(void *ptr)
1662{ 1700{
1663 struct pginfo *info; 1701 struct pginfo *info;
1664 struct pginfo **pd; 1702 struct pginfo **pd;
1665 struct pdinfo *pi; 1703 struct pdinfo *pi;
1666 u_long pidx; 1704 u_long pidx;
1667 u_long index; 1705 u_long index;
1668 1706
1669 /* This is legal */ 1707 /* This is legal */
1670 if (ptr == NULL) 1708 if (ptr == NULL)
1671 return; 1709 return;
1672 1710
1673 if (!malloc_started) { 1711 if (!malloc_started) {
1674 wrtwarning("malloc() has never been called\n"); 1712 wrtwarning("malloc() has never been called\n");
1675 return; 1713 return;
1676 } 1714 }
1677 1715 /* If we're already sinking, don't make matters any worse. */
1678 /* If we're already sinking, don't make matters any worse. */ 1716 if (suicide)
1679 if (suicide) 1717 return;
1680 return;
1681
1682 if (malloc_ptrguard && PTR_ALIGNED(ptr))
1683 ptr = (char *)ptr - PTR_GAP;
1684 1718
1685 index = ptr2index(ptr); 1719 if (malloc_ptrguard && PTR_ALIGNED(ptr))
1720 ptr = (char *) ptr - PTR_GAP;
1686 1721
1687 if (index < malloc_pageshift) { 1722 index = ptr2index(ptr);
1688 warnx("(%p)", ptr);
1689 wrtwarning("ifree: junk pointer, too low to make sense\n");
1690 return;
1691 }
1692
1693 if (index > last_index) {
1694 warnx("(%p)", ptr);
1695 wrtwarning("ifree: junk pointer, too high to make sense\n");
1696 return;
1697 }
1698 1723
1699 pidx = PI_IDX(index); 1724 if (index < malloc_pageshift) {
1700 pdir_lookup(index, &pi); 1725 warnx("(%p)", ptr);
1726 wrtwarning("ifree: junk pointer, too low to make sense\n");
1727 return;
1728 }
1729 if (index > last_index) {
1730 warnx("(%p)", ptr);
1731 wrtwarning("ifree: junk pointer, too high to make sense\n");
1732 return;
1733 }
1734 pidx = PI_IDX(index);
1735 pdir_lookup(index, &pi);
1701#ifdef MALLOC_EXTRA_SANITY 1736#ifdef MALLOC_EXTRA_SANITY
1702 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) { 1737 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1703 wrterror("(ES): mapped pages not found in directory\n"); 1738 wrterror("(ES): mapped pages not found in directory\n");
1704 errno = EFAULT; 1739 errno = EFAULT;
1740 return;
1741 }
1742#endif /* MALLOC_EXTRA_SANITY */
1743 if (pi != last_dir) {
1744 prev_dir = last_dir;
1745 last_dir = pi;
1746 }
1747 pd = pi->base;
1748 info = pd[PI_OFF(index)];
1749
1750 if (info < MALLOC_MAGIC)
1751 free_pages(ptr, index, info);
1752 else
1753 free_bytes(ptr, index, info);
1705 return; 1754 return;
1706 }
1707#endif /* MALLOC_EXTRA_SANITY */
1708 if (pi != last_dir) {
1709 prev_dir = last_dir;
1710 last_dir = pi;
1711 }
1712
1713 pd = pi->base;
1714 info = pd[PI_OFF(index)];
1715
1716 if (info < MALLOC_MAGIC)
1717 free_pages(ptr, index, info);
1718 else
1719 free_bytes(ptr, index, info);
1720 return;
1721} 1755}
1722 1756
1723/* 1757/*
@@ -1728,80 +1762,80 @@ ifree(void *ptr)
1728static void 1762static void
1729malloc_recurse(void) 1763malloc_recurse(void)
1730{ 1764{
1731 static int noprint; 1765 static int noprint;
1732 1766
1733 if (noprint == 0) { 1767 if (noprint == 0) {
1734 noprint = 1; 1768 noprint = 1;
1735 wrtwarning("recursive call\n"); 1769 wrtwarning("recursive call\n");
1736 } 1770 }
1737 malloc_active--; 1771 malloc_active--;
1738 _MALLOC_UNLOCK(); 1772 _MALLOC_UNLOCK();
1739 errno = EDEADLK; 1773 errno = EDEADLK;
1740} 1774}
1741 1775
1742/* 1776/*
1743 * These are the public exported interface routines. 1777 * These are the public exported interface routines.
1744 */ 1778 */
1745void * 1779void *
1746malloc(size_t size) 1780malloc(size_t size)
1747{ 1781{
1748 void *r; 1782 void *r;
1749 1783
1750 _MALLOC_LOCK(); 1784 _MALLOC_LOCK();
1751 malloc_func = " in malloc():"; 1785 malloc_func = " in malloc():";
1752 if (malloc_active++) { 1786 if (malloc_active++) {
1753 malloc_recurse(); 1787 malloc_recurse();
1754 return (NULL); 1788 return (NULL);
1755 } 1789 }
1756 r = imalloc(size); 1790 r = imalloc(size);
1757 UTRACE(0, size, r); 1791 UTRACE(0, size, r);
1758 malloc_active--; 1792 malloc_active--;
1759 _MALLOC_UNLOCK(); 1793 _MALLOC_UNLOCK();
1760 if (malloc_xmalloc && r == NULL) { 1794 if (malloc_xmalloc && r == NULL) {
1761 wrterror("out of memory\n"); 1795 wrterror("out of memory\n");
1762 errno = ENOMEM; 1796 errno = ENOMEM;
1763 } 1797 }
1764 return (r); 1798 return (r);
1765} 1799}
1766 1800
1767void 1801void
1768free(void *ptr) 1802free(void *ptr)
1769{ 1803{
1770 _MALLOC_LOCK(); 1804 _MALLOC_LOCK();
1771 malloc_func = " in free():"; 1805 malloc_func = " in free():";
1772 if (malloc_active++) { 1806 if (malloc_active++) {
1773 malloc_recurse(); 1807 malloc_recurse();
1808 return;
1809 }
1810 ifree(ptr);
1811 UTRACE(ptr, 0, 0);
1812 malloc_active--;
1813 _MALLOC_UNLOCK();
1774 return; 1814 return;
1775 }
1776 ifree(ptr);
1777 UTRACE(ptr, 0, 0);
1778 malloc_active--;
1779 _MALLOC_UNLOCK();
1780 return;
1781} 1815}
1782 1816
1783void * 1817void *
1784realloc(void *ptr, size_t size) 1818realloc(void *ptr, size_t size)
1785{ 1819{
1786 void *r; 1820 void *r;
1787 1821
1788 _MALLOC_LOCK(); 1822 _MALLOC_LOCK();
1789 malloc_func = " in realloc():"; 1823 malloc_func = " in realloc():";
1790 if (malloc_active++) { 1824 if (malloc_active++) {
1791 malloc_recurse(); 1825 malloc_recurse();
1792 return (NULL); 1826 return (NULL);
1793 } 1827 }
1794 if (ptr == NULL) { 1828 if (ptr == NULL) {
1795 r = imalloc(size); 1829 r = imalloc(size);
1796 } else { 1830 } else {
1797 r = irealloc(ptr, size); 1831 r = irealloc(ptr, size);
1798 } 1832 }
1799 UTRACE(ptr, size, r); 1833 UTRACE(ptr, size, r);
1800 malloc_active--; 1834 malloc_active--;
1801 _MALLOC_UNLOCK(); 1835 _MALLOC_UNLOCK();
1802 if (malloc_xmalloc && r == NULL) { 1836 if (malloc_xmalloc && r == NULL) {
1803 wrterror("out of memory\n"); 1837 wrterror("out of memory\n");
1804 errno = ENOMEM; 1838 errno = ENOMEM;
1805 } 1839 }
1806 return (r); 1840 return (r);
1807} 1841}