get Compiler "working" under useithreads
[p5sagit/p5-mst-13.2.git] / malloc.c
index 664fbe7..9c6a6d8 100644 (file)
--- a/malloc.c
+++ b/malloc.c
     } STMT_END
 #endif
 
+#ifdef PERL_IMPLICIT_CONTEXT
+#  define PERL_IS_ALIVE                aTHX
+#else
+#  define PERL_IS_ALIVE                TRUE
+#endif
+    
+
 /*
  * Layout of memory:
  * ~~~~~~~~~~~~~~~~
@@ -916,6 +923,10 @@ emergency_sbrk(MEM_SIZE size)
 #define        NBUCKETS (32*BUCKETS_PER_POW2 + 1)
 static union overhead *nextf[NBUCKETS];
 
+#if defined(PURIFY) && !defined(USE_PERL_SBRK)
+#  define USE_PERL_SBRK
+#endif
+
 #ifdef USE_PERL_SBRK
 #define sbrk(a) Perl_sbrk(a)
 Malloc_t Perl_sbrk (int size);
@@ -947,7 +958,7 @@ static      u_int goodsbrk;
 static void
 botch(char *diag, char *s)
 {
-       dTHXo;
+       dTHX;
        PerlIO_printf(PerlIO_stderr(), "assertion botched (%s?): %s\n", diag, s);
        PerlProc_abort();
 }
@@ -1032,13 +1043,13 @@ Perl_malloc(register size_t nbytes)
        /* remove from linked list */
 #if defined(RCHECK)
        if ((PTR2UV(p)) & (MEM_ALIGNBYTES - 1)) {
-           dTHXo;
+           dTHX;
            PerlIO_printf(PerlIO_stderr(),
                          "Unaligned pointer in the free chain 0x%"UVxf"\n",
                          PTR2UV(p));
        }
        if ((PTR2UV(p->ov_next)) & (MEM_ALIGNBYTES - 1)) {
-           dTHXo;
+           dTHX;
            PerlIO_printf(PerlIO_stderr(),
                          "Unaligned `next' pointer in the free "
                          "chain 0x"UVxf" at 0x%"UVxf"\n",
@@ -1502,18 +1513,36 @@ Perl_mfree(void *mp)
            {
                static int bad_free_warn = -1;
                if (bad_free_warn == -1) {
-                   dTHXo;
+                   dTHX;
                    char *pbf = PerlEnv_getenv("PERL_BADFREE");
                    bad_free_warn = (pbf) ? atoi(pbf) : 1;
                }
                if (!bad_free_warn)
                    return;
 #ifdef RCHECK
+#ifdef PERL_CORE
+               {
+                   dTHX;
+                   if (!PERL_IS_ALIVE || !PL_curcop || ckWARN_d(WARN_MALLOC))
+                       Perl_warner(aTHX_ WARN_MALLOC, "%s free() ignored",
+                                   ovp->ov_rmagic == RMAGIC - 1 ?
+                                   "Duplicate" : "Bad");
+               }
+#else
                warn("%s free() ignored",
                    ovp->ov_rmagic == RMAGIC - 1 ? "Duplicate" : "Bad");
+#endif         
+#else
+#ifdef PERL_CORE
+               {
+                   dTHX;
+                   if (!PERL_IS_ALIVE || !PL_curcop || ckWARN_d(WARN_MALLOC))
+                       Perl_warner(aTHX_ WARN_MALLOC, "%s", "Bad free() ignored");
+               }
 #else
                warn("%s", "Bad free() ignored");
 #endif
+#endif
                return;                         /* sanity */
            }
 #ifdef RCHECK
@@ -1584,19 +1613,39 @@ Perl_realloc(void *mp, size_t nbytes)
            {
                static int bad_free_warn = -1;
                if (bad_free_warn == -1) {
-                   dTHXo;
+                   dTHX;
                    char *pbf = PerlEnv_getenv("PERL_BADFREE");
                    bad_free_warn = (pbf) ? atoi(pbf) : 1;
                }
                if (!bad_free_warn)
                    return Nullch;
 #ifdef RCHECK
+#ifdef PERL_CORE
+               {
+                   dTHX;
+                   if (!PERL_IS_ALIVE || !PL_curcop || ckWARN_d(WARN_MALLOC))
+                       Perl_warner(aTHX_ WARN_MALLOC, "%srealloc() %signored",
+                                   (ovp->ov_rmagic == RMAGIC - 1 ? "" : "Bad "),
+                                   ovp->ov_rmagic == RMAGIC - 1
+                                   ? "of freed memory " : "");
+               }
+#else
                warn("%srealloc() %signored",
                    (ovp->ov_rmagic == RMAGIC - 1 ? "" : "Bad "),
                     ovp->ov_rmagic == RMAGIC - 1 ? "of freed memory " : "");
+#endif
+#else
+#ifdef PERL_CORE
+               {
+                   dTHX;
+                   if (!PERL_IS_ALIVE || !PL_curcop || ckWARN_d(WARN_MALLOC))
+                       Perl_warner(aTHX_ WARN_MALLOC, "%s",
+                                   "Bad realloc() ignored");
+               }
 #else
                warn("%s", "Bad realloc() ignored");
 #endif
+#endif
                return Nullch;                  /* sanity */
            }
 
@@ -1814,95 +1863,134 @@ Perl_malloced_size(void *p)
 #  else
 #    define MIN_EVEN_REPORT MIN_BUCKET
 #  endif 
-/*
- * mstats - print out statistics about malloc
- * 
- * Prints two lines of numbers, one showing the length of the free list
- * for each size category, the second showing the number of mallocs -
- * frees for each size category.
- */
-void
-Perl_dump_mstats(pTHX_ char *s)
+
+int
+Perl_get_mstats(pTHX_ perl_mstats_t *buf, int buflen, int level)
 {
 #ifdef DEBUGGING_MSTATS
        register int i, j;
        register union overhead *p;
-       int topbucket=0, topbucket_ev=0, topbucket_odd=0, totfree=0, total=0;
-       u_int nfree[NBUCKETS];
-       int total_chain = 0;
        struct chunk_chain_s* nextchain;
 
+       buf->topbucket = buf->topbucket_ev = buf->topbucket_odd 
+           = buf->totfree = buf->total = buf->total_chain = 0;
+
+       buf->minbucket = MIN_BUCKET;
        MALLOC_LOCK;
        for (i = MIN_BUCKET ; i < NBUCKETS; i++) {
                for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
                        ;
-               nfree[i] = j;
-               totfree += nfree[i] * BUCKET_SIZE_REAL(i);
-               total += nmalloc[i] * BUCKET_SIZE_REAL(i);
+               if (i < buflen) {
+                   buf->nfree[i] = j;
+                   buf->ntotal[i] = nmalloc[i];
+               }               
+               buf->totfree += j * BUCKET_SIZE_REAL(i);
+               buf->total += nmalloc[i] * BUCKET_SIZE_REAL(i);
                if (nmalloc[i]) {
-                   i % 2 ? (topbucket_odd = i) : (topbucket_ev = i);
-                   topbucket = i;
+                   i % 2 ? (buf->topbucket_odd = i) : (buf->topbucket_ev = i);
+                   buf->topbucket = i;
                }
        }
        nextchain = chunk_chain;
        while (nextchain) {
-           total_chain += nextchain->size;
+           buf->total_chain += nextchain->size;
            nextchain = nextchain->next;
        }
+       buf->total_sbrk = goodsbrk + sbrk_slack;
+       buf->sbrks = sbrks;
+       buf->sbrk_good = sbrk_good;
+       buf->sbrk_slack = sbrk_slack;
+       buf->start_slack = start_slack;
+       buf->sbrked_remains = sbrked_remains;
        MALLOC_UNLOCK;
+       if (level) {
+           for (i = MIN_BUCKET ; i < NBUCKETS; i++) {
+               if (i >= buflen)
+                   break;
+               buf->bucket_mem_size[i] = BUCKET_SIZE(i);
+               buf->bucket_available_size[i] = BUCKET_SIZE_REAL(i);
+           }
+       }
+#endif /* defined DEBUGGING_MSTATS */
+       return 0;               /* XXX unused */
+}
+/*
+ * mstats - print out statistics about malloc
+ * 
+ * Prints two lines of numbers, one showing the length of the free list
+ * for each size category, the second showing the number of mallocs -
+ * frees for each size category.
+ */
+void
+Perl_dump_mstats(pTHX_ char *s)
+{
+#ifdef DEBUGGING_MSTATS
+       register int i, j;
+       register union overhead *p;
+       perl_mstats_t buffer;
+       unsigned long nf[NBUCKETS];
+       unsigned long nt[NBUCKETS];
+       struct chunk_chain_s* nextchain;
+
+       buffer.nfree  = nf;
+       buffer.ntotal = nt;
+       get_mstats(&buffer, NBUCKETS, 0);
+
        if (s)
            PerlIO_printf(Perl_error_log,
                          "Memory allocation statistics %s (buckets %ld(%ld)..%ld(%ld)\n",
                          s, 
                          (long)BUCKET_SIZE_REAL(MIN_BUCKET), 
                          (long)BUCKET_SIZE(MIN_BUCKET),
-                         (long)BUCKET_SIZE_REAL(topbucket), (long)BUCKET_SIZE(topbucket));
-       PerlIO_printf(Perl_error_log, "%8d free:", totfree);
-       for (i = MIN_EVEN_REPORT; i <= topbucket; i += BUCKETS_PER_POW2) {
+                         (long)BUCKET_SIZE_REAL(buffer.topbucket), 
+                         (long)BUCKET_SIZE(buffer.topbucket));
+       PerlIO_printf(Perl_error_log, "%8d free:", buffer.totfree);
+       for (i = MIN_EVEN_REPORT; i <= buffer.topbucket; i += BUCKETS_PER_POW2) {
                PerlIO_printf(Perl_error_log, 
                              ((i < 8*BUCKETS_PER_POW2 || i == 10*BUCKETS_PER_POW2)
                               ? " %5d" 
                               : ((i < 12*BUCKETS_PER_POW2) ? " %3d" : " %d")),
-                             nfree[i]);
+                             buffer.nfree[i]);
        }
 #ifdef BUCKETS_ROOT2
        PerlIO_printf(Perl_error_log, "\n\t   ");
-       for (i = MIN_BUCKET + 1; i <= topbucket_odd; i += BUCKETS_PER_POW2) {
+       for (i = MIN_BUCKET + 1; i <= buffer.topbucket_odd; i += BUCKETS_PER_POW2) {
                PerlIO_printf(Perl_error_log, 
                              ((i < 8*BUCKETS_PER_POW2 || i == 10*BUCKETS_PER_POW2)
                               ? " %5d" 
                               : ((i < 12*BUCKETS_PER_POW2) ? " %3d" : " %d")),
-                             nfree[i]);
+                             buffer.nfree[i]);
        }
 #endif 
-       PerlIO_printf(Perl_error_log, "\n%8d used:", total - totfree);
-       for (i = MIN_EVEN_REPORT; i <= topbucket; i += BUCKETS_PER_POW2) {
+       PerlIO_printf(Perl_error_log, "\n%8d used:", buffer.total - buffer.totfree);
+       for (i = MIN_EVEN_REPORT; i <= buffer.topbucket; i += BUCKETS_PER_POW2) {
                PerlIO_printf(Perl_error_log, 
                              ((i < 8*BUCKETS_PER_POW2 || i == 10*BUCKETS_PER_POW2)
                               ? " %5d" 
                               : ((i < 12*BUCKETS_PER_POW2) ? " %3d" : " %d")), 
-                             nmalloc[i] - nfree[i]);
+                             buffer.ntotal[i] - buffer.nfree[i]);
        }
 #ifdef BUCKETS_ROOT2
        PerlIO_printf(Perl_error_log, "\n\t   ");
-       for (i = MIN_BUCKET + 1; i <= topbucket_odd; i += BUCKETS_PER_POW2) {
+       for (i = MIN_BUCKET + 1; i <= buffer.topbucket_odd; i += BUCKETS_PER_POW2) {
                PerlIO_printf(Perl_error_log, 
                              ((i < 8*BUCKETS_PER_POW2 || i == 10*BUCKETS_PER_POW2)
                               ? " %5d" 
                               : ((i < 12*BUCKETS_PER_POW2) ? " %3d" : " %d")),
-                             nmalloc[i] - nfree[i]);
+                             buffer.ntotal[i] - buffer.nfree[i]);
        }
 #endif 
        PerlIO_printf(Perl_error_log, "\nTotal sbrk(): %d/%d:%d. Odd ends: pad+heads+chain+tail: %d+%d+%d+%d.\n",
-                     goodsbrk + sbrk_slack, sbrks, sbrk_good, sbrk_slack,
-                     start_slack, total_chain, sbrked_remains);
+                     buffer.total_sbrk, buffer.sbrks, buffer.sbrk_good,
+                     buffer.sbrk_slack, buffer.start_slack,
+                     buffer.total_chain, buffer.sbrked_remains);
 #endif /* DEBUGGING_MSTATS */
 }
 #endif /* lint */
 
 #ifdef USE_PERL_SBRK
 
-#   if defined(__MACHTEN_PPC__) || defined(NeXT) || defined(__NeXT__)
+#   if defined(__MACHTEN_PPC__) || defined(NeXT) || defined(__NeXT__) || defined(PURIFY)
 #      define PERL_SBRK_VIA_MALLOC
 /*
  * MachTen's malloc() returns a buffer aligned on a two-byte boundary.