52b23aef5e89849a7031d3729c9ea38ca363754b
[platform/upstream/bash.git] / lib / malloc / stats.c
1 /* stats.c - malloc statistics */
2
3 /*  Copyright (C) 2001 Free Software Foundation, Inc.
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2, or (at your option)
8     any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
18
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22
23 #include "imalloc.h"
24
25 #ifdef MALLOC_STATS
26
27 #include <stdio.h>
28 #ifdef HAVE_UNISTD_H
29 #  include <unistd.h>
30 #endif
31
32 #include "mstats.h"
33
34 extern int malloc_free_blocks __P((int));
35
36 extern struct _malstats _mstats;
37
38 struct bucket_stats
39 malloc_bucket_stats (size)
40      int size;
41 {
42   struct bucket_stats v;
43
44   v.nfree = 0;
45
46   if (size < 0 || size >= NBUCKETS)
47     {
48       v.blocksize = 0;
49       v.nused = v.nmal = v.nmorecore = v.nlesscore = v.nsplit = 0;
50       return v;
51     }
52
53   v.blocksize = 1 << (size + 3);
54   v.nused = _mstats.nmalloc[size];
55   v.nmal = _mstats.tmalloc[size];
56   v.nmorecore = _mstats.nmorecore[size];
57   v.nlesscore = _mstats.nlesscore[size];
58   v.nsplit = _mstats.nsplit[size];
59   v.ncoalesce = _mstats.ncoalesce[size];
60
61   v.nfree = malloc_free_blocks (size);  /* call back to malloc.c */
62
63   return v;
64 }
65
66 /* Return a copy of _MSTATS, with two additional fields filled in:
67    BYTESFREE is the total number of bytes on free lists.  BYTESUSED
68    is the total number of bytes in use.  These two fields are fairly
69    expensive to compute, so we do it only when asked to. */
70 struct _malstats
71 malloc_stats ()
72 {
73   struct _malstats result;
74   struct bucket_stats v;
75   register int i;
76
77   result = _mstats;
78   result.bytesused = result.bytesfree = 0;
79   for (i = 0; i < NBUCKETS; i++)
80     {
81       v = malloc_bucket_stats (i);
82       result.bytesfree += v.nfree * v.blocksize;
83       result.bytesused += v.nused * v.blocksize;
84     }
85   return (result);
86 }
87
88 static void
89 _print_malloc_stats (s, fp)
90      char *s;
91      FILE *fp;
92 {
93   register int i;
94   unsigned long totused, totfree;
95   struct bucket_stats v;
96
97   fprintf (fp, "Memory allocation statistics: %s\n    size\tfree\tin use\ttotal\tmorecore lesscore split\tcoalesce\n", s ? s : "");
98   for (i = totused = totfree = 0; i < NBUCKETS; i++)
99     {
100       v = malloc_bucket_stats (i);
101       if (v.nmal > 0)
102         fprintf (fp, "%8lu\t%4d\t%6d\t%5d\t%8d\t%d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce);
103       totfree += v.nfree * v.blocksize;
104       totused += v.nused * v.blocksize;
105     }
106   fprintf (fp, "\nTotal bytes in use: %lu, total bytes free: %lu\n",
107            totused, totfree);
108   fprintf (fp, "\nTotal bytes requested by application: %lu\n", _mstats.bytesreq);
109   fprintf (fp, "Total mallocs: %d, total frees: %d, total reallocs: %d (%d copies)\n",
110            _mstats.nmal, _mstats.nfre, _mstats.nrealloc, _mstats.nrcopy);
111   fprintf (fp, "Total sbrks: %d, total bytes via sbrk: %d\n",
112            _mstats.nsbrk, _mstats.tsbrk);
113   fprintf (fp, "Total blocks split: %d, total block coalesces: %d\n",
114            _mstats.tbsplit, _mstats.tbcoalesce);
115 }
116
117 void
118 print_malloc_stats (s)
119      char *s;
120 {
121   _print_malloc_stats (s, stderr);
122 }
123
124 void
125 fprint_malloc_stats (s, fp)
126      char *s;
127      FILE *fp;
128 {
129   _print_malloc_stats (s, fp);
130 }
131
132 #define TRACEROOT "/var/tmp/maltrace/trace."
133 static char mallbuf[1024];
134
135 void
136 trace_malloc_stats (s, fn)
137      char *s, *fn;
138 {
139   char defname[sizeof (TRACEROOT) + 64];
140   char fname[1024];
141   long l;
142   FILE *fp;
143
144   l = (long)getpid ();
145   if (fn == 0)
146     {
147       sprintf (defname, "%s%ld", TRACEROOT, l);  
148       fp = fopen(defname, "w");
149     }
150   else
151     {
152       char *p, *q, *r;
153       char pidbuf[32];
154       int sp;
155
156       sprintf (pidbuf, "%ld", l);
157       if ((strlen (pidbuf) + strlen (fn) + 2) >= sizeof (fname))
158         return;
159       for (sp = 0, p = fname, q = fn; *q; )
160         {
161           if (sp == 0 && *q == '%' && q[1] == 'p')
162             {
163               sp = 1;
164               for (r = pidbuf; *r; )
165                 *p++ = *r++;
166               q += 2;
167             }
168           else
169             *p++ = *q++;
170         }
171       *p = '\0';
172       fp = fopen (fname, "w");
173     }
174         
175   if (fp)
176     {
177       setvbuf (fp, mallbuf, _IOFBF, sizeof (mallbuf));
178       _print_malloc_stats (s, fp);
179       fflush(fp);
180       fclose(fp);
181     }
182 }
183
184 #endif /* MALLOC_STATS */