perl 5.003_04: config_h.SH
[p5sagit/p5-mst-13.2.git] / malloc.c
CommitLineData
a0d0e21e 1/* malloc.c
8d063cd8 2 *
8d063cd8 3 */
4
5#ifndef lint
a687059c 6#ifdef DEBUGGING
8d063cd8 7#define RCHECK
a687059c 8#endif
8d063cd8 9/*
10 * malloc.c (Caltech) 2/21/82
11 * Chris Kingsley, kingsley@cit-20.
12 *
13 * This is a very fast storage allocator. It allocates blocks of a small
14 * number of different sizes, and keeps free lists of each size. Blocks that
15 * don't exactly fit are passed up to the next larger size. In this
16 * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
cf5c4ad8 17 * If PACK_MALLOC is defined, small blocks are 2^n bytes long.
8d063cd8 18 * This is designed for use in a program that uses vast quantities of memory,
19 * but bombs when it runs out.
20 */
21
135863df 22#include "EXTERN.h"
135863df 23#include "perl.h"
24
760ac839 25#ifdef DEBUGGING
26#undef DEBUG_m
27#define DEBUG_m(a) if (debug & 128) a
28#endif
29
135863df 30/* I don't much care whether these are defined in sys/types.h--LAW */
31
32#define u_char unsigned char
33#define u_int unsigned int
34#define u_short unsigned short
8d063cd8 35
cf5c4ad8 36/* 286 and atarist like big chunks, which gives too much overhead. */
37#if (defined(RCHECK) || defined(I286) || defined(atarist)) && defined(PACK_MALLOC)
38#undef PACK_MALLOC
39#endif
40
41
8d063cd8 42/*
cf5c4ad8 43 * The description below is applicable if PACK_MALLOC is not defined.
44 *
8d063cd8 45 * The overhead on a block is at least 4 bytes. When free, this space
46 * contains a pointer to the next free block, and the bottom two bits must
47 * be zero. When in use, the first byte is set to MAGIC, and the second
48 * byte is the size index. The remaining bytes are for alignment.
49 * If range checking is enabled and the size of the block fits
50 * in two bytes, then the top two bytes hold the size of the requested block
51 * plus the range checking words, and the header word MINUS ONE.
52 */
53union overhead {
54 union overhead *ov_next; /* when free */
85e6fe83 55#if MEM_ALIGNBYTES > 4
c623bd54 56 double strut; /* alignment problems */
a687059c 57#endif
8d063cd8 58 struct {
59 u_char ovu_magic; /* magic number */
60 u_char ovu_index; /* bucket # */
61#ifdef RCHECK
62 u_short ovu_size; /* actual block size */
63 u_int ovu_rmagic; /* range magic number */
64#endif
65 } ovu;
66#define ov_magic ovu.ovu_magic
67#define ov_index ovu.ovu_index
68#define ov_size ovu.ovu_size
69#define ov_rmagic ovu.ovu_rmagic
70};
71
760ac839 72#ifdef DEBUGGING
a0d0e21e 73static void botch _((char *s));
74#endif
75static void morecore _((int bucket));
76static int findbucket _((union overhead *freep, int srchlen));
77
8d063cd8 78#define MAGIC 0xff /* magic # on accounting info */
79#define RMAGIC 0x55555555 /* magic # on range info */
80#ifdef RCHECK
81#define RSLOP sizeof (u_int)
82#else
83#define RSLOP 0
84#endif
85
cf5c4ad8 86#ifdef PACK_MALLOC
87/*
88 * In this case it is assumed that if we do sbrk() in 2K units, we
89 * will get 2K aligned blocks. The bucket number of the given subblock is
90 * on the boundary of 2K block which contains the subblock.
91 * Several following bytes contain the magic numbers for the subblocks
92 * in the block.
93 *
94 * Sizes of chunks are powers of 2 for chunks in buckets <=
95 * MAX_PACKED, after this they are (2^n - sizeof(union overhead)) (to
96 * get alignment right).
97 *
98 * We suppose that starts of all the chunks in a 2K block are in
99 * different 2^n-byte-long chunks. If the top of the last chunk is
100 * aligned on a boundary of 2K block, this means that
101 * sizeof(union overhead)*"number of chunks" < 2^n, or
102 * sizeof(union overhead)*2K < 4^n, or n > 6 + log2(sizeof()/2)/2, if a
103 * chunk of size 2^n - overhead is used. Since this rules out n = 7
104 * for 8 byte alignment, we specialcase allocation of the first of 16
105 * 128-byte-long chunks.
106 *
107 * Note that with the above assumption we automatically have enough
108 * place for MAGIC at the start of 2K block. Note also that we
109 * overlay union overhead over the chunk, thus the start of the chunk
110 * is immediately overwritten after freeing.
111 */
112# define MAX_PACKED 6
113# define MAX_2_POT_ALGO ((1<<(MAX_PACKED + 1)) - M_OVERHEAD)
114# define TWOK_MASK ((1<<11) - 1)
115# define TWOK_MASKED(x) ((int)x & ~TWOK_MASK)
116# define TWOK_SHIFT(x) ((int)x & TWOK_MASK)
117# define OV_INDEXp(block) ((u_char*)(TWOK_MASKED(block)))
118# define OV_INDEX(block) (*OV_INDEXp(block))
119# define OV_MAGIC(block,bucket) (*(OV_INDEXp(block) + \
120 (TWOK_SHIFT(block)>>(bucket + 3)) + \
121 (bucket > MAX_NONSHIFT ? 1 : 0)))
122# define CHUNK_SHIFT 0
123
124static u_char n_blks[11 - 3] = {224, 120, 62, 31, 16, 8, 4, 2};
125static u_short blk_shift[11 - 3] = {256, 128, 64, 32,
126 16*sizeof(union overhead),
127 8*sizeof(union overhead),
128 4*sizeof(union overhead),
129 2*sizeof(union overhead),
130# define MAX_NONSHIFT 2 /* Shift 64 greater than chunk 32. */
131};
132
133# ifdef DEBUGGING_MSTATS
134static u_int sbrk_slack;
135static u_int start_slack;
136# endif
137
138#else /* !PACK_MALLOC */
139
140# define OV_MAGIC(block,bucket) (block)->ov_magic
141# define OV_INDEX(block) (block)->ov_index
142# define CHUNK_SHIFT 1
143#endif /* !PACK_MALLOC */
144
145# define M_OVERHEAD (sizeof(union overhead) + RSLOP)
146
8d063cd8 147/*
148 * nextf[i] is the pointer to the next free block of size 2^(i+3). The
149 * smallest allocatable block is 8 bytes. The overhead information
150 * precedes the data area returned to the user.
151 */
152#define NBUCKETS 30
153static union overhead *nextf[NBUCKETS];
cf5c4ad8 154
155#ifdef USE_PERL_SBRK
156#define sbrk(a) Perl_sbrk(a)
157char * Perl_sbrk _((int size));
158#else
8d063cd8 159extern char *sbrk();
cf5c4ad8 160#endif
8d063cd8 161
c07a80fd 162#ifdef DEBUGGING_MSTATS
8d063cd8 163/*
164 * nmalloc[i] is the difference between the number of mallocs and frees
165 * for a given block size.
166 */
167static u_int nmalloc[NBUCKETS];
8d063cd8 168#endif
169
760ac839 170#ifdef DEBUGGING
8d063cd8 171#define ASSERT(p) if (!(p)) botch("p"); else
ee0007ab 172static void
8d063cd8 173botch(s)
174 char *s;
175{
176
177 printf("assertion botched: %s\n", s);
178 abort();
179}
180#else
181#define ASSERT(p)
182#endif
183
2304df62 184Malloc_t
8d063cd8 185malloc(nbytes)
ee0007ab 186 register MEM_SIZE nbytes;
8d063cd8 187{
188 register union overhead *p;
189 register int bucket = 0;
ee0007ab 190 register MEM_SIZE shiftr;
8d063cd8 191
45d8adaa 192#ifdef safemalloc
193#ifdef DEBUGGING
ee0007ab 194 MEM_SIZE size = nbytes;
45d8adaa 195#endif
196
197#ifdef MSDOS
198 if (nbytes > 0xffff) {
760ac839 199 PerlIO_printf(PerlIO_stderr(), "Allocation too large: %lx\n", (long)nbytes);
79072805 200 my_exit(1);
45d8adaa 201 }
202#endif /* MSDOS */
203#ifdef DEBUGGING
204 if ((long)nbytes < 0)
463ee0b2 205 croak("panic: malloc");
45d8adaa 206#endif
207#endif /* safemalloc */
208
8d063cd8 209 /*
210 * Convert amount of memory requested into
211 * closest block size stored in hash buckets
212 * which satisfies request. Account for
213 * space used per block for accounting.
214 */
cf5c4ad8 215#ifdef PACK_MALLOC
216 if (nbytes > MAX_2_POT_ALGO) {
217#endif
218 nbytes += M_OVERHEAD;
219 nbytes = (nbytes + 3) &~ 3;
220#ifdef PACK_MALLOC
221 } else if (nbytes == 0) {
222 nbytes = 1;
223 }
224#endif
8d063cd8 225 shiftr = (nbytes - 1) >> 2;
226 /* apart from this loop, this is O(1) */
227 while (shiftr >>= 1)
228 bucket++;
229 /*
230 * If nothing in hash bucket right now,
231 * request more memory from the system.
232 */
233 if (nextf[bucket] == NULL)
234 morecore(bucket);
45d8adaa 235 if ((p = (union overhead *)nextf[bucket]) == NULL) {
236#ifdef safemalloc
ee0007ab 237 if (!nomemok) {
760ac839 238 PerlIO_puts(PerlIO_stderr(),"Out of memory!\n");
79072805 239 my_exit(1);
ee0007ab 240 }
45d8adaa 241#else
8d063cd8 242 return (NULL);
45d8adaa 243#endif
244 }
245
246#ifdef safemalloc
760ac839 247 DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) malloc %ld bytes\n",
a0d0e21e 248 (unsigned long)(p+1),an++,(long)size));
45d8adaa 249#endif /* safemalloc */
250
8d063cd8 251 /* remove from linked list */
bf38876a 252#ifdef RCHECK
253 if (*((int*)p) & (sizeof(union overhead) - 1))
760ac839 254 PerlIO_printf(PerlIO_stderr(), "Corrupt malloc ptr 0x%lx at 0x%lx\n",
a0d0e21e 255 (unsigned long)*((int*)p),(unsigned long)p);
bf38876a 256#endif
257 nextf[bucket] = p->ov_next;
cf5c4ad8 258 OV_MAGIC(p, bucket) = MAGIC;
259#ifndef PACK_MALLOC
260 OV_INDEX(p) = bucket;
261#endif
c07a80fd 262#ifdef DEBUGGING_MSTATS
8d063cd8 263 nmalloc[bucket]++;
264#endif
265#ifdef RCHECK
266 /*
267 * Record allocated size of block and
268 * bound space with magic numbers.
269 */
270 if (nbytes <= 0x10000)
271 p->ov_size = nbytes - 1;
272 p->ov_rmagic = RMAGIC;
273 *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
274#endif
cf5c4ad8 275 return ((Malloc_t)(p + CHUNK_SHIFT));
8d063cd8 276}
277
278/*
279 * Allocate more memory to the indicated bucket.
280 */
a0d0e21e 281static void
8d063cd8 282morecore(bucket)
a687059c 283 register int bucket;
8d063cd8 284{
285 register union overhead *op;
286 register int rnu; /* 2^rnu bytes will be requested */
287 register int nblks; /* become nblks blocks of the desired size */
ee0007ab 288 register MEM_SIZE siz;
cf5c4ad8 289 int slack = 0;
8d063cd8 290
291 if (nextf[bucket])
292 return;
293 /*
294 * Insure memory is allocated
295 * on a page boundary. Should
296 * make getpageize call?
297 */
ee0007ab 298#ifndef atarist /* on the atari we dont have to worry about this */
8d063cd8 299 op = (union overhead *)sbrk(0);
cf5c4ad8 300# ifndef I286
301# ifdef PACK_MALLOC
302 if ((int)op & 0x7ff)
303 (void)sbrk(slack = 2048 - ((int)op & 0x7ff));
304# else
8d063cd8 305 if ((int)op & 0x3ff)
cf5c4ad8 306 (void)sbrk(slack = 1024 - ((int)op & 0x3ff));
307# endif
308# if defined(DEBUGGING_MSTATS) && defined(PACK_MALLOC)
309 sbrk_slack += slack;
310# endif
311# else
a687059c 312 /* The sbrk(0) call on the I286 always returns the next segment */
cf5c4ad8 313# endif
ee0007ab 314#endif /* atarist */
a687059c 315
ee0007ab 316#if !(defined(I286) || defined(atarist))
8d063cd8 317 /* take 2k unless the block is bigger than that */
318 rnu = (bucket <= 8) ? 11 : bucket + 3;
a687059c 319#else
320 /* take 16k unless the block is bigger than that
ee0007ab 321 (80286s like large segments!), probably good on the atari too */
a687059c 322 rnu = (bucket <= 11) ? 14 : bucket + 3;
323#endif
8d063cd8 324 nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */
cf5c4ad8 325 /* if (rnu < bucket)
326 rnu = bucket; Why anyone needs this? */
ee0007ab 327 op = (union overhead *)sbrk(1L << rnu);
8d063cd8 328 /* no more room! */
329 if ((int)op == -1)
330 return;
331 /*
332 * Round up to minimum allocation size boundary
333 * and deduct from block count to reflect.
334 */
a687059c 335#ifndef I286
cf5c4ad8 336# ifdef PACK_MALLOC
337 if ((int)op & 0x7ff)
338 croak("panic: Off-page sbrk");
339# endif
8d063cd8 340 if ((int)op & 7) {
ee0007ab 341 op = (union overhead *)(((MEM_SIZE)op + 8) &~ 7);
8d063cd8 342 nblks--;
343 }
a687059c 344#else
345 /* Again, this should always be ok on an 80286 */
346#endif
8d063cd8 347 /*
348 * Add new memory allocated to that on
349 * free list for this hash bucket.
350 */
8d063cd8 351 siz = 1 << (bucket + 3);
cf5c4ad8 352#ifdef PACK_MALLOC
353 *(u_char*)op = bucket; /* Fill index. */
354 if (bucket <= MAX_PACKED - 3) {
355 op = (union overhead *) ((char*)op + blk_shift[bucket]);
356 nblks = n_blks[bucket];
357# ifdef DEBUGGING_MSTATS
358 start_slack += blk_shift[bucket];
359# endif
360 } else if (bucket <= 11 - 1 - 3) {
361 op = (union overhead *) ((char*)op + blk_shift[bucket]);
362 /* nblks = n_blks[bucket]; */
363 siz -= sizeof(union overhead);
364 } else op++; /* One chunk per block. */
365#endif /* !PACK_MALLOC */
366 nextf[bucket] = op;
8d063cd8 367 while (--nblks > 0) {
368 op->ov_next = (union overhead *)((caddr_t)op + siz);
369 op = (union overhead *)((caddr_t)op + siz);
370 }
cf5c4ad8 371#if defined(USE_PERL_SBRK) || defined(OS2)
372 /* all real sbrks return zeroe-d memory, perl's sbrk doesn't guarantee this */
373 op->ov_next = (union overhead *)NULL;
374#endif
375#ifdef PACK_MALLOC
376 if (bucket == 7 - 3) { /* Special case, explanation is above. */
377 union overhead *n_op = nextf[7 - 3]->ov_next;
378 nextf[7 - 3] = (union overhead *)((caddr_t)nextf[7 - 3]
379 - sizeof(union overhead));
380 nextf[7 - 3]->ov_next = n_op;
381 }
382#endif /* !PACK_MALLOC */
8d063cd8 383}
384
94b6baf5 385Free_t
352d5a3a 386free(mp)
2304df62 387 Malloc_t mp;
8d063cd8 388{
ee0007ab 389 register MEM_SIZE size;
8d063cd8 390 register union overhead *op;
352d5a3a 391 char *cp = (char*)mp;
cf5c4ad8 392#ifdef PACK_MALLOC
393 u_char bucket;
394#endif
8d063cd8 395
45d8adaa 396#ifdef safemalloc
760ac839 397 DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%lx: (%05d) free\n",(unsigned long)cp,an++));
45d8adaa 398#endif /* safemalloc */
399
cf5c4ad8 400 if (cp == NULL)
401 return;
402 op = (union overhead *)((caddr_t)cp
403 - sizeof (union overhead) * CHUNK_SHIFT);
404#ifdef PACK_MALLOC
405 bucket = OV_INDEX(op);
406#endif
760ac839 407#ifdef DEBUGGING
cf5c4ad8 408 ASSERT(OV_MAGIC(op, bucket) == MAGIC); /* make sure it was in use */
8d063cd8 409#else
cf5c4ad8 410 if (OV_MAGIC(op, bucket) != MAGIC) {
411 static bad_free_warn = -1;
412 if (bad_free_warn == -1) {
413 char *pbf = getenv("PERL_BADFREE");
414 bad_free_warn = (pbf) ? atoi(pbf) : 1;
415 }
416 if (!bad_free_warn)
417 return;
8990e307 418#ifdef RCHECK
a687059c 419 warn("%s free() ignored",
8990e307 420 op->ov_rmagic == RMAGIC - 1 ? "Duplicate" : "Bad");
421#else
422 warn("Bad free() ignored");
423#endif
8d063cd8 424 return; /* sanity */
378cc40b 425 }
8d063cd8 426#endif
427#ifdef RCHECK
428 ASSERT(op->ov_rmagic == RMAGIC);
cf5c4ad8 429 if (OV_INDEX(op) <= 13)
8d063cd8 430 ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC);
8990e307 431 op->ov_rmagic = RMAGIC - 1;
8d063cd8 432#endif
cf5c4ad8 433 ASSERT(OV_INDEX(op) < NBUCKETS);
434 size = OV_INDEX(op);
8d063cd8 435 op->ov_next = nextf[size];
436 nextf[size] = op;
c07a80fd 437#ifdef DEBUGGING_MSTATS
8d063cd8 438 nmalloc[size]--;
439#endif
440}
441
442/*
443 * When a program attempts "storage compaction" as mentioned in the
444 * old malloc man page, it realloc's an already freed block. Usually
445 * this is the last block it freed; occasionally it might be farther
446 * back. We have to search all the free lists for the block in order
447 * to determine its bucket: 1st we make one pass thru the lists
448 * checking only the first block in each; if that fails we search
378cc40b 449 * ``reall_srchlen'' blocks in each list for a match (the variable
8d063cd8 450 * is extern so the caller can modify it). If that fails we just copy
451 * however many bytes was given to realloc() and hope it's not huge.
452 */
378cc40b 453int reall_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
8d063cd8 454
2304df62 455Malloc_t
352d5a3a 456realloc(mp, nbytes)
2304df62 457 Malloc_t mp;
ee0007ab 458 MEM_SIZE nbytes;
8d063cd8 459{
ee0007ab 460 register MEM_SIZE onb;
8d063cd8 461 union overhead *op;
462 char *res;
463 register int i;
464 int was_alloced = 0;
352d5a3a 465 char *cp = (char*)mp;
8d063cd8 466
45d8adaa 467#ifdef safemalloc
468#ifdef DEBUGGING
ee0007ab 469 MEM_SIZE size = nbytes;
45d8adaa 470#endif
471
472#ifdef MSDOS
473 if (nbytes > 0xffff) {
760ac839 474 PerlIO_printf(PerlIO_stderr(), "Reallocation too large: %lx\n", size);
79072805 475 my_exit(1);
45d8adaa 476 }
477#endif /* MSDOS */
478 if (!cp)
ee0007ab 479 return malloc(nbytes);
45d8adaa 480#ifdef DEBUGGING
481 if ((long)nbytes < 0)
463ee0b2 482 croak("panic: realloc");
45d8adaa 483#endif
484#endif /* safemalloc */
485
cf5c4ad8 486 op = (union overhead *)((caddr_t)cp
487 - sizeof (union overhead) * CHUNK_SHIFT);
488 i = OV_INDEX(op);
489 if (OV_MAGIC(op, i) == MAGIC) {
8d063cd8 490 was_alloced++;
8d063cd8 491 } else {
492 /*
493 * Already free, doing "compaction".
494 *
495 * Search for the old block of memory on the
496 * free list. First, check the most common
497 * case (last element free'd), then (this failing)
378cc40b 498 * the last ``reall_srchlen'' items free'd.
8d063cd8 499 * If all lookups fail, then assume the size of
500 * the memory block being realloc'd is the
501 * smallest possible.
502 */
503 if ((i = findbucket(op, 1)) < 0 &&
378cc40b 504 (i = findbucket(op, reall_srchlen)) < 0)
8d063cd8 505 i = 0;
506 }
cf5c4ad8 507 onb = (1L << (i + 3)) -
508#ifdef PACK_MALLOC
509 (i <= (MAX_PACKED - 3) ? 0 : M_OVERHEAD)
510#else
511 M_OVERHEAD
512#endif
513 ;
8d063cd8 514 /* avoid the copy if same size block */
515 if (was_alloced &&
cf5c4ad8 516 nbytes <= onb && nbytes > (onb >> 1) - M_OVERHEAD) {
a687059c 517#ifdef RCHECK
518 /*
519 * Record new allocated size of block and
520 * bound space with magic numbers.
521 */
cf5c4ad8 522 if (OV_INDEX(op) <= 13) {
a687059c 523 /*
524 * Convert amount of memory requested into
525 * closest block size stored in hash buckets
526 * which satisfies request. Account for
527 * space used per block for accounting.
528 */
cf5c4ad8 529 nbytes += M_OVERHEAD;
a687059c 530 nbytes = (nbytes + 3) &~ 3;
531 op->ov_size = nbytes - 1;
532 *((u_int *)((caddr_t)op + nbytes - RSLOP)) = RMAGIC;
533 }
534#endif
45d8adaa 535 res = cp;
a687059c 536 }
45d8adaa 537 else {
538 if ((res = (char*)malloc(nbytes)) == NULL)
539 return (NULL);
540 if (cp != res) /* common optimization */
ee0007ab 541 Copy(cp, res, (MEM_SIZE)(nbytes<onb?nbytes:onb), char);
45d8adaa 542 if (was_alloced)
543 free(cp);
544 }
545
546#ifdef safemalloc
547#ifdef DEBUGGING
a0d0e21e 548 if (debug & 128) {
760ac839 549 PerlIO_printf(PerlIO_stderr(), "0x%lx: (%05d) rfree\n",(unsigned long)res,an++);
550 PerlIO_printf(PerlIO_stderr(), "0x%lx: (%05d) realloc %ld bytes\n",
a0d0e21e 551 (unsigned long)res,an++,(long)size);
552 }
45d8adaa 553#endif
554#endif /* safemalloc */
2304df62 555 return ((Malloc_t)res);
8d063cd8 556}
557
558/*
559 * Search ``srchlen'' elements of each free list for a block whose
560 * header starts at ``freep''. If srchlen is -1 search the whole list.
561 * Return bucket number, or -1 if not found.
562 */
ee0007ab 563static int
8d063cd8 564findbucket(freep, srchlen)
565 union overhead *freep;
566 int srchlen;
567{
568 register union overhead *p;
569 register int i, j;
570
571 for (i = 0; i < NBUCKETS; i++) {
572 j = 0;
573 for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
574 if (p == freep)
575 return (i);
576 j++;
577 }
578 }
579 return (-1);
580}
581
cf5c4ad8 582Malloc_t
583calloc(elements, size)
584 register MEM_SIZE elements;
585 register MEM_SIZE size;
586{
587 long sz = elements * size;
588 Malloc_t p = malloc(sz);
589
590 if (p) {
591 memset((void*)p, 0, sz);
592 }
593 return p;
594}
595
c07a80fd 596#ifdef DEBUGGING_MSTATS
8d063cd8 597/*
598 * mstats - print out statistics about malloc
599 *
600 * Prints two lines of numbers, one showing the length of the free list
601 * for each size category, the second showing the number of mallocs -
602 * frees for each size category.
603 */
ee0007ab 604void
c07a80fd 605dump_mstats(s)
8d063cd8 606 char *s;
607{
608 register int i, j;
609 register union overhead *p;
c07a80fd 610 int topbucket=0, totfree=0, totused=0;
611 u_int nfree[NBUCKETS];
8d063cd8 612
c07a80fd 613 for (i=0; i < NBUCKETS; i++) {
8d063cd8 614 for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
615 ;
c07a80fd 616 nfree[i] = j;
617 totfree += nfree[i] * (1 << (i + 3));
8d063cd8 618 totused += nmalloc[i] * (1 << (i + 3));
c07a80fd 619 if (nfree[i] || nmalloc[i])
620 topbucket = i;
621 }
622 if (s)
760ac839 623 PerlIO_printf(PerlIO_stderr(), "Memory allocation statistics %s (buckets 8..%d)\n",
c07a80fd 624 s, (1 << (topbucket + 3)) );
760ac839 625 PerlIO_printf(PerlIO_stderr(), " %7d free: ", totfree);
c07a80fd 626 for (i=0; i <= topbucket; i++) {
760ac839 627 PerlIO_printf(PerlIO_stderr(), (i<5)?" %5d":" %3d", nfree[i]);
8d063cd8 628 }
760ac839 629 PerlIO_printf(PerlIO_stderr(), "\n %7d used: ", totused);
c07a80fd 630 for (i=0; i <= topbucket; i++) {
760ac839 631 PerlIO_printf(PerlIO_stderr(), (i<5)?" %5d":" %3d", nmalloc[i]);
c07a80fd 632 }
760ac839 633 PerlIO_printf(PerlIO_stderr(), "\n");
cf5c4ad8 634#ifdef PACK_MALLOC
635 if (sbrk_slack || start_slack) {
760ac839 636 PerlIO_printf(PerlIO_stderr(), "Odd ends: %7d bytes from sbrk(), %7d from malloc.\n",
cf5c4ad8 637 sbrk_slack, start_slack);
638 }
639#endif
c07a80fd 640}
641#else
642void
643dump_mstats(s)
644 char *s;
645{
8d063cd8 646}
647#endif
a687059c 648#endif /* lint */
cf5c4ad8 649
650
651#ifdef USE_PERL_SBRK
652
760ac839 653# ifdef NeXT
654# define PERL_SBRK_VIA_MALLOC
655# endif
656
657# ifdef PERL_SBRK_VIA_MALLOC
658# ifdef HIDEMYMALLOC
659# undef malloc
660# else
661# include "Error: -DPERL_SBRK_VIA_MALLOC requires -DHIDEMYMALLOC"
662# endif
cf5c4ad8 663
664/* it may seem schizophrenic to use perl's malloc and let it call system */
665/* malloc, the reason for that is only the 3.2 version of the OS that had */
666/* frequent core dumps within nxzonefreenolock. This sbrk routine put an */
667/* end to the cores */
668
760ac839 669# define SYSTEM_ALLOC(a) malloc(a)
cf5c4ad8 670
760ac839 671# endif /* PERL_SBRK_VIA_MALLOC */
cf5c4ad8 672
673static IV Perl_sbrk_oldchunk;
674static long Perl_sbrk_oldsize;
675
760ac839 676# define PERLSBRK_32_K (1<<15)
677# define PERLSBRK_64_K (1<<16)
cf5c4ad8 678
679char *
680Perl_sbrk(size)
681int size;
682{
683 IV got;
684 int small, reqsize;
685
686 if (!size) return 0;
687#ifdef safemalloc
688 reqsize = size; /* just for the DEBUG_m statement */
689#endif
690 if (size <= Perl_sbrk_oldsize) {
691 got = Perl_sbrk_oldchunk;
692 Perl_sbrk_oldchunk += size;
693 Perl_sbrk_oldsize -= size;
694 } else {
695 if (size >= PERLSBRK_32_K) {
696 small = 0;
697 } else {
698#ifndef safemalloc
699 reqsize = size;
700#endif
701 size = PERLSBRK_64_K;
702 small = 1;
703 }
704 got = (IV)SYSTEM_ALLOC(size);
705 if (small) {
706 /* Chunk is small, register the rest for future allocs. */
707 Perl_sbrk_oldchunk = got + reqsize;
708 Perl_sbrk_oldsize = size - reqsize;
709 }
710 }
711
712#ifdef safemalloc
760ac839 713 DEBUG_m(PerlIO_printf(PerlIO_stderr(), "sbrk malloc size %ld (reqsize %ld), left size %ld, give addr 0x%lx\n",
cf5c4ad8 714 size, reqsize, Perl_sbrk_oldsize, got));
715#endif
716
717 return (void *)got;
718}
719
720#endif /* ! defined USE_PERL_SBRK */