1*84d9c625SLionel Sambuc /* $NetBSD: xmalloc.c,v 1.12 2013/01/24 17:57:29 christos Exp $ */
2e83f7ba2SBen Gras
3e83f7ba2SBen Gras /*
4e83f7ba2SBen Gras * Copyright 1996 John D. Polstra.
5e83f7ba2SBen Gras * Copyright 1996 Matt Thomas <matt@3am-software.com>
6e83f7ba2SBen Gras * All rights reserved.
7e83f7ba2SBen Gras *
8e83f7ba2SBen Gras * Redistribution and use in source and binary forms, with or without
9e83f7ba2SBen Gras * modification, are permitted provided that the following conditions
10e83f7ba2SBen Gras * are met:
11e83f7ba2SBen Gras * 1. Redistributions of source code must retain the above copyright
12e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer.
13e83f7ba2SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
14e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer in the
15e83f7ba2SBen Gras * documentation and/or other materials provided with the distribution.
16e83f7ba2SBen Gras * 3. All advertising materials mentioning features or use of this software
17e83f7ba2SBen Gras * must display the following acknowledgement:
18e83f7ba2SBen Gras * This product includes software developed by John Polstra.
19e83f7ba2SBen Gras * 4. The name of the author may not be used to endorse or promote products
20e83f7ba2SBen Gras * derived from this software without specific prior written permission.
21e83f7ba2SBen Gras *
22e83f7ba2SBen Gras * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23e83f7ba2SBen Gras * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24e83f7ba2SBen Gras * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25e83f7ba2SBen Gras * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26e83f7ba2SBen Gras * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27e83f7ba2SBen Gras * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28e83f7ba2SBen Gras * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29e83f7ba2SBen Gras * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30e83f7ba2SBen Gras * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31e83f7ba2SBen Gras * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32e83f7ba2SBen Gras */
33e83f7ba2SBen Gras
34e83f7ba2SBen Gras /*
35e83f7ba2SBen Gras * Copyright (c) 1983 Regents of the University of California.
36e83f7ba2SBen Gras * All rights reserved.
37e83f7ba2SBen Gras *
38e83f7ba2SBen Gras * Redistribution and use in source and binary forms, with or without
39e83f7ba2SBen Gras * modification, are permitted provided that the following conditions
40e83f7ba2SBen Gras * are met:
41e83f7ba2SBen Gras * 1. Redistributions of source code must retain the above copyright
42e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer.
43e83f7ba2SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
44e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer in the
45e83f7ba2SBen Gras * documentation and/or other materials provided with the distribution.
46e83f7ba2SBen Gras * 3. Neither the name of the University nor the names of its contributors
47e83f7ba2SBen Gras * may be used to endorse or promote products derived from this software
48e83f7ba2SBen Gras * without specific prior written permission.
49e83f7ba2SBen Gras *
50e83f7ba2SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51e83f7ba2SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52e83f7ba2SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53e83f7ba2SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54e83f7ba2SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55e83f7ba2SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56e83f7ba2SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57e83f7ba2SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58e83f7ba2SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59e83f7ba2SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60e83f7ba2SBen Gras * SUCH DAMAGE.
61e83f7ba2SBen Gras */
62e83f7ba2SBen Gras
63e83f7ba2SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
64e83f7ba2SBen Gras /*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/
65e83f7ba2SBen Gras #endif /* LIBC_SCCS and not lint */
66e83f7ba2SBen Gras
67e83f7ba2SBen Gras /*
68e83f7ba2SBen Gras * malloc.c (Caltech) 2/21/82
69e83f7ba2SBen Gras * Chris Kingsley, kingsley@cit-20.
70e83f7ba2SBen Gras *
71e83f7ba2SBen Gras * This is a very fast storage allocator. It allocates blocks of a small
72e83f7ba2SBen Gras * number of different sizes, and keeps free lists of each size. Blocks that
73e83f7ba2SBen Gras * don't exactly fit are passed up to the next larger size. In this
74e83f7ba2SBen Gras * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long.
75e83f7ba2SBen Gras * This is designed for use in a virtual memory environment.
76e83f7ba2SBen Gras */
77e83f7ba2SBen Gras
78e83f7ba2SBen Gras #include <sys/cdefs.h>
79e83f7ba2SBen Gras #ifndef lint
80*84d9c625SLionel Sambuc __RCSID("$NetBSD: xmalloc.c,v 1.12 2013/01/24 17:57:29 christos Exp $");
81e83f7ba2SBen Gras #endif /* not lint */
82e83f7ba2SBen Gras
83e83f7ba2SBen Gras #include <stdlib.h>
84e83f7ba2SBen Gras #include <string.h>
85e83f7ba2SBen Gras #include <unistd.h>
86e83f7ba2SBen Gras #include <errno.h>
87e83f7ba2SBen Gras
88e83f7ba2SBen Gras #include <sys/types.h>
89e83f7ba2SBen Gras #include <sys/param.h>
90e83f7ba2SBen Gras #include <sys/mman.h>
91e83f7ba2SBen Gras #include <sys/stat.h>
92e83f7ba2SBen Gras
93e83f7ba2SBen Gras #include "rtld.h"
94e83f7ba2SBen Gras
95e83f7ba2SBen Gras /*
96e83f7ba2SBen Gras * Pre-allocate mmap'ed pages
97e83f7ba2SBen Gras */
98e83f7ba2SBen Gras #define NPOOLPAGES (32*1024/pagesz)
99e83f7ba2SBen Gras static char *pagepool_start, *pagepool_end;
100e83f7ba2SBen Gras static int morepages(int);
101e83f7ba2SBen Gras #define PAGEPOOL_SIZE (size_t)(pagepool_end - pagepool_start)
102e83f7ba2SBen Gras
103e83f7ba2SBen Gras /*
104e83f7ba2SBen Gras * The overhead on a block is at least 4 bytes. When free, this space
105e83f7ba2SBen Gras * contains a pointer to the next free block, and the bottom two bits must
106e83f7ba2SBen Gras * be zero. When in use, the first byte is set to MAGIC, and the second
107e83f7ba2SBen Gras * byte is the size index. The remaining bytes are for alignment.
108e83f7ba2SBen Gras * If range checking is enabled then a second word holds the size of the
109e83f7ba2SBen Gras * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
110e83f7ba2SBen Gras * The order of elements is critical: ov_magic must overlay the low order
111e83f7ba2SBen Gras * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
112e83f7ba2SBen Gras */
113e83f7ba2SBen Gras union overhead {
114e83f7ba2SBen Gras union overhead *ov_next; /* when free */
115e83f7ba2SBen Gras struct {
116e83f7ba2SBen Gras u_char ovu_magic; /* magic number */
117e83f7ba2SBen Gras u_char ovu_index; /* bucket # */
118e83f7ba2SBen Gras #ifdef RCHECK
119e83f7ba2SBen Gras u_short ovu_rmagic; /* range magic number */
120e83f7ba2SBen Gras u_int ovu_size; /* actual block size */
121e83f7ba2SBen Gras #endif
122e83f7ba2SBen Gras } ovu;
123e83f7ba2SBen Gras #define ov_magic ovu.ovu_magic
124e83f7ba2SBen Gras #define ov_index ovu.ovu_index
125e83f7ba2SBen Gras #define ov_rmagic ovu.ovu_rmagic
126e83f7ba2SBen Gras #define ov_size ovu.ovu_size
127e83f7ba2SBen Gras };
128e83f7ba2SBen Gras
129e83f7ba2SBen Gras static void morecore(size_t);
130e83f7ba2SBen Gras static void *imalloc(size_t);
131e83f7ba2SBen Gras
132e83f7ba2SBen Gras #define MAGIC 0xef /* magic # on accounting info */
133e83f7ba2SBen Gras #define RMAGIC 0x5555 /* magic # on range info */
134e83f7ba2SBen Gras
135e83f7ba2SBen Gras #ifdef RCHECK
136e83f7ba2SBen Gras #define RSLOP (sizeof (u_short))
137e83f7ba2SBen Gras #else
138e83f7ba2SBen Gras #define RSLOP 0
139e83f7ba2SBen Gras #endif
140e83f7ba2SBen Gras
141e83f7ba2SBen Gras /*
142e83f7ba2SBen Gras * nextf[i] is the pointer to the next free block of size 2^(i+3). The
143e83f7ba2SBen Gras * smallest allocatable block is 8 bytes. The overhead information
144e83f7ba2SBen Gras * precedes the data area returned to the user.
145e83f7ba2SBen Gras */
146e83f7ba2SBen Gras #define NBUCKETS 30
147e83f7ba2SBen Gras static union overhead *nextf[NBUCKETS];
148e83f7ba2SBen Gras
149e83f7ba2SBen Gras static size_t pagesz; /* page size */
150e83f7ba2SBen Gras static size_t pagebucket; /* page size bucket */
151f14fb602SLionel Sambuc static size_t pageshift; /* page size shift */
152e83f7ba2SBen Gras
153e83f7ba2SBen Gras #ifdef MSTATS
154e83f7ba2SBen Gras /*
155e83f7ba2SBen Gras * nmalloc[i] is the difference between the number of mallocs and frees
156e83f7ba2SBen Gras * for a given block size.
157e83f7ba2SBen Gras */
158e83f7ba2SBen Gras static u_int nmalloc[NBUCKETS];
159e83f7ba2SBen Gras #endif
160e83f7ba2SBen Gras
161e83f7ba2SBen Gras #if defined(MALLOC_DEBUG) || defined(RCHECK)
162e83f7ba2SBen Gras #define ASSERT(p) if (!(p)) botch("p")
163e83f7ba2SBen Gras static void
botch(const char * s)164e83f7ba2SBen Gras botch(const char *s)
165e83f7ba2SBen Gras {
166e83f7ba2SBen Gras xwarnx("\r\nassertion botched: %s\r\n", s);
167e83f7ba2SBen Gras abort();
168e83f7ba2SBen Gras }
169e83f7ba2SBen Gras #else
170e83f7ba2SBen Gras #define ASSERT(p)
171e83f7ba2SBen Gras #endif
172e83f7ba2SBen Gras
173e83f7ba2SBen Gras #define TRACE() xprintf("TRACE %s:%d\n", __FILE__, __LINE__)
174e83f7ba2SBen Gras
175e83f7ba2SBen Gras static void *
imalloc(size_t nbytes)176e83f7ba2SBen Gras imalloc(size_t nbytes)
177e83f7ba2SBen Gras {
178e83f7ba2SBen Gras union overhead *op;
179e83f7ba2SBen Gras size_t bucket;
180e83f7ba2SBen Gras size_t n, m;
181e83f7ba2SBen Gras unsigned amt;
182e83f7ba2SBen Gras
183e83f7ba2SBen Gras /*
184e83f7ba2SBen Gras * First time malloc is called, setup page size and
185e83f7ba2SBen Gras * align break pointer so all data will be page aligned.
186e83f7ba2SBen Gras */
187e83f7ba2SBen Gras if (pagesz == 0) {
188e83f7ba2SBen Gras pagesz = n = _rtld_pagesz;
189e83f7ba2SBen Gras if (morepages(NPOOLPAGES) == 0)
190e83f7ba2SBen Gras return NULL;
191e83f7ba2SBen Gras op = (union overhead *)(pagepool_start);
192e83f7ba2SBen Gras m = sizeof (*op) - (((char *)op - (char *)NULL) & (n - 1));
193e83f7ba2SBen Gras if (n < m)
194e83f7ba2SBen Gras n += pagesz - m;
195e83f7ba2SBen Gras else
196e83f7ba2SBen Gras n -= m;
197e83f7ba2SBen Gras if (n) {
198e83f7ba2SBen Gras pagepool_start += n;
199e83f7ba2SBen Gras }
200e83f7ba2SBen Gras bucket = 0;
201e83f7ba2SBen Gras amt = sizeof(union overhead);
202e83f7ba2SBen Gras while (pagesz > amt) {
203e83f7ba2SBen Gras amt <<= 1;
204e83f7ba2SBen Gras bucket++;
205e83f7ba2SBen Gras }
206e83f7ba2SBen Gras pagebucket = bucket;
207f14fb602SLionel Sambuc pageshift = ffs(pagesz) - 1;
208e83f7ba2SBen Gras }
209e83f7ba2SBen Gras /*
210e83f7ba2SBen Gras * Convert amount of memory requested into closest block size
211e83f7ba2SBen Gras * stored in hash buckets which satisfies request.
212e83f7ba2SBen Gras * Account for space used per block for accounting.
213e83f7ba2SBen Gras */
214e83f7ba2SBen Gras if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) {
215e83f7ba2SBen Gras if (sizeof(union overhead) & (sizeof(union overhead) - 1)) {
216e83f7ba2SBen Gras amt = sizeof(union overhead) * 2;
217e83f7ba2SBen Gras bucket = 1;
218e83f7ba2SBen Gras } else {
219e83f7ba2SBen Gras amt = sizeof(union overhead); /* size of first bucket */
220e83f7ba2SBen Gras bucket = 0;
221e83f7ba2SBen Gras }
222e83f7ba2SBen Gras n = -(sizeof (*op) + RSLOP);
223e83f7ba2SBen Gras } else {
224e83f7ba2SBen Gras amt = pagesz;
225e83f7ba2SBen Gras bucket = pagebucket;
226e83f7ba2SBen Gras }
227e83f7ba2SBen Gras while (nbytes > amt + n) {
228e83f7ba2SBen Gras amt <<= 1;
229e83f7ba2SBen Gras if (amt == 0)
230e83f7ba2SBen Gras return (NULL);
231e83f7ba2SBen Gras bucket++;
232e83f7ba2SBen Gras }
233e83f7ba2SBen Gras /*
234e83f7ba2SBen Gras * If nothing in hash bucket right now,
235e83f7ba2SBen Gras * request more memory from the system.
236e83f7ba2SBen Gras */
237e83f7ba2SBen Gras if ((op = nextf[bucket]) == NULL) {
238e83f7ba2SBen Gras morecore(bucket);
239e83f7ba2SBen Gras if ((op = nextf[bucket]) == NULL)
240e83f7ba2SBen Gras return (NULL);
241e83f7ba2SBen Gras }
242e83f7ba2SBen Gras /* remove from linked list */
243e83f7ba2SBen Gras nextf[bucket] = op->ov_next;
244e83f7ba2SBen Gras op->ov_magic = MAGIC;
245e83f7ba2SBen Gras op->ov_index = bucket;
246e83f7ba2SBen Gras #ifdef MSTATS
247e83f7ba2SBen Gras nmalloc[bucket]++;
248e83f7ba2SBen Gras #endif
249e83f7ba2SBen Gras #ifdef RCHECK
250e83f7ba2SBen Gras /*
251e83f7ba2SBen Gras * Record allocated size of block and
252e83f7ba2SBen Gras * bound space with magic numbers.
253e83f7ba2SBen Gras */
254e83f7ba2SBen Gras op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
255e83f7ba2SBen Gras op->ov_rmagic = RMAGIC;
256e83f7ba2SBen Gras *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
257e83f7ba2SBen Gras #endif
258e83f7ba2SBen Gras return ((char *)(op + 1));
259e83f7ba2SBen Gras }
260e83f7ba2SBen Gras
261e83f7ba2SBen Gras /*
262e83f7ba2SBen Gras * Allocate more memory to the indicated bucket.
263e83f7ba2SBen Gras */
264e83f7ba2SBen Gras static void
morecore(size_t bucket)265e83f7ba2SBen Gras morecore(size_t bucket)
266e83f7ba2SBen Gras {
267e83f7ba2SBen Gras union overhead *op;
268e83f7ba2SBen Gras size_t sz; /* size of desired block */
269e83f7ba2SBen Gras size_t amt; /* amount to allocate */
270e83f7ba2SBen Gras size_t nblks; /* how many blocks we get */
271e83f7ba2SBen Gras
272e83f7ba2SBen Gras /*
273e83f7ba2SBen Gras * sbrk_size <= 0 only for big, FLUFFY, requests (about
274e83f7ba2SBen Gras * 2^30 bytes on a VAX, I think) or for a negative arg.
275e83f7ba2SBen Gras */
276e83f7ba2SBen Gras sz = 1 << (bucket + 3);
277e83f7ba2SBen Gras #ifdef MALLOC_DEBUG
278e83f7ba2SBen Gras ASSERT(sz > 0);
279e83f7ba2SBen Gras #endif
280e83f7ba2SBen Gras if (sz < pagesz) {
281e83f7ba2SBen Gras amt = pagesz;
282f14fb602SLionel Sambuc nblks = amt >> (bucket + 3);
283e83f7ba2SBen Gras } else {
284e83f7ba2SBen Gras amt = sz + pagesz;
285e83f7ba2SBen Gras nblks = 1;
286e83f7ba2SBen Gras }
287e83f7ba2SBen Gras if (amt > PAGEPOOL_SIZE)
288f14fb602SLionel Sambuc if (morepages((amt >> pageshift) + NPOOLPAGES) == 0)
289e83f7ba2SBen Gras return;
290e83f7ba2SBen Gras op = (union overhead *)pagepool_start;
291e83f7ba2SBen Gras pagepool_start += amt;
292e83f7ba2SBen Gras
293e83f7ba2SBen Gras /*
294e83f7ba2SBen Gras * Add new memory allocated to that on
295e83f7ba2SBen Gras * free list for this hash bucket.
296e83f7ba2SBen Gras */
297e83f7ba2SBen Gras nextf[bucket] = op;
298e83f7ba2SBen Gras while (--nblks > 0) {
299e83f7ba2SBen Gras op->ov_next = (union overhead *)((caddr_t)op + sz);
300e83f7ba2SBen Gras op = (union overhead *)((caddr_t)op + sz);
301e83f7ba2SBen Gras }
302e83f7ba2SBen Gras }
303e83f7ba2SBen Gras
304e83f7ba2SBen Gras void
xfree(void * cp)305e83f7ba2SBen Gras xfree(void *cp)
306e83f7ba2SBen Gras {
307e83f7ba2SBen Gras int size;
308e83f7ba2SBen Gras union overhead *op;
309e83f7ba2SBen Gras
310e83f7ba2SBen Gras if (cp == NULL)
311e83f7ba2SBen Gras return;
312e83f7ba2SBen Gras op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
313e83f7ba2SBen Gras #ifdef MALLOC_DEBUG
314e83f7ba2SBen Gras ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */
315e83f7ba2SBen Gras #else
316e83f7ba2SBen Gras if (op->ov_magic != MAGIC)
317e83f7ba2SBen Gras return; /* sanity */
318e83f7ba2SBen Gras #endif
319e83f7ba2SBen Gras #ifdef RCHECK
320e83f7ba2SBen Gras ASSERT(op->ov_rmagic == RMAGIC);
321e83f7ba2SBen Gras ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
322e83f7ba2SBen Gras #endif
323e83f7ba2SBen Gras size = op->ov_index;
324e83f7ba2SBen Gras ASSERT(size < NBUCKETS);
325e83f7ba2SBen Gras op->ov_next = nextf[size]; /* also clobbers ov_magic */
326e83f7ba2SBen Gras nextf[size] = op;
327e83f7ba2SBen Gras #ifdef MSTATS
328e83f7ba2SBen Gras nmalloc[size]--;
329e83f7ba2SBen Gras #endif
330e83f7ba2SBen Gras }
331e83f7ba2SBen Gras
332e83f7ba2SBen Gras static void *
irealloc(void * cp,size_t nbytes)333e83f7ba2SBen Gras irealloc(void *cp, size_t nbytes)
334e83f7ba2SBen Gras {
335e83f7ba2SBen Gras size_t onb;
336e83f7ba2SBen Gras size_t i;
337e83f7ba2SBen Gras union overhead *op;
338e83f7ba2SBen Gras char *res;
339e83f7ba2SBen Gras
340e83f7ba2SBen Gras if (cp == NULL)
341e83f7ba2SBen Gras return (imalloc(nbytes));
342e83f7ba2SBen Gras op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
343e83f7ba2SBen Gras if (op->ov_magic != MAGIC) {
344e83f7ba2SBen Gras static const char *err_str =
345e83f7ba2SBen Gras "memory corruption or double free in realloc\n";
346e83f7ba2SBen Gras extern char *__progname;
347e83f7ba2SBen Gras write(STDERR_FILENO, __progname, strlen(__progname));
348e83f7ba2SBen Gras write(STDERR_FILENO, err_str, strlen(err_str));
349e83f7ba2SBen Gras abort();
350e83f7ba2SBen Gras }
351e83f7ba2SBen Gras
352e83f7ba2SBen Gras i = op->ov_index;
353e83f7ba2SBen Gras onb = 1 << (i + 3);
354e83f7ba2SBen Gras if (onb < pagesz)
355e83f7ba2SBen Gras onb -= sizeof (*op) + RSLOP;
356e83f7ba2SBen Gras else
357e83f7ba2SBen Gras onb += pagesz - sizeof (*op) - RSLOP;
358e83f7ba2SBen Gras /* avoid the copy if same size block */
359e83f7ba2SBen Gras if (i) {
360e83f7ba2SBen Gras i = 1 << (i + 2);
361e83f7ba2SBen Gras if (i < pagesz)
362e83f7ba2SBen Gras i -= sizeof (*op) + RSLOP;
363e83f7ba2SBen Gras else
364e83f7ba2SBen Gras i += pagesz - sizeof (*op) - RSLOP;
365e83f7ba2SBen Gras }
366e83f7ba2SBen Gras if (nbytes <= onb && nbytes > i) {
367e83f7ba2SBen Gras #ifdef RCHECK
368e83f7ba2SBen Gras op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
369e83f7ba2SBen Gras *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
370e83f7ba2SBen Gras #endif
371e83f7ba2SBen Gras return(cp);
372*84d9c625SLionel Sambuc }
373e83f7ba2SBen Gras if ((res = imalloc(nbytes)) == NULL)
374e83f7ba2SBen Gras return (NULL);
375*84d9c625SLionel Sambuc if (cp != res) { /* common optimization if "compacting" */
376e83f7ba2SBen Gras memcpy(res, cp, (nbytes < onb) ? nbytes : onb);
377*84d9c625SLionel Sambuc xfree(cp);
378*84d9c625SLionel Sambuc }
379e83f7ba2SBen Gras return (res);
380e83f7ba2SBen Gras }
381e83f7ba2SBen Gras
382e83f7ba2SBen Gras #ifdef MSTATS
383e83f7ba2SBen Gras /*
384e83f7ba2SBen Gras * mstats - print out statistics about malloc
385e83f7ba2SBen Gras *
386e83f7ba2SBen Gras * Prints two lines of numbers, one showing the length of the free list
387e83f7ba2SBen Gras * for each size category, the second showing the number of mallocs -
388e83f7ba2SBen Gras * frees for each size category.
389e83f7ba2SBen Gras */
390e83f7ba2SBen Gras void
mstats(char * s)391e83f7ba2SBen Gras mstats(char *s)
392e83f7ba2SBen Gras {
393e83f7ba2SBen Gras int i, j;
394e83f7ba2SBen Gras union overhead *p;
395e83f7ba2SBen Gras int totfree = 0,
396e83f7ba2SBen Gras totused = 0;
397e83f7ba2SBen Gras
398e83f7ba2SBen Gras xprintf("Memory allocation statistics %s\nfree:\t", s);
399e83f7ba2SBen Gras for (i = 0; i < NBUCKETS; i++) {
400e83f7ba2SBen Gras for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
401e83f7ba2SBen Gras ;
402e83f7ba2SBen Gras xprintf(" %d", j);
403e83f7ba2SBen Gras totfree += j * (1 << (i + 3));
404e83f7ba2SBen Gras }
405e83f7ba2SBen Gras xprintf("\nused:\t");
406e83f7ba2SBen Gras for (i = 0; i < NBUCKETS; i++) {
407e83f7ba2SBen Gras xprintf(" %d", nmalloc[i]);
408e83f7ba2SBen Gras totused += nmalloc[i] * (1 << (i + 3));
409e83f7ba2SBen Gras }
410e83f7ba2SBen Gras xprintf("\n\tTotal in use: %d, total free: %d\n",
411e83f7ba2SBen Gras totused, totfree);
412e83f7ba2SBen Gras }
413e83f7ba2SBen Gras #endif
414e83f7ba2SBen Gras
415e83f7ba2SBen Gras
416e83f7ba2SBen Gras static int
morepages(int n)417e83f7ba2SBen Gras morepages(int n)
418e83f7ba2SBen Gras {
419e83f7ba2SBen Gras int fd = -1;
420e83f7ba2SBen Gras int offset;
421e83f7ba2SBen Gras
422e83f7ba2SBen Gras #ifdef NEED_DEV_ZERO
423e83f7ba2SBen Gras fd = open("/dev/zero", O_RDWR, 0);
424e83f7ba2SBen Gras if (fd == -1)
425e83f7ba2SBen Gras xerr(1, "/dev/zero");
426e83f7ba2SBen Gras #endif
427e83f7ba2SBen Gras
428e83f7ba2SBen Gras if (PAGEPOOL_SIZE > pagesz) {
429e83f7ba2SBen Gras caddr_t addr = (caddr_t)
430e83f7ba2SBen Gras (((long)pagepool_start + pagesz - 1) & ~(pagesz - 1));
431e83f7ba2SBen Gras if (munmap(addr, pagepool_end - addr) != 0)
432e83f7ba2SBen Gras xwarn("morepages: munmap %p", addr);
433e83f7ba2SBen Gras }
434e83f7ba2SBen Gras
435e83f7ba2SBen Gras offset = (long)pagepool_start - ((long)pagepool_start & ~(pagesz - 1));
436e83f7ba2SBen Gras
437e83f7ba2SBen Gras if ((pagepool_start = mmap(0, n * pagesz,
438e83f7ba2SBen Gras PROT_READ|PROT_WRITE,
439e83f7ba2SBen Gras MAP_ANON|MAP_PRIVATE, fd, 0)) == (caddr_t)-1) {
440e83f7ba2SBen Gras xprintf("Cannot map anonymous memory");
441e83f7ba2SBen Gras return 0;
442e83f7ba2SBen Gras }
443e83f7ba2SBen Gras pagepool_end = pagepool_start + n * pagesz;
444e83f7ba2SBen Gras pagepool_start += offset;
445e83f7ba2SBen Gras
446e83f7ba2SBen Gras #ifdef NEED_DEV_ZERO
447e83f7ba2SBen Gras close(fd);
448e83f7ba2SBen Gras #endif
449e83f7ba2SBen Gras return n;
450e83f7ba2SBen Gras }
451e83f7ba2SBen Gras
452e83f7ba2SBen Gras void *
xcalloc(size_t size)453e83f7ba2SBen Gras xcalloc(size_t size)
454e83f7ba2SBen Gras {
455e83f7ba2SBen Gras
456e83f7ba2SBen Gras return memset(xmalloc(size), 0, size);
457e83f7ba2SBen Gras }
458e83f7ba2SBen Gras
459e83f7ba2SBen Gras void *
xmalloc(size_t size)460e83f7ba2SBen Gras xmalloc(size_t size)
461e83f7ba2SBen Gras {
462e83f7ba2SBen Gras void *p = imalloc(size);
463e83f7ba2SBen Gras
464e83f7ba2SBen Gras if (p == NULL)
465e83f7ba2SBen Gras xerr(1, "%s", xstrerror(errno));
466e83f7ba2SBen Gras return p;
467e83f7ba2SBen Gras }
468e83f7ba2SBen Gras
469e83f7ba2SBen Gras void *
xrealloc(void * p,size_t size)470e83f7ba2SBen Gras xrealloc(void *p, size_t size)
471e83f7ba2SBen Gras {
472e83f7ba2SBen Gras p = irealloc(p, size);
473e83f7ba2SBen Gras
474e83f7ba2SBen Gras if (p == NULL)
475e83f7ba2SBen Gras xerr(1, "%s", xstrerror(errno));
476e83f7ba2SBen Gras return p;
477e83f7ba2SBen Gras }
478e83f7ba2SBen Gras
479e83f7ba2SBen Gras char *
xstrdup(const char * str)480e83f7ba2SBen Gras xstrdup(const char *str)
481e83f7ba2SBen Gras {
482e83f7ba2SBen Gras size_t len;
483e83f7ba2SBen Gras char *copy;
484e83f7ba2SBen Gras
485e83f7ba2SBen Gras len = strlen(str) + 1;
486e83f7ba2SBen Gras copy = xmalloc(len);
487e83f7ba2SBen Gras memcpy(copy, str, len);
488e83f7ba2SBen Gras return (copy);
489e83f7ba2SBen Gras }
490