fix AIX hints for PL_* changes
[p5sagit/p5-mst-13.2.git] / malloc.c
index 91815a2..f46c0c0 100644 (file)
--- a/malloc.c
+++ b/malloc.c
@@ -2,6 +2,110 @@
  *
  */
 
+/*
+  Here are some notes on configuring Perl's malloc.
+  There are two macros which serve as bulk disablers of advanced
+  features of this malloc: NO_FANCY_MALLOC, PLAIN_MALLOC (undef by
+  default).  Look in the list of default values below to understand
+  their exact effect.  Defining NO_FANCY_MALLOC returns malloc.c to the
+  state of the malloc in Perl 5.004.  Additionally defining PLAIN_MALLOC
+  returns it to the state as of Perl 5.000.
+
+  Note that some of the settings below may be ignored in the code based
+  on values of other macros.  The PERL_CORE symbol is only defined when
+  perl itself is being compiled (so malloc can make some assumptions
+  about perl's facilities being available to it).
+
+  Each config option has a short description, followed by its name,
+  default value, and a comment about the default (if applicable).  Some
+  options take a precise value, while the others are just boolean.
+  The boolean ones are listed first.
+
+    # Enable code for an emergency memory pool in $^M.  See perlvar.pod
+    # for a description of $^M.
+    PERL_EMERGENCY_SBRK                (!PLAIN_MALLOC && PERL_CORE)
+
+    # Enable code for printing memory statistics.
+    DEBUGGING_MSTATS           (!PLAIN_MALLOC && PERL_CORE)
+
+    # Move allocation info for small buckets into separate areas.
+    # Memory optimization (especially for small allocations, of the
+    # less than 64 bytes).  Since perl usually makes a large number
+    # of small allocations, this is usually a win.
+    PACK_MALLOC                        (!PLAIN_MALLOC && !RCHECK)
+
+    # Add one page to big powers of two when calculating bucket size.
+    # This is targeted at big allocations, as are common in image
+    # processing.
+    TWO_POT_OPTIMIZE           !PLAIN_MALLOC
+    # Use intermediate bucket sizes between powers-of-two.  This is
+    # generally a memory optimization, and a (small) speed pessimization.
+    BUCKETS_ROOT2              !NO_FANCY_MALLOC
+
+    # Do not check small deallocations for bad free().  Memory
+    # and speed optimization, error reporting pessimization.
+    IGNORE_SMALL_BAD_FREE      (!NO_FANCY_MALLOC && !RCHECK)
+
+    # Use table lookup to decide in which bucket a given allocation will go.
+    SMALL_BUCKET_VIA_TABLE     !NO_FANCY_MALLOC
+
+    # Use a perl-defined sbrk() instead of the (presumably broken or
+    # missing) system-supplied sbrk().
+    USE_PERL_SBRK              undef
+
+    # Use system malloc() (or calloc() etc.) to emulate sbrk(). Normally
+    # only used with broken sbrk()s.
+    PERL_SBRK_VIA_MALLOC       undef
+
+    # Which allocator to use if PERL_SBRK_VIA_MALLOC
+    SYSTEM_ALLOC(a)            malloc(a)
+
+    # Disable memory overwrite checking with DEBUGGING.  Memory and speed
+    # optimization, error reporting pessimization.
+    NO_RCHECK                  undef
+
+    # Enable memory overwrite checking with DEBUGGING.  Memory and speed
+    # pessimization, error reporting optimization
+    RCHECK                     (DEBUGGING && !NO_RCHECK)
+
+    # Failed allocations bigger than this size croak (if
+    # PERL_EMERGENCY_SBRK is enabled) without touching $^M.  See
+    # perlvar.pod for a description of $^M.
+    BIG_SIZE                    (1<<16)        # 64K
+
+    # Starting from this power of two, add an extra page to the
+    # size of the bucket. This enables optimized allocations of sizes
+    # close to powers of 2.  Note that the value is indexed at 0.
+    FIRST_BIG_POW2             15              # 32K, 16K is used too often
+
+    # Estimate of minimal memory footprint.  malloc uses this value to
+    # request the most reasonable largest blocks of memory from the system.
+    FIRST_SBRK                         (48*1024)
+
+    # Round up sbrk()s to multiples of this.
+    MIN_SBRK                   2048
+
+    # Round up sbrk()s to multiples of this percent of footprint.
+    MIN_SBRK_FRAC              3
+
+    # Add this much memory to big powers of two to get the bucket size.
+    PERL_PAGESIZE              4096
+
+    # This many sbrk() discontinuities should be tolerated even
+    # from the start without deciding that sbrk() is usually
+    # discontinuous.
+    SBRK_ALLOW_FAILURES                3
+
+    # This many continuous sbrk()s compensate for one discontinuous one.
+    SBRK_FAILURE_PRICE         50
+
+  This implementation assumes that calling PerlIO_printf() does not
+  result in any memory allocation calls (used during a panic).
+
+ */
+
 #ifndef NO_FANCY_MALLOC
 #  ifndef SMALL_BUCKET_VIA_TABLE
 #    define SMALL_BUCKET_VIA_TABLE
 
 #ifdef DEBUGGING
 #  undef DEBUG_m
-#  define DEBUG_m(a)  if (debug & 128)   a
+#  define DEBUG_m(a)  if (PL_debug & 128)   a
 #endif
 
 /* I don't much care whether these are defined in sys/types.h--LAW */
@@ -207,6 +311,19 @@ static int findbucket _((union overhead *freep, int srchlen));
 #  define BUCKETS_PER_POW2 1
 #endif 
 
+#if !defined(MEM_ALIGNBYTES) || ((MEM_ALIGNBYTES > 4) && !defined(STRICT_ALIGNMENT))
+/* Figure out the alignment of void*. */
+struct aligner {
+  char c;
+  void *p;
+};
+#  define ALIGN_SMALL ((int)((caddr_t)&(((struct aligner*)0)->p)))
+#else
+#  define ALIGN_SMALL MEM_ALIGNBYTES
+#endif
+
+#define IF_ALIGN_8(yes,no)     ((ALIGN_SMALL>4) ? (yes) : (no))
+
 #ifdef BUCKETS_ROOT2
 #  define MAX_BUCKET_BY_TABLE 13
 static u_short buck_size[MAX_BUCKET_BY_TABLE + 1] = 
@@ -351,7 +468,7 @@ static char bucket_of[] =
       /* 0 to 15 in 4-byte increments. */
       (sizeof(void*) > 4 ? 6 : 5),     /* 4/8, 5-th bucket for better reports */
       6,                               /* 8 */
-      7, 8,                            /* 12, 16 */
+      IF_ALIGN_8(8,7), 8,              /* 16/12, 16 */
       9, 9, 10, 10,                    /* 24, 32 */
       11, 11, 11, 11,                  /* 48 */
       12, 12, 12, 12,                  /* 64 */
@@ -456,25 +573,25 @@ emergency_sbrk(size)
 {
     if (size >= BIG_SIZE) {
        /* Give the possibility to recover: */
-       MUTEX_UNLOCK(&malloc_mutex);
-       croak("Out of memory during request for %i bytes", size);
+       MUTEX_UNLOCK(&PL_malloc_mutex);
+       croak("Out of memory during \"large\" request for %i bytes", size);
     }
 
     if (!emergency_buffer) {           
        dTHR;
        /* First offense, give a possibility to recover by dieing. */
        /* No malloc involved here: */
-       GV **gvp = (GV**)hv_fetch(defstash, "^M", 2, 0);
+       GV **gvp = (GV**)hv_fetch(PL_defstash, "^M", 2, 0);
        SV *sv;
        char *pv;
 
-       if (!gvp) gvp = (GV**)hv_fetch(defstash, "\015", 1, 0);
+       if (!gvp) gvp = (GV**)hv_fetch(PL_defstash, "\015", 1, 0);
        if (!gvp || !(sv = GvSV(*gvp)) || !SvPOK(sv) 
            || (SvLEN(sv) < (1<<LOG_OF_MIN_ARENA) - M_OVERHEAD)) 
            return (char *)-1;          /* Now die die die... */
 
        /* Got it, now detach SvPV: */
-       pv = SvPV(sv, na);
+       pv = SvPV(sv, PL_na);
        /* Check alignment: */
        if (((u_bigint)(pv - M_OVERHEAD)) & ((1<<LOG_OF_MIN_ARENA) - 1)) {
            PerlIO_puts(PerlIO_stderr(),"Bad alignment of $^M!\n");
@@ -485,7 +602,7 @@ emergency_sbrk(size)
        emergency_buffer_size = SvLEN(sv) + M_OVERHEAD;
        SvPOK_off(sv);
        SvREADONLY_on(sv);
-       MUTEX_UNLOCK(&malloc_mutex);
+       MUTEX_UNLOCK(&PL_malloc_mutex);
        croak("Out of memory during request for %i bytes", size);
     }
     else if (emergency_buffer_size >= size) {
@@ -562,7 +679,7 @@ malloc(register size_t nbytes)
                croak("%s", "panic: malloc");
 #endif
 
-       MUTEX_LOCK(&malloc_mutex);
+       MUTEX_LOCK(&PL_malloc_mutex);
        /*
         * Convert amount of memory requested into
         * closest block size stored in hash buckets
@@ -601,9 +718,9 @@ malloc(register size_t nbytes)
        if (nextf[bucket] == NULL)    
                morecore(bucket);
        if ((p = nextf[bucket]) == NULL) {
-               MUTEX_UNLOCK(&malloc_mutex);
+               MUTEX_UNLOCK(&PL_malloc_mutex);
 #ifdef PERL_CORE
-               if (!nomemok) {
+               if (!PL_nomemok) {
                    PerlIO_puts(PerlIO_stderr(),"Out of memory!\n");
                    my_exit(1);
                }
@@ -614,12 +731,12 @@ malloc(register size_t nbytes)
 
        DEBUG_m(PerlIO_printf(Perl_debug_log,
                              "0x%lx: (%05lu) malloc %ld bytes\n",
-                             (unsigned long)(p+1), (unsigned long)(an++),
+                             (unsigned long)(p+1), (unsigned long)(PL_an++),
                              (long)size));
 
        /* remove from linked list */
-#ifdef RCHECK
-       if (*((int*)p) & (sizeof(union overhead) - 1))
+#if defined(RCHECK)
+       if (((UV)p) & (MEM_ALIGNBYTES - 1))
            PerlIO_printf(PerlIO_stderr(), "Corrupt malloc ptr 0x%lx at 0x%lx\n",
                (unsigned long)*((int*)p),(unsigned long)p);
 #endif
@@ -651,7 +768,7 @@ malloc(register size_t nbytes)
            *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
        }
 #endif
-       MUTEX_UNLOCK(&malloc_mutex);
+       MUTEX_UNLOCK(&PL_malloc_mutex);
        return ((Malloc_t)(p + CHUNK_SHIFT));
 }
 
@@ -836,7 +953,7 @@ getpages(int needed, int *nblksp, int bucket)
                                      "failed to fix bad sbrk()\n"));
 #ifdef PACK_MALLOC
                if (slack) {
-                   MUTEX_UNLOCK(&malloc_mutex);
+                   MUTEX_UNLOCK(&PL_malloc_mutex);
                    croak("%s", "panic: Off-page sbrk");
                }
 #endif
@@ -946,7 +1063,7 @@ morecore(register int bucket)
        if (nextf[bucket])
                return;
        if (bucket == sizeof(MEM_SIZE)*8*BUCKETS_PER_POW2) {
-           MUTEX_UNLOCK(&malloc_mutex);
+           MUTEX_UNLOCK(&PL_malloc_mutex);
            croak("%s", "Out of memory during ridiculously large request");
        }
        if (bucket > max_bucket)
@@ -1044,7 +1161,7 @@ free(void *mp)
 
        DEBUG_m(PerlIO_printf(Perl_debug_log, 
                              "0x%lx: (%05lu) free\n",
-                             (unsigned long)cp, (unsigned long)(an++)));
+                             (unsigned long)cp, (unsigned long)(PL_an++)));
 
        if (cp == NULL)
                return;
@@ -1075,7 +1192,7 @@ free(void *mp)
 #endif
                return;                         /* sanity */
            }
-       MUTEX_LOCK(&malloc_mutex);
+       MUTEX_LOCK(&PL_malloc_mutex);
 #ifdef RCHECK
        ASSERT(ovp->ov_rmagic == RMAGIC, "chunk's head overwrite");
        if (OV_INDEX(ovp) <= MAX_SHORT_BUCKET) {
@@ -1098,7 +1215,7 @@ free(void *mp)
        size = OV_INDEX(ovp);
        ovp->ov_next = nextf[size];
        nextf[size] = ovp;
-       MUTEX_UNLOCK(&malloc_mutex);
+       MUTEX_UNLOCK(&PL_malloc_mutex);
 }
 
 /*
@@ -1136,7 +1253,7 @@ realloc(void *mp, size_t nbytes)
        if (!cp)
                return malloc(nbytes);
 
-       MUTEX_LOCK(&malloc_mutex);
+       MUTEX_LOCK(&PL_malloc_mutex);
        ovp = (union overhead *)((caddr_t)cp 
                                - sizeof (union overhead) * CHUNK_SHIFT);
        bucket = OV_INDEX(ovp);
@@ -1234,7 +1351,7 @@ realloc(void *mp, size_t nbytes)
                }
 #endif
                res = cp;
-               MUTEX_UNLOCK(&malloc_mutex);
+               MUTEX_UNLOCK(&PL_malloc_mutex);
        } else if (incr == 1 && (cp - M_OVERHEAD == last_op) 
                   && (onb > (1 << LOG_OF_MIN_ARENA))) {
            MEM_SIZE require, newarena = nbytes, pow;
@@ -1262,7 +1379,7 @@ realloc(void *mp, size_t nbytes)
                goto hard_way;
        } else {
          hard_way:
-           MUTEX_UNLOCK(&malloc_mutex);
+           MUTEX_UNLOCK(&PL_malloc_mutex);
            if ((res = (char*)malloc(nbytes)) == NULL)
                return (NULL);
            if (cp != res)                      /* common optimization */
@@ -1272,10 +1389,10 @@ realloc(void *mp, size_t nbytes)
        }
 
        DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%lu: (%05lu) rfree\n",
-                             (unsigned long)res,(unsigned long)(an++)));
+                             (unsigned long)res,(unsigned long)(PL_an++)));
        DEBUG_m(PerlIO_printf(Perl_debug_log, 
                              "0x%lx: (%05lu) realloc %ld bytes\n",
-                             (unsigned long)res,(unsigned long)(an++),
+                             (unsigned long)res,(unsigned long)(PL_an++),
                              (long)size));
        return ((Malloc_t)res);
 }
@@ -1317,8 +1434,18 @@ calloc(register size_t elements, register size_t size)
 MEM_SIZE
 malloced_size(void *p)
 {
-    int bucket = OV_INDEX((union overhead *)p);
-
+    union overhead *ovp = (union overhead *)
+       ((caddr_t)p - sizeof (union overhead) * CHUNK_SHIFT);
+    int bucket = OV_INDEX(ovp);
+#ifdef RCHECK
+    /* The caller wants to have a complete control over the chunk,
+       disable the memory checking inside the chunk.  */
+    if (bucket <= MAX_SHORT_BUCKET) {
+       MEM_SIZE size = BUCKET_SIZE_REAL(bucket);
+       ovp->ov_size = size + M_OVERHEAD - 1;
+       *((u_int *)((caddr_t)ovp + size + M_OVERHEAD - RSLOP)) = RMAGIC;
+    }
+#endif
     return BUCKET_SIZE_REAL(bucket);
 }
 
@@ -1423,9 +1550,27 @@ dump_mstats(char *s)
 #      define PERL_SBRK_VIA_MALLOC
 #   endif
 
+#   ifdef __MACHTEN_PPC__
+#      define PERL_SBRK_VIA_MALLOC
+/*
+ * MachTen's malloc() returns a buffer aligned on a two-byte boundary.
+ * While this is adequate, it may slow down access to longer data
+ * types by forcing multiple memory accesses.  It also causes
+ * complaints when RCHECK is in force.  So we allocate six bytes
+ * more than we need to, and return an address rounded up to an
+ * eight-byte boundary.
+ *
+ * 980701 Dominic Dunlop <domo@computer.org>
+ */
+#      define SYSTEM_ALLOC(a) ((void *)(((unsigned)malloc((a)+6)+6)&~7))
+#   endif
+
 #   ifdef PERL_SBRK_VIA_MALLOC
 #      if defined(HIDEMYMALLOC) || defined(EMBEDMYMALLOC)
-#         undef malloc
+#         undef malloc         /* Expose names that  */
+#         undef calloc         /* HIDEMYMALLOC hides */
+#         undef realloc
+#         undef free
 #      else
 #         include "Error: -DPERL_SBRK_VIA_MALLOC needs -D(HIDE|EMBED)MYMALLOC"
 #      endif
@@ -1435,7 +1580,9 @@ dump_mstats(char *s)
 /* frequent core dumps within nxzonefreenolock. This sbrk routine put an */
 /* end to the cores */
 
-#      define SYSTEM_ALLOC(a) malloc(a)
+#      ifndef SYSTEM_ALLOC
+#         define SYSTEM_ALLOC(a) malloc(a)
+#      endif
 
 #   endif  /* PERL_SBRK_VIA_MALLOC */