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