diff options
| author | tholo <> | 1996-09-26 04:19:42 +0000 |
|---|---|---|
| committer | tholo <> | 1996-09-26 04:19:42 +0000 |
| commit | 40954213683da2af94f45d9b0f35806b54e5e306 (patch) | |
| tree | 4d52bb67398acd4227bd70258a69403ba2acf910 /src/lib/libc/stdlib/malloc.c | |
| parent | 7bfb6e73ddb58269b8ec906a008d5999e1b70abf (diff) | |
| download | openbsd-40954213683da2af94f45d9b0f35806b54e5e306.tar.gz openbsd-40954213683da2af94f45d9b0f35806b54e5e306.tar.bz2 openbsd-40954213683da2af94f45d9b0f35806b54e5e306.zip | |
Latest changes from FreeBSD
Diffstat (limited to 'src/lib/libc/stdlib/malloc.c')
| -rw-r--r-- | src/lib/libc/stdlib/malloc.c | 491 |
1 files changed, 271 insertions, 220 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index bff70c7b54..a6f60b3fe3 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c | |||
| @@ -8,12 +8,15 @@ | |||
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #if defined(LIBC_SCCS) && !defined(lint) | 10 | #if defined(LIBC_SCCS) && !defined(lint) |
| 11 | static char rcsid[] = "$OpenBSD: malloc.c,v 1.13 1996/09/19 20:38:48 tholo Exp $"; | 11 | static char rcsid[] = "$OpenBSD: malloc.c,v 1.14 1996/09/26 04:19:42 tholo Exp $"; |
| 12 | #endif /* LIBC_SCCS and not lint */ | 12 | #endif /* LIBC_SCCS and not lint */ |
| 13 | 13 | ||
| 14 | /* | 14 | /* |
| 15 | * Defining EXTRA_SANITY will enable some checks which are related | 15 | * Defining EXTRA_SANITY will enable extra checks which are related |
| 16 | * to internal conditions and consistency in malloc.c | 16 | * to internal conditions and consistency in malloc.c. This has a |
| 17 | * noticeable runtime performance hit, and generally will not do you | ||
| 18 | * any good unless you fiddle with the internals of malloc or want | ||
| 19 | * to catch random pointer corruption as early as possible. | ||
| 17 | */ | 20 | */ |
| 18 | #undef EXTRA_SANITY | 21 | #undef EXTRA_SANITY |
| 19 | 22 | ||
| @@ -29,23 +32,23 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.13 1996/09/19 20:38:48 tholo Exp $ | |||
| 29 | #endif | 32 | #endif |
| 30 | 33 | ||
| 31 | /* | 34 | /* |
| 32 | * What to use for Junk | 35 | * What to use for Junk. This is the byte value we use to fill with |
| 36 | * when the 'J' option is enabled. | ||
| 33 | */ | 37 | */ |
| 34 | #define SOME_JUNK 0xd0 /* as in "Duh" :-) */ | 38 | #define SOME_JUNK 0xd0 /* as in "Duh" :-) */ |
| 35 | 39 | ||
| 40 | /* | ||
| 41 | * No user serviceable parts behind this point. | ||
| 42 | */ | ||
| 43 | |||
| 36 | #include <stdio.h> | 44 | #include <stdio.h> |
| 37 | #include <stdlib.h> | 45 | #include <stdlib.h> |
| 46 | #include <string.h> | ||
| 38 | #include <unistd.h> | 47 | #include <unistd.h> |
| 39 | #include <memory.h> | ||
| 40 | #include <errno.h> | 48 | #include <errno.h> |
| 41 | #include <err.h> | ||
| 42 | #include <sys/types.h> | 49 | #include <sys/types.h> |
| 43 | #include <sys/param.h> | 50 | #include <sys/param.h> |
| 44 | #include <sys/mman.h> | 51 | #include <sys/mman.h> |
| 45 | #ifdef _THREAD_SAFE | ||
| 46 | #include <pthread.h> | ||
| 47 | #include "pthread_private.h" | ||
| 48 | #endif | ||
| 49 | 52 | ||
| 50 | /* | 53 | /* |
| 51 | * If these weren't defined here, they would be calculated on the fly, | 54 | * If these weren't defined here, they would be calculated on the fly, |
| @@ -108,14 +111,14 @@ struct pgfree { | |||
| 108 | * We might as well use them. There are C-language backups, but | 111 | * We might as well use them. There are C-language backups, but |
| 109 | * they are considerably slower. | 112 | * they are considerably slower. |
| 110 | */ | 113 | */ |
| 111 | #ifdef __i386__ | 114 | #if defined(__i386__) && defined(__GNUC__) |
| 112 | #define ffs _ffs | 115 | #define ffs _ffs |
| 113 | static __inline int | 116 | static __inline int |
| 114 | _ffs(input) | 117 | _ffs(input) |
| 115 | unsigned input; | 118 | unsigned input; |
| 116 | { | 119 | { |
| 117 | int result; | 120 | int result; |
| 118 | __asm("bsfl %1,%0" : "=r" (result) : "r" (input)); | 121 | __asm("bsfl %1, %0" : "=r" (result) : "r" (input)); |
| 119 | return result+1; | 122 | return result+1; |
| 120 | } | 123 | } |
| 121 | 124 | ||
| @@ -125,7 +128,7 @@ _fls(input) | |||
| 125 | unsigned input; | 128 | unsigned input; |
| 126 | { | 129 | { |
| 127 | int result; | 130 | int result; |
| 128 | __asm("bsrl %1,%0" : "=r" (result) : "r" (input)); | 131 | __asm("bsrl %1, %0" : "=r" (result) : "r" (input)); |
| 129 | return result+1; | 132 | return result+1; |
| 130 | } | 133 | } |
| 131 | 134 | ||
| @@ -135,7 +138,7 @@ _set_bit(pi, bit) | |||
| 135 | struct pginfo *pi; | 138 | struct pginfo *pi; |
| 136 | int bit; | 139 | int bit; |
| 137 | { | 140 | { |
| 138 | __asm("btsl %0,(%1)" : | 141 | __asm("btsl %0, (%1)" : |
| 139 | : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); | 142 | : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); |
| 140 | } | 143 | } |
| 141 | 144 | ||
| @@ -145,11 +148,11 @@ _clr_bit(pi, bit) | |||
| 145 | struct pginfo *pi; | 148 | struct pginfo *pi; |
| 146 | int bit; | 149 | int bit; |
| 147 | { | 150 | { |
| 148 | __asm("btcl %0,(%1)" : | 151 | __asm("btcl %0, (%1)" : |
| 149 | : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); | 152 | : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); |
| 150 | } | 153 | } |
| 151 | 154 | ||
| 152 | #endif /* __i386__ */ | 155 | #endif /* __i386__ && __GNUC__ */ |
| 153 | 156 | ||
| 154 | /* | 157 | /* |
| 155 | * Set to one when malloc_init has been called | 158 | * Set to one when malloc_init has been called |
| @@ -165,17 +168,13 @@ static unsigned initialized; | |||
| 165 | static unsigned malloc_pagesize; | 168 | static unsigned malloc_pagesize; |
| 166 | #endif /* malloc_pagesize */ | 169 | #endif /* malloc_pagesize */ |
| 167 | 170 | ||
| 168 | /* | 171 | /* A mask for the offset inside a page. */ |
| 169 | * A mask for the offset inside a page. | ||
| 170 | */ | ||
| 171 | #define malloc_pagemask ((malloc_pagesize)-1) | 172 | #define malloc_pagemask ((malloc_pagesize)-1) |
| 172 | 173 | ||
| 173 | #define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask))) | 174 | #define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask))) |
| 174 | #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo) | 175 | #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo) |
| 175 | 176 | ||
| 176 | /* | 177 | /* malloc_pagesize == 1 << malloc_pageshift */ |
| 177 | * malloc_pagesize == 1 << malloc_pageshift | ||
| 178 | */ | ||
| 179 | #ifndef malloc_pageshift | 178 | #ifndef malloc_pageshift |
| 180 | static unsigned malloc_pageshift; | 179 | static unsigned malloc_pageshift; |
| 181 | #endif /* malloc_pageshift */ | 180 | #endif /* malloc_pageshift */ |
| @@ -197,85 +196,78 @@ static unsigned malloc_minsize; | |||
| 197 | static unsigned malloc_maxsize; | 196 | static unsigned malloc_maxsize; |
| 198 | #endif /* malloc_maxsize */ | 197 | #endif /* malloc_maxsize */ |
| 199 | 198 | ||
| 200 | /* | 199 | /* The minimum size (in pages) of the free page cache. */ |
| 201 | * The minimum size (in bytes) of the free page cache. | 200 | static unsigned malloc_cache = 16; |
| 202 | */ | ||
| 203 | #ifndef malloc_cache | ||
| 204 | static unsigned malloc_cache; | ||
| 205 | #endif /* malloc_cache */ | ||
| 206 | 201 | ||
| 207 | /* | 202 | /* The offset from pagenumber to index into the page directory */ |
| 208 | * The offset from pagenumber to index into the page directory | ||
| 209 | */ | ||
| 210 | static u_long malloc_origo; | 203 | static u_long malloc_origo; |
| 211 | 204 | ||
| 212 | /* | 205 | /* The last index in the page directory we care about */ |
| 213 | * The last index in the page directory we care about | ||
| 214 | */ | ||
| 215 | static u_long last_index; | 206 | static u_long last_index; |
| 216 | 207 | ||
| 217 | /* | 208 | /* Pointer to page directory. Allocated "as if with" malloc */ |
| 218 | * Pointer to page directory. | ||
| 219 | * Allocated "as if with" malloc | ||
| 220 | */ | ||
| 221 | static struct pginfo **page_dir; | 209 | static struct pginfo **page_dir; |
| 222 | 210 | ||
| 223 | /* | 211 | /* How many slots in the page directory */ |
| 224 | * How many slots in the page directory | ||
| 225 | */ | ||
| 226 | static unsigned malloc_ninfo; | 212 | static unsigned malloc_ninfo; |
| 227 | 213 | ||
| 228 | /* | 214 | /* Free pages line up here */ |
| 229 | * Free pages line up here | ||
| 230 | */ | ||
| 231 | static struct pgfree free_list; | 215 | static struct pgfree free_list; |
| 232 | 216 | ||
| 233 | /* | 217 | /* Abort(), user doesn't handle problems. */ |
| 234 | * Abort() if we fail to get VM ? | ||
| 235 | */ | ||
| 236 | static int malloc_abort; | 218 | static int malloc_abort; |
| 237 | 219 | ||
| 238 | /* | 220 | /* Are we trying to die ? */ |
| 239 | * Are we trying to die ? | ||
| 240 | */ | ||
| 241 | static int suicide; | 221 | static int suicide; |
| 242 | 222 | ||
| 243 | #ifdef MALLOC_STATS | 223 | #ifdef MALLOC_STATS |
| 244 | /* | 224 | /* dump statistics */ |
| 245 | * dump statistics | ||
| 246 | */ | ||
| 247 | static int malloc_stats; | 225 | static int malloc_stats; |
| 248 | #endif /* MALLOC_STATS */ | 226 | #endif /* MALLOC_STATS */ |
| 249 | 227 | ||
| 250 | /* | 228 | /* always realloc ? */ |
| 251 | * always realloc ? | ||
| 252 | */ | ||
| 253 | static int malloc_realloc; | 229 | static int malloc_realloc; |
| 254 | 230 | ||
| 255 | /* | 231 | #ifdef __FreeBSD__ |
| 256 | * zero fill ? | 232 | /* pass the kernel a hint on free pages ? */ |
| 257 | */ | 233 | static int malloc_hint; |
| 234 | #endif | ||
| 235 | |||
| 236 | /* zero fill ? */ | ||
| 258 | static int malloc_zero; | 237 | static int malloc_zero; |
| 259 | 238 | ||
| 260 | /* | 239 | /* junk fill ? */ |
| 261 | * junk fill ? | ||
| 262 | */ | ||
| 263 | static int malloc_junk; | 240 | static int malloc_junk; |
| 264 | 241 | ||
| 265 | /* | 242 | #ifdef __FreeBSD__ |
| 266 | * my last break. | 243 | /* utrace ? */ |
| 267 | */ | 244 | static int malloc_utrace; |
| 245 | |||
| 246 | struct ut { void *p; size_t s; void *r; }; | ||
| 247 | |||
| 248 | #define UTRACE(a, b, c) \ | ||
| 249 | if (malloc_utrace) \ | ||
| 250 | {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);} | ||
| 251 | #else /* !__FreeBSD__ */ | ||
| 252 | #define UTRACE(a,b,c) | ||
| 253 | #endif | ||
| 254 | |||
| 255 | /* my last break. */ | ||
| 268 | static void *malloc_brk; | 256 | static void *malloc_brk; |
| 269 | 257 | ||
| 270 | /* | 258 | /* one location cache for free-list holders */ |
| 271 | * one location cache for free-list holders | ||
| 272 | */ | ||
| 273 | static struct pgfree *px; | 259 | static struct pgfree *px; |
| 274 | 260 | ||
| 261 | /* compile-time options */ | ||
| 262 | char *malloc_options; | ||
| 263 | |||
| 275 | /* | 264 | /* |
| 276 | * Necessary function declarations | 265 | * Necessary function declarations |
| 277 | */ | 266 | */ |
| 278 | static int extend_pgdir(u_long index); | 267 | static int extend_pgdir(u_long index); |
| 268 | static void *imalloc(size_t size); | ||
| 269 | static void ifree(void *ptr); | ||
| 270 | static void *irealloc(void *ptr, size_t size); | ||
| 279 | 271 | ||
| 280 | #ifdef MALLOC_STATS | 272 | #ifdef MALLOC_STATS |
| 281 | void | 273 | void |
| @@ -290,60 +282,63 @@ malloc_dump(fd) | |||
| 290 | 282 | ||
| 291 | /* print out all the pages */ | 283 | /* print out all the pages */ |
| 292 | for(j=0;j<=last_index;j++) { | 284 | for(j=0;j<=last_index;j++) { |
| 293 | fprintf(fd,"%08lx %5d ",(j+malloc_origo) << malloc_pageshift,j); | 285 | fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j); |
| 294 | if (pd[j] == MALLOC_NOT_MINE) { | 286 | if (pd[j] == MALLOC_NOT_MINE) { |
| 295 | for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++) | 287 | for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++) |
| 296 | ; | 288 | ; |
| 297 | j--; | 289 | j--; |
| 298 | fprintf(fd,".. %5d not mine\n", j); | 290 | fprintf(fd, ".. %5d not mine\n", j); |
| 299 | } else if (pd[j] == MALLOC_FREE) { | 291 | } else if (pd[j] == MALLOC_FREE) { |
| 300 | for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++) | 292 | for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++) |
| 301 | ; | 293 | ; |
| 302 | j--; | 294 | j--; |
| 303 | fprintf(fd,".. %5d free\n", j); | 295 | fprintf(fd, ".. %5d free\n", j); |
| 304 | } else if (pd[j] == MALLOC_FIRST) { | 296 | } else if (pd[j] == MALLOC_FIRST) { |
| 305 | for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++) | 297 | for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++) |
| 306 | ; | 298 | ; |
| 307 | j--; | 299 | j--; |
| 308 | fprintf(fd,".. %5d in use\n", j); | 300 | fprintf(fd, ".. %5d in use\n", j); |
| 309 | } else if (pd[j] < MALLOC_MAGIC) { | 301 | } else if (pd[j] < MALLOC_MAGIC) { |
| 310 | fprintf(fd,"(%p)\n", pd[j]); | 302 | fprintf(fd, "(%p)\n", pd[j]); |
| 311 | } else { | 303 | } else { |
| 312 | fprintf(fd,"%p %d (of %d) x %d @ %p --> %p\n", | 304 | fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n", |
| 313 | pd[j],pd[j]->free, pd[j]->total, | 305 | pd[j], pd[j]->free, pd[j]->total, |
| 314 | pd[j]->size, pd[j]->page, pd[j]->next); | 306 | pd[j]->size, pd[j]->page, pd[j]->next); |
| 315 | } | 307 | } |
| 316 | } | 308 | } |
| 317 | 309 | ||
| 318 | for(pf=free_list.next; pf; pf=pf->next) { | 310 | for(pf=free_list.next; pf; pf=pf->next) { |
| 319 | fprintf(fd,"Free: @%p [%p...%p[ %ld ->%p <-%p\n", | 311 | fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n", |
| 320 | pf,pf->page,pf->end,pf->size,pf->prev,pf->next); | 312 | pf, pf->page, pf->end, pf->size, pf->prev, pf->next); |
| 321 | if (pf == pf->next) { | 313 | if (pf == pf->next) { |
| 322 | fprintf(fd,"Free_list loops.\n"); | 314 | + fprintf(fd, "Free_list loops.\n"); |
| 323 | break; | 315 | break; |
| 324 | } | 316 | } |
| 325 | } | 317 | } |
| 326 | 318 | ||
| 327 | /* print out various info */ | 319 | /* print out various info */ |
| 328 | fprintf(fd,"Minsize\t%d\n",malloc_minsize); | 320 | fprintf(fd, "Minsize\t%d\n", malloc_minsize); |
| 329 | fprintf(fd,"Maxsize\t%d\n",malloc_maxsize); | 321 | fprintf(fd, "Maxsize\t%d\n", malloc_maxsize); |
| 330 | fprintf(fd,"Pagesize\t%d\n",malloc_pagesize); | 322 | fprintf(fd, "Pagesize\t%d\n", malloc_pagesize); |
| 331 | fprintf(fd,"Pageshift\t%d\n",malloc_pageshift); | 323 | fprintf(fd, "Pageshift\t%d\n", malloc_pageshift); |
| 332 | fprintf(fd,"FirstPage\t%ld\n",malloc_origo); | 324 | fprintf(fd, "FirstPage\t%ld\n", malloc_origo); |
| 333 | fprintf(fd,"LastPage\t%ld %lx\n",last_index+malloc_pageshift, | 325 | fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift, |
| 334 | (last_index + malloc_pageshift) << malloc_pageshift); | 326 | (last_index + malloc_pageshift) << malloc_pageshift); |
| 335 | fprintf(fd,"Break\t%ld\n",(u_long)sbrk(0) >> malloc_pageshift); | 327 | fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift); |
| 336 | } | 328 | } |
| 337 | #endif /* MALLOC_STATS */ | 329 | #endif /* MALLOC_STATS */ |
| 338 | 330 | ||
| 331 | static char *malloc_func; | ||
| 332 | |||
| 339 | static void | 333 | static void |
| 340 | wrterror(p) | 334 | wrterror(p) |
| 341 | char *p; | 335 | char *p; |
| 342 | { | 336 | { |
| 343 | char *q = "Malloc error: "; | 337 | char *q = "Malloc error: "; |
| 344 | suicide = 1; | 338 | suicide = 1; |
| 345 | write(2,q,strlen(q)); | 339 | write(2, q, strlen(q)); |
| 346 | write(2,p,strlen(p)); | 340 | write(2, malloc_func, strlen(malloc_func)); |
| 341 | write(2, p, strlen(p)); | ||
| 347 | #ifdef MALLOC_STATS | 342 | #ifdef MALLOC_STATS |
| 348 | if (malloc_stats) | 343 | if (malloc_stats) |
| 349 | malloc_dump(stderr); | 344 | malloc_dump(stderr); |
| @@ -358,21 +353,22 @@ wrtwarning(p) | |||
| 358 | char *q = "Malloc warning: "; | 353 | char *q = "Malloc warning: "; |
| 359 | if (malloc_abort) | 354 | if (malloc_abort) |
| 360 | wrterror(p); | 355 | wrterror(p); |
| 361 | write(2,q,strlen(q)); | 356 | write(2, q, strlen(q)); |
| 362 | write(2,p,strlen(p)); | 357 | write(2, malloc_func, strlen(malloc_func)); |
| 358 | write(2, p, strlen(p)); | ||
| 363 | } | 359 | } |
| 364 | 360 | ||
| 365 | #ifdef EXTRA_SANITY | 361 | #ifdef EXTRA_SANITY |
| 366 | static void | 362 | static void |
| 367 | malloc_exit() | 363 | malloc_exit() |
| 368 | { | 364 | { |
| 369 | FILE *fd = fopen("malloc.out","a"); | 365 | FILE *fd = fopen("malloc.out", "a"); |
| 370 | char *q = "malloc() warning: Couldn't dump stats.\n"; | 366 | char *q = "malloc() warning: Couldn't dump stats.\n"; |
| 371 | if (fd) { | 367 | if (fd) { |
| 372 | malloc_dump(fd); | 368 | malloc_dump(fd); |
| 373 | fclose(fd); | 369 | fclose(fd); |
| 374 | } else | 370 | } else |
| 375 | write(2,q,strlen(q)); | 371 | write(2, q, strlen(q)); |
| 376 | } | 372 | } |
| 377 | #endif /* EXTRA_SANITY */ | 373 | #endif /* EXTRA_SANITY */ |
| 378 | 374 | ||
| @@ -384,14 +380,14 @@ static caddr_t | |||
| 384 | map_pages(pages) | 380 | map_pages(pages) |
| 385 | int pages; | 381 | int pages; |
| 386 | { | 382 | { |
| 387 | caddr_t result,tail; | 383 | caddr_t result, tail; |
| 388 | 384 | ||
| 389 | result = (caddr_t)pageround((u_long)sbrk(0)); | 385 | result = (caddr_t)pageround((u_long)sbrk(0)); |
| 390 | tail = result + (pages << malloc_pageshift); | 386 | tail = result + (pages << malloc_pageshift); |
| 391 | 387 | ||
| 392 | if (brk(tail)) { | 388 | if (brk(tail)) { |
| 393 | #ifdef EXTRA_SANITY | 389 | #ifdef EXTRA_SANITY |
| 394 | wrterror("(internal): map_pages fails\n"); | 390 | wrterror("(ES): map_pages fails\n"); |
| 395 | #endif /* EXTRA_SANITY */ | 391 | #endif /* EXTRA_SANITY */ |
| 396 | return 0; | 392 | return 0; |
| 397 | } | 393 | } |
| @@ -466,7 +462,7 @@ static int | |||
| 466 | extend_pgdir(index) | 462 | extend_pgdir(index) |
| 467 | u_long index; | 463 | u_long index; |
| 468 | { | 464 | { |
| 469 | struct pginfo **new,**old; | 465 | struct pginfo **new, **old; |
| 470 | int i, oldlen; | 466 | int i, oldlen; |
| 471 | 467 | ||
| 472 | /* Make it this many pages */ | 468 | /* Make it this many pages */ |
| @@ -520,35 +516,61 @@ extend_pgdir(index) | |||
| 520 | static void | 516 | static void |
| 521 | malloc_init () | 517 | malloc_init () |
| 522 | { | 518 | { |
| 523 | char *p; | 519 | char *p, b[64]; |
| 520 | int i, j; | ||
| 524 | 521 | ||
| 525 | #ifdef EXTRA_SANITY | 522 | #ifdef EXTRA_SANITY |
| 526 | malloc_junk = 1; | 523 | malloc_junk = 1; |
| 527 | #endif /* EXTRA_SANITY */ | 524 | #endif /* EXTRA_SANITY */ |
| 528 | 525 | ||
| 529 | if (issetugid() == 0) { | 526 | for (i = 0; i < 3; i++) { |
| 530 | for (p=getenv("MALLOC_OPTIONS"); p && *p; p++) { | 527 | if (i == 0) { |
| 528 | j = readlink("/etc/malloc.conf", b, sizeof b - 1); | ||
| 529 | if (j <= 0) | ||
| 530 | continue; | ||
| 531 | b[j] = '\0'; | ||
| 532 | p = b; | ||
| 533 | } else if (i == 1) { | ||
| 534 | p = getenv("MALLOC_OPTIONS"); | ||
| 535 | } else if (i == 2) { | ||
| 536 | p = malloc_options; | ||
| 537 | } | ||
| 538 | for (; p && *p; p++) { | ||
| 531 | switch (*p) { | 539 | switch (*p) { |
| 532 | case 'a': malloc_abort = 0; break; | 540 | case '>': malloc_cache <<= 1; break; |
| 533 | case 'A': malloc_abort = 1; break; | 541 | case '<': malloc_cache >>= 1; break; |
| 542 | case 'a': malloc_abort = 0; break; | ||
| 543 | case 'A': malloc_abort = 1; break; | ||
| 534 | #ifdef MALLOC_STATS | 544 | #ifdef MALLOC_STATS |
| 535 | case 'd': malloc_stats = 0; break; | 545 | case 'd': malloc_stats = 0; break; |
| 536 | case 'D': malloc_stats = 1; break; | 546 | case 'D': malloc_stats = 1; break; |
| 537 | #endif /* MALLOC_STATS */ | 547 | #endif /* MALLOC_STATS */ |
| 538 | case 'r': malloc_realloc = 0; break; | 548 | #ifdef __FreeBSD__ |
| 539 | case 'R': malloc_realloc = 1; break; | 549 | case 'h': malloc_hint = 0; break; |
| 540 | case 'j': malloc_junk = 0; break; | 550 | case 'H': malloc_hint = 1; break; |
| 541 | case 'J': malloc_junk = 1; break; | 551 | #endif /* __FreeBSD__ */ |
| 542 | case 'z': malloc_zero = 0; break; | 552 | case 'r': malloc_realloc = 0; break; |
| 543 | case 'Z': malloc_zero = 1; break; | 553 | case 'R': malloc_realloc = 1; break; |
| 544 | default: | 554 | case 'j': malloc_junk = 0; break; |
| 545 | wrtwarning("(Init): Unknown char in MALLOC_OPTIONS\n"); | 555 | case 'J': malloc_junk = 1; break; |
| 546 | p = 0; | 556 | #ifdef __FreeBSD__ |
| 547 | break; | 557 | case 'u': malloc_utrace = 0; break; |
| 558 | case 'U': malloc_utrace = 1; break; | ||
| 559 | #endif /* __FreeBSD__ */ | ||
| 560 | case 'z': malloc_zero = 0; break; | ||
| 561 | case 'Z': malloc_zero = 1; break; | ||
| 562 | default: | ||
| 563 | j = malloc_abort; | ||
| 564 | malloc_abort = 0; | ||
| 565 | wrtwarning("unknown char in MALLOC_OPTIONS\n"); | ||
| 566 | malloc_abort = j; | ||
| 567 | break; | ||
| 548 | } | 568 | } |
| 549 | } | 569 | } |
| 550 | } | 570 | } |
| 551 | 571 | ||
| 572 | UTRACE(0, 0, 0); | ||
| 573 | |||
| 552 | /* | 574 | /* |
| 553 | * We want junk in the entire allocation, and zero only in the part | 575 | * We want junk in the entire allocation, and zero only in the part |
| 554 | * the user asked for. | 576 | * the user asked for. |
| @@ -579,10 +601,6 @@ malloc_init () | |||
| 579 | } | 601 | } |
| 580 | #endif /* malloc_pageshift */ | 602 | #endif /* malloc_pageshift */ |
| 581 | 603 | ||
| 582 | #ifndef malloc_cache | ||
| 583 | malloc_cache = 100 << malloc_pageshift; | ||
| 584 | #endif /* malloc_cache */ | ||
| 585 | |||
| 586 | #ifndef malloc_minsize | 604 | #ifndef malloc_minsize |
| 587 | { | 605 | { |
| 588 | int i; | 606 | int i; |
| @@ -612,7 +630,7 @@ malloc_init () | |||
| 612 | page_dir = (struct pginfo **) mmap(0, malloc_pagesize, PROT_READ|PROT_WRITE, | 630 | page_dir = (struct pginfo **) mmap(0, malloc_pagesize, PROT_READ|PROT_WRITE, |
| 613 | MAP_ANON|MAP_PRIVATE, -1, (off_t)0); | 631 | MAP_ANON|MAP_PRIVATE, -1, (off_t)0); |
| 614 | if (page_dir == (struct pginfo **) -1) | 632 | if (page_dir == (struct pginfo **) -1) |
| 615 | wrterror("(Init) my first mmap failed. (check limits ?)\n"); | 633 | wrterror("mmap(2) failed, check limits.\n"); |
| 616 | 634 | ||
| 617 | /* | 635 | /* |
| 618 | * We need a maximum of malloc_pageshift buckets, steal these from the | 636 | * We need a maximum of malloc_pageshift buckets, steal these from the |
| @@ -630,7 +648,12 @@ malloc_init () | |||
| 630 | * This is a nice hack from Kaleb Keithly (kaleb@x.org). | 648 | * This is a nice hack from Kaleb Keithly (kaleb@x.org). |
| 631 | * We can sbrk(2) further back when we keep this on a low address. | 649 | * We can sbrk(2) further back when we keep this on a low address. |
| 632 | */ | 650 | */ |
| 633 | px = (struct pgfree *) malloc (sizeof *px); | 651 | px = (struct pgfree *) imalloc (sizeof *px); |
| 652 | |||
| 653 | if (!malloc_cache) | ||
| 654 | malloc_cache++; | ||
| 655 | |||
| 656 | malloc_cache <<= malloc_pageshift; | ||
| 634 | } | 657 | } |
| 635 | 658 | ||
| 636 | /* | 659 | /* |
| @@ -640,7 +663,7 @@ void * | |||
| 640 | malloc_pages(size) | 663 | malloc_pages(size) |
| 641 | size_t size; | 664 | size_t size; |
| 642 | { | 665 | { |
| 643 | void *p,*delay_free = 0; | 666 | void *p, *delay_free = 0; |
| 644 | int i; | 667 | int i; |
| 645 | struct pgfree *pf; | 668 | struct pgfree *pf; |
| 646 | u_long index; | 669 | u_long index; |
| @@ -705,14 +728,14 @@ malloc_pages(size) | |||
| 705 | page_dir[index+i] = MALLOC_FOLLOW; | 728 | page_dir[index+i] = MALLOC_FOLLOW; |
| 706 | 729 | ||
| 707 | if (malloc_junk) | 730 | if (malloc_junk) |
| 708 | memset(p, SOME_JUNK,size << malloc_pageshift); | 731 | memset(p, SOME_JUNK, size << malloc_pageshift); |
| 709 | } | 732 | } |
| 710 | 733 | ||
| 711 | if (delay_free) { | 734 | if (delay_free) { |
| 712 | if (!px) | 735 | if (!px) |
| 713 | px = delay_free; | 736 | px = delay_free; |
| 714 | else | 737 | else |
| 715 | free(delay_free); | 738 | ifree(delay_free); |
| 716 | } | 739 | } |
| 717 | 740 | ||
| 718 | return p; | 741 | return p; |
| @@ -728,7 +751,7 @@ malloc_make_chunks(bits) | |||
| 728 | { | 751 | { |
| 729 | struct pginfo *bp; | 752 | struct pginfo *bp; |
| 730 | void *pp; | 753 | void *pp; |
| 731 | int i,k,l; | 754 | int i, k, l; |
| 732 | 755 | ||
| 733 | /* Allocate a new bucket */ | 756 | /* Allocate a new bucket */ |
| 734 | pp = malloc_pages(malloc_pagesize); | 757 | pp = malloc_pages(malloc_pagesize); |
| @@ -744,7 +767,7 @@ malloc_make_chunks(bits) | |||
| 744 | if ((1<<(bits)) <= l+l) { | 767 | if ((1<<(bits)) <= l+l) { |
| 745 | bp = (struct pginfo *)pp; | 768 | bp = (struct pginfo *)pp; |
| 746 | } else { | 769 | } else { |
| 747 | bp = (struct pginfo *)malloc(l); | 770 | bp = (struct pginfo *)imalloc(l); |
| 748 | if (!bp) | 771 | if (!bp) |
| 749 | return 0; | 772 | return 0; |
| 750 | } | 773 | } |
| @@ -768,12 +791,12 @@ malloc_make_chunks(bits) | |||
| 768 | bp->bits[i / MALLOC_BITS] = (u_long)~0; | 791 | bp->bits[i / MALLOC_BITS] = (u_long)~0; |
| 769 | 792 | ||
| 770 | for(; i < k; i++) | 793 | for(; i < k; i++) |
| 771 | set_bit(bp,i); | 794 | set_bit(bp, i); |
| 772 | 795 | ||
| 773 | if (bp == bp->page) { | 796 | if (bp == bp->page) { |
| 774 | /* Mark the ones we stole for ourselves */ | 797 | /* Mark the ones we stole for ourselves */ |
| 775 | for(i=0;l > 0;i++) { | 798 | for(i=0;l > 0;i++) { |
| 776 | clr_bit(bp,i); | 799 | clr_bit(bp, i); |
| 777 | bp->free--; | 800 | bp->free--; |
| 778 | bp->total--; | 801 | bp->total--; |
| 779 | l -= (1 << bits); | 802 | l -= (1 << bits); |
| @@ -835,8 +858,8 @@ malloc_bytes(size) | |||
| 835 | /* | 858 | /* |
| 836 | * Allocate a piece of memory | 859 | * Allocate a piece of memory |
| 837 | */ | 860 | */ |
| 838 | void * | 861 | static void * |
| 839 | malloc(size) | 862 | imalloc(size) |
| 840 | size_t size; | 863 | size_t size; |
| 841 | { | 864 | { |
| 842 | void *result; | 865 | void *result; |
| @@ -850,36 +873,30 @@ malloc(size) | |||
| 850 | if (suicide) | 873 | if (suicide) |
| 851 | abort(); | 874 | abort(); |
| 852 | 875 | ||
| 853 | #ifdef _THREAD_SAFE | ||
| 854 | _thread_kern_sig_block(&status); | ||
| 855 | #endif | ||
| 856 | if (size <= malloc_maxsize) | 876 | if (size <= malloc_maxsize) |
| 857 | result = malloc_bytes(size); | 877 | result = malloc_bytes(size); |
| 858 | else | 878 | else |
| 859 | result = malloc_pages(size); | 879 | result = malloc_pages(size); |
| 860 | 880 | ||
| 861 | if (malloc_abort && !result) | 881 | if (malloc_abort && !result) |
| 862 | wrterror("malloc(): returns NULL\n"); | 882 | wrterror("allocation failed.\n"); |
| 863 | 883 | ||
| 864 | if (malloc_zero) | 884 | if (malloc_zero) |
| 865 | memset(result,0,size); | 885 | memset(result, 0, size); |
| 866 | 886 | ||
| 867 | #ifdef _THREAD_SAFE | ||
| 868 | _thread_kern_sig_unblock(status); | ||
| 869 | #endif | ||
| 870 | return result; | 887 | return result; |
| 871 | } | 888 | } |
| 872 | 889 | ||
| 873 | /* | 890 | /* |
| 874 | * Change the size of an allocation. | 891 | * Change the size of an allocation. |
| 875 | */ | 892 | */ |
| 876 | void * | 893 | static void * |
| 877 | realloc(ptr, size) | 894 | irealloc(ptr, size) |
| 878 | void *ptr; | 895 | void *ptr; |
| 879 | size_t size; | 896 | size_t size; |
| 880 | { | 897 | { |
| 881 | void *p; | 898 | void *p; |
| 882 | u_long osize,index; | 899 | u_long osize, index; |
| 883 | struct pginfo **mp; | 900 | struct pginfo **mp; |
| 884 | int i; | 901 | int i; |
| 885 | #ifdef _THREAD_SAFE | 902 | #ifdef _THREAD_SAFE |
| @@ -889,37 +906,20 @@ realloc(ptr, size) | |||
| 889 | if (suicide) | 906 | if (suicide) |
| 890 | return 0; | 907 | return 0; |
| 891 | 908 | ||
| 892 | if (!ptr) /* Bounce to malloc() */ | ||
| 893 | return malloc(size); | ||
| 894 | |||
| 895 | if (!initialized) { | 909 | if (!initialized) { |
| 896 | wrtwarning("realloc(): malloc() never got called.\n"); | 910 | wrtwarning("malloc() has never been called.\n"); |
| 897 | return 0; | ||
| 898 | } | ||
| 899 | |||
| 900 | if (ptr && !size) { /* Bounce to free() */ | ||
| 901 | free(ptr); | ||
| 902 | return 0; | 911 | return 0; |
| 903 | } | 912 | } |
| 904 | 913 | ||
| 905 | #ifdef _THREAD_SAFE | ||
| 906 | _thread_kern_sig_block(&status); | ||
| 907 | #endif | ||
| 908 | index = ptr2index(ptr); | 914 | index = ptr2index(ptr); |
| 909 | 915 | ||
| 910 | if (index < malloc_pageshift) { | 916 | if (index < malloc_pageshift) { |
| 911 | wrtwarning("realloc(): junk pointer (too low)\n"); | 917 | wrtwarning("junk pointer, too low to make sense.\n"); |
| 912 | #ifdef _THREAD_SAFE | ||
| 913 | _thread_kern_sig_unblock(status); | ||
| 914 | #endif | ||
| 915 | return 0; | 918 | return 0; |
| 916 | } | 919 | } |
| 917 | 920 | ||
| 918 | if (index > last_index) { | 921 | if (index > last_index) { |
| 919 | wrtwarning("realloc(): junk pointer (too high)\n"); | 922 | wrtwarning("junk pointer, too high to make sense.\n"); |
| 920 | #ifdef _THREAD_SAFE | ||
| 921 | _thread_kern_sig_unblock(status); | ||
| 922 | #endif | ||
| 923 | return 0; | 923 | return 0; |
| 924 | } | 924 | } |
| 925 | 925 | ||
| @@ -929,10 +929,7 @@ realloc(ptr, size) | |||
| 929 | 929 | ||
| 930 | /* Check the pointer */ | 930 | /* Check the pointer */ |
| 931 | if ((u_long)ptr & malloc_pagemask) { | 931 | if ((u_long)ptr & malloc_pagemask) { |
| 932 | wrtwarning("realloc(): modified page pointer.\n"); | 932 | wrtwarning("modified (page-) pointer.\n"); |
| 933 | #ifdef _THREAD_SAFE | ||
| 934 | _thread_kern_sig_unblock(status); | ||
| 935 | #endif | ||
| 936 | return 0; | 933 | return 0; |
| 937 | } | 934 | } |
| 938 | 935 | ||
| @@ -943,9 +940,6 @@ realloc(ptr, size) | |||
| 943 | if (!malloc_realloc && /* unless we have to, */ | 940 | if (!malloc_realloc && /* unless we have to, */ |
| 944 | size <= osize && /* .. or are too small, */ | 941 | size <= osize && /* .. or are too small, */ |
| 945 | size > (osize - malloc_pagesize)) { /* .. or can free a page, */ | 942 | size > (osize - malloc_pagesize)) { /* .. or can free a page, */ |
| 946 | #ifdef _THREAD_SAFE | ||
| 947 | _thread_kern_sig_unblock(status); | ||
| 948 | #endif | ||
| 949 | return ptr; /* don't do anything. */ | 943 | return ptr; /* don't do anything. */ |
| 950 | } | 944 | } |
| 951 | 945 | ||
| @@ -953,10 +947,7 @@ realloc(ptr, size) | |||
| 953 | 947 | ||
| 954 | /* Check the pointer for sane values */ | 948 | /* Check the pointer for sane values */ |
| 955 | if (((u_long)ptr & ((*mp)->size-1))) { | 949 | if (((u_long)ptr & ((*mp)->size-1))) { |
| 956 | wrtwarning("realloc(): modified chunk pointer.\n"); | 950 | wrtwarning("modified (chunk-) pointer.\n"); |
| 957 | #ifdef _THREAD_SAFE | ||
| 958 | _thread_kern_sig_unblock(status); | ||
| 959 | #endif | ||
| 960 | return 0; | 951 | return 0; |
| 961 | } | 952 | } |
| 962 | 953 | ||
| @@ -964,11 +955,8 @@ realloc(ptr, size) | |||
| 964 | i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift; | 955 | i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift; |
| 965 | 956 | ||
| 966 | /* Verify that it isn't a free chunk already */ | 957 | /* Verify that it isn't a free chunk already */ |
| 967 | if (tst_bit(*mp,i)) { | 958 | if (tst_bit(*mp, i)) { |
| 968 | wrtwarning("realloc(): already free chunk.\n"); | 959 | wrtwarning("chunk is already free.\n"); |
| 969 | #ifdef _THREAD_SAFE | ||
| 970 | _thread_kern_sig_unblock(status); | ||
| 971 | #endif | ||
| 972 | return 0; | 960 | return 0; |
| 973 | } | 961 | } |
| 974 | 962 | ||
| @@ -978,33 +966,24 @@ realloc(ptr, size) | |||
| 978 | size < osize && /* ..or are too small, */ | 966 | size < osize && /* ..or are too small, */ |
| 979 | (size > osize/2 || /* ..or could use a smaller size, */ | 967 | (size > osize/2 || /* ..or could use a smaller size, */ |
| 980 | osize == malloc_minsize)) { /* ..(if there is one) */ | 968 | osize == malloc_minsize)) { /* ..(if there is one) */ |
| 981 | #ifdef _THREAD_SAFE | ||
| 982 | _thread_kern_sig_unblock(status); | ||
| 983 | #endif | ||
| 984 | return ptr; /* ..Don't do anything */ | 969 | return ptr; /* ..Don't do anything */ |
| 985 | } | 970 | } |
| 986 | 971 | ||
| 987 | } else { | 972 | } else { |
| 988 | wrtwarning("realloc(): wrong page pointer.\n"); | 973 | wrtwarning("pointer to wrong page.\n"); |
| 989 | #ifdef _THREAD_SAFE | ||
| 990 | _thread_kern_sig_unblock(status); | ||
| 991 | #endif | ||
| 992 | return 0; | 974 | return 0; |
| 993 | } | 975 | } |
| 994 | 976 | ||
| 995 | p = malloc(size); | 977 | p = imalloc(size); |
| 996 | 978 | ||
| 997 | if (p) { | 979 | if (p) { |
| 998 | /* copy the lesser of the two sizes, and free the old one */ | 980 | /* copy the lesser of the two sizes, and free the old one */ |
| 999 | if (osize < size) | 981 | if (osize < size) |
| 1000 | memcpy(p,ptr,osize); | 982 | memcpy(p, ptr, osize); |
| 1001 | else | 983 | else |
| 1002 | memcpy(p,ptr,size); | 984 | memcpy(p, ptr, size); |
| 1003 | free(ptr); | 985 | ifree(ptr); |
| 1004 | } | 986 | } |
| 1005 | #ifdef _THREAD_SAFE | ||
| 1006 | _thread_kern_sig_unblock(status); | ||
| 1007 | #endif | ||
| 1008 | return p; | 987 | return p; |
| 1009 | } | 988 | } |
| 1010 | 989 | ||
| @@ -1019,22 +998,22 @@ free_pages(ptr, index, info) | |||
| 1019 | struct pginfo *info; | 998 | struct pginfo *info; |
| 1020 | { | 999 | { |
| 1021 | int i; | 1000 | int i; |
| 1022 | struct pgfree *pf,*pt=0; | 1001 | struct pgfree *pf, *pt=0; |
| 1023 | u_long l; | 1002 | u_long l; |
| 1024 | void *tail; | 1003 | void *tail; |
| 1025 | 1004 | ||
| 1026 | if (info == MALLOC_FREE) { | 1005 | if (info == MALLOC_FREE) { |
| 1027 | wrtwarning("free(): already free page.\n"); | 1006 | wrtwarning("page is already free.\n"); |
| 1028 | return; | 1007 | return; |
| 1029 | } | 1008 | } |
| 1030 | 1009 | ||
| 1031 | if (info != MALLOC_FIRST) { | 1010 | if (info != MALLOC_FIRST) { |
| 1032 | wrtwarning("free(): freeing wrong page.\n"); | 1011 | wrtwarning("pointer to wrong page.\n"); |
| 1033 | return; | 1012 | return; |
| 1034 | } | 1013 | } |
| 1035 | 1014 | ||
| 1036 | if ((u_long)ptr & malloc_pagemask) { | 1015 | if ((u_long)ptr & malloc_pagemask) { |
| 1037 | wrtwarning("free(): modified page pointer.\n"); | 1016 | wrtwarning("modified (page-) pointer.\n"); |
| 1038 | return; | 1017 | return; |
| 1039 | } | 1018 | } |
| 1040 | 1019 | ||
| @@ -1045,11 +1024,16 @@ free_pages(ptr, index, info) | |||
| 1045 | 1024 | ||
| 1046 | l = i << malloc_pageshift; | 1025 | l = i << malloc_pageshift; |
| 1047 | 1026 | ||
| 1048 | tail = (char *)ptr + l; | 1027 | #ifdef __FreeBSD__ |
| 1028 | if (malloc_hint) | ||
| 1029 | madvise(ptr, l, MADV_FREE); | ||
| 1030 | #endif | ||
| 1031 | |||
| 1032 | tail = (char *)ptr+l; | ||
| 1049 | 1033 | ||
| 1050 | /* add to free-list */ | 1034 | /* add to free-list */ |
| 1051 | if (!px) | 1035 | if (!px) |
| 1052 | px = malloc(sizeof *pt); /* This cannot fail... */ | 1036 | px = imalloc(sizeof *pt); /* This cannot fail... */ |
| 1053 | px->page = ptr; | 1037 | px->page = ptr; |
| 1054 | px->end = tail; | 1038 | px->end = tail; |
| 1055 | px->size = l; | 1039 | px->size = l; |
| @@ -1065,7 +1049,7 @@ free_pages(ptr, index, info) | |||
| 1065 | } else { | 1049 | } else { |
| 1066 | 1050 | ||
| 1067 | /* Find the right spot, leave pf pointing to the modified entry. */ | 1051 | /* Find the right spot, leave pf pointing to the modified entry. */ |
| 1068 | tail = (char *)ptr + l; | 1052 | tail = (char *)ptr+l; |
| 1069 | 1053 | ||
| 1070 | for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next) | 1054 | for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next) |
| 1071 | ; /* Race ahead here */ | 1055 | ; /* Race ahead here */ |
| @@ -1103,7 +1087,7 @@ free_pages(ptr, index, info) | |||
| 1103 | pf = px; | 1087 | pf = px; |
| 1104 | px = 0; | 1088 | px = 0; |
| 1105 | } else { | 1089 | } else { |
| 1106 | wrterror("messed up free list"); | 1090 | wrterror("freelist is destroyed.\n"); |
| 1107 | } | 1091 | } |
| 1108 | } | 1092 | } |
| 1109 | 1093 | ||
| @@ -1132,7 +1116,7 @@ free_pages(ptr, index, info) | |||
| 1132 | /* XXX: We could realloc/shrink the pagedir here I guess. */ | 1116 | /* XXX: We could realloc/shrink the pagedir here I guess. */ |
| 1133 | } | 1117 | } |
| 1134 | if (pt) | 1118 | if (pt) |
| 1135 | free(pt); | 1119 | ifree(pt); |
| 1136 | } | 1120 | } |
| 1137 | 1121 | ||
| 1138 | /* | 1122 | /* |
| @@ -1154,16 +1138,16 @@ free_bytes(ptr, index, info) | |||
| 1154 | i = ((u_long)ptr & malloc_pagemask) >> info->shift; | 1138 | i = ((u_long)ptr & malloc_pagemask) >> info->shift; |
| 1155 | 1139 | ||
| 1156 | if (((u_long)ptr & (info->size-1))) { | 1140 | if (((u_long)ptr & (info->size-1))) { |
| 1157 | wrtwarning("free(): modified pointer.\n"); | 1141 | wrtwarning("modified (chunk-) pointer.\n"); |
| 1158 | return; | 1142 | return; |
| 1159 | } | 1143 | } |
| 1160 | 1144 | ||
| 1161 | if (tst_bit(info,i)) { | 1145 | if (tst_bit(info, i)) { |
| 1162 | wrtwarning("free(): already free chunk.\n"); | 1146 | wrtwarning("chunk is already free.\n"); |
| 1163 | return; | 1147 | return; |
| 1164 | } | 1148 | } |
| 1165 | 1149 | ||
| 1166 | set_bit(info,i); | 1150 | set_bit(info, i); |
| 1167 | info->free++; | 1151 | info->free++; |
| 1168 | 1152 | ||
| 1169 | mp = page_dir + info->shift; | 1153 | mp = page_dir + info->shift; |
| @@ -1198,12 +1182,12 @@ free_bytes(ptr, index, info) | |||
| 1198 | page_dir[ptr2index(info->page)] = MALLOC_FIRST; | 1182 | page_dir[ptr2index(info->page)] = MALLOC_FIRST; |
| 1199 | vp = info->page; /* Order is important ! */ | 1183 | vp = info->page; /* Order is important ! */ |
| 1200 | if(vp != (void*)info) | 1184 | if(vp != (void*)info) |
| 1201 | free(info); | 1185 | ifree(info); |
| 1202 | free(vp); | 1186 | ifree(vp); |
| 1203 | } | 1187 | } |
| 1204 | 1188 | ||
| 1205 | void | 1189 | static void |
| 1206 | free(ptr) | 1190 | ifree(ptr) |
| 1207 | void *ptr; | 1191 | void *ptr; |
| 1208 | { | 1192 | { |
| 1209 | struct pginfo *info; | 1193 | struct pginfo *info; |
| @@ -1217,7 +1201,7 @@ free(ptr) | |||
| 1217 | return; | 1201 | return; |
| 1218 | 1202 | ||
| 1219 | if (!initialized) { | 1203 | if (!initialized) { |
| 1220 | wrtwarning("free(): malloc() never got called.\n"); | 1204 | wrtwarning("malloc() has never been called.\n"); |
| 1221 | return; | 1205 | return; |
| 1222 | } | 1206 | } |
| 1223 | 1207 | ||
| @@ -1225,35 +1209,102 @@ free(ptr) | |||
| 1225 | if (suicide) | 1209 | if (suicide) |
| 1226 | return; | 1210 | return; |
| 1227 | 1211 | ||
| 1228 | #ifdef _THREAD_SAFE | ||
| 1229 | _thread_kern_sig_block(&status); | ||
| 1230 | #endif | ||
| 1231 | index = ptr2index(ptr); | 1212 | index = ptr2index(ptr); |
| 1232 | 1213 | ||
| 1233 | if (index < malloc_pageshift) { | 1214 | if (index < malloc_pageshift) { |
| 1234 | wrtwarning("free(): junk pointer (too low)\n"); | 1215 | wrtwarning("junk pointer, too low to make sense.\n"); |
| 1235 | #ifdef _THREAD_SAFE | ||
| 1236 | _thread_kern_sig_unblock(status); | ||
| 1237 | #endif | ||
| 1238 | return; | 1216 | return; |
| 1239 | } | 1217 | } |
| 1240 | 1218 | ||
| 1241 | if (index > last_index) { | 1219 | if (index > last_index) { |
| 1242 | wrtwarning("free(): junk pointer (too high)\n"); | 1220 | wrtwarning("junk pointer, too high to make sense.\n"); |
| 1243 | #ifdef _THREAD_SAFE | ||
| 1244 | _thread_kern_sig_unblock(status); | ||
| 1245 | #endif | ||
| 1246 | return; | 1221 | return; |
| 1247 | } | 1222 | } |
| 1248 | 1223 | ||
| 1249 | info = page_dir[index]; | 1224 | info = page_dir[index]; |
| 1250 | 1225 | ||
| 1251 | if (info < MALLOC_MAGIC) | 1226 | if (info < MALLOC_MAGIC) |
| 1252 | free_pages(ptr,index,info); | 1227 | free_pages(ptr, index, info); |
| 1253 | else | 1228 | else |
| 1254 | free_bytes(ptr,index,info); | 1229 | free_bytes(ptr, index, info); |
| 1255 | #ifdef _THREAD_SAFE | 1230 | return; |
| 1256 | _thread_kern_sig_unblock(status); | 1231 | } |
| 1232 | |||
| 1233 | /* | ||
| 1234 | * These are the public exported interface routines. | ||
| 1235 | */ | ||
| 1236 | |||
| 1237 | #ifdef _THREAD_SAFE | ||
| 1238 | #include <pthread.h> | ||
| 1239 | #include "pthread_private.h" | ||
| 1240 | static int malloc_lock; | ||
| 1241 | #define THREAD_LOCK() _thread_kern_sig_block(&malloc_lock); | ||
| 1242 | #define THREAD_UNLOCK() _thread_kern_sig_unblock(&malloc_lock); | ||
| 1243 | #else | ||
| 1244 | #define THREAD_LOCK() | ||
| 1245 | #define THREAD_UNLOCK() | ||
| 1257 | #endif | 1246 | #endif |
| 1247 | |||
| 1248 | static int malloc_active; | ||
| 1249 | |||
| 1250 | void * | ||
| 1251 | malloc(size_t size) | ||
| 1252 | { | ||
| 1253 | register void *r; | ||
| 1254 | |||
| 1255 | malloc_func = "malloc():"; | ||
| 1256 | THREAD_LOCK(); | ||
| 1257 | if (malloc_active++) { | ||
| 1258 | wrtwarning("recursive call.\n"); | ||
| 1259 | malloc_active--; | ||
| 1260 | return (0); | ||
| 1261 | } | ||
| 1262 | r = imalloc(size); | ||
| 1263 | UTRACE(0, size, r); | ||
| 1264 | malloc_active--; | ||
| 1265 | THREAD_UNLOCK(); | ||
| 1266 | return (r); | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | void | ||
| 1270 | free(void *ptr) | ||
| 1271 | { | ||
| 1272 | malloc_func = "free():"; | ||
| 1273 | THREAD_LOCK(); | ||
| 1274 | if (malloc_active++) { | ||
| 1275 | wrtwarning("recursive call.\n"); | ||
| 1276 | malloc_active--; | ||
| 1277 | return; | ||
| 1278 | } | ||
| 1279 | ifree(ptr); | ||
| 1280 | UTRACE(ptr, 0, 0); | ||
| 1281 | malloc_active--; | ||
| 1282 | THREAD_UNLOCK(); | ||
| 1258 | return; | 1283 | return; |
| 1259 | } | 1284 | } |
| 1285 | |||
| 1286 | void * | ||
| 1287 | realloc(void *ptr, size_t size) | ||
| 1288 | { | ||
| 1289 | register void *r; | ||
| 1290 | |||
| 1291 | malloc_func = "realloc():"; | ||
| 1292 | THREAD_LOCK(); | ||
| 1293 | if (malloc_active++) { | ||
| 1294 | wrtwarning("recursive call.\n"); | ||
| 1295 | malloc_active--; | ||
| 1296 | return (0); | ||
| 1297 | } | ||
| 1298 | if (!ptr) { | ||
| 1299 | r = imalloc(size); | ||
| 1300 | } else if (ptr && !size) { | ||
| 1301 | ifree(ptr); | ||
| 1302 | r = 0; | ||
| 1303 | } else { | ||
| 1304 | r = irealloc(ptr, size); | ||
| 1305 | } | ||
| 1306 | UTRACE(ptr, size, r); | ||
| 1307 | malloc_active--; | ||
| 1308 | THREAD_UNLOCK(); | ||
| 1309 | return (r); | ||
| 1310 | } | ||
