1d49ca25dSKonstantin Belousov /*- 2d49ca25dSKonstantin Belousov * SPDX-License-Identifier: BSD-3-Clause 3d49ca25dSKonstantin Belousov * 4d49ca25dSKonstantin Belousov * Copyright (c) 1983 Regents of the University of California. 5d49ca25dSKonstantin Belousov * All rights reserved. 6d49ca25dSKonstantin Belousov * 7d49ca25dSKonstantin Belousov * Redistribution and use in source and binary forms, with or without 8d49ca25dSKonstantin Belousov * modification, are permitted provided that the following conditions 9d49ca25dSKonstantin Belousov * are met: 10d49ca25dSKonstantin Belousov * 1. Redistributions of source code must retain the above copyright 11d49ca25dSKonstantin Belousov * notice, this list of conditions and the following disclaimer. 12d49ca25dSKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright 13d49ca25dSKonstantin Belousov * notice, this list of conditions and the following disclaimer in the 14d49ca25dSKonstantin Belousov * documentation and/or other materials provided with the distribution. 15d49ca25dSKonstantin Belousov * 3. Neither the name of the University nor the names of its contributors 16d49ca25dSKonstantin Belousov * may be used to endorse or promote products derived from this software 17d49ca25dSKonstantin Belousov * without specific prior written permission. 18d49ca25dSKonstantin Belousov * 19d49ca25dSKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20d49ca25dSKonstantin Belousov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21d49ca25dSKonstantin Belousov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22d49ca25dSKonstantin Belousov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23d49ca25dSKonstantin Belousov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24d49ca25dSKonstantin Belousov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25d49ca25dSKonstantin Belousov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26d49ca25dSKonstantin Belousov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27d49ca25dSKonstantin Belousov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28d49ca25dSKonstantin Belousov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29d49ca25dSKonstantin Belousov * SUCH DAMAGE. 30d49ca25dSKonstantin Belousov */ 31d49ca25dSKonstantin Belousov 32d49ca25dSKonstantin Belousov #if defined(LIBC_SCCS) && !defined(lint) 33d49ca25dSKonstantin Belousov /*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/ 34d49ca25dSKonstantin Belousov static char *rcsid = "$FreeBSD$"; 35d49ca25dSKonstantin Belousov #endif /* LIBC_SCCS and not lint */ 36d49ca25dSKonstantin Belousov 37d49ca25dSKonstantin Belousov /* 38d49ca25dSKonstantin Belousov * malloc.c (Caltech) 2/21/82 39d49ca25dSKonstantin Belousov * Chris Kingsley, kingsley@cit-20. 40d49ca25dSKonstantin Belousov * 41d49ca25dSKonstantin Belousov * This is a very fast storage allocator. It allocates blocks of a small 42d49ca25dSKonstantin Belousov * number of different sizes, and keeps free lists of each size. Blocks that 43d49ca25dSKonstantin Belousov * don't exactly fit are passed up to the next larger size. In this 44d49ca25dSKonstantin Belousov * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long. 45d49ca25dSKonstantin Belousov * This is designed for use in a virtual memory environment. 46d49ca25dSKonstantin Belousov */ 47d49ca25dSKonstantin Belousov 485cac2021SKonstantin Belousov #include <sys/param.h> 49d49ca25dSKonstantin Belousov #include <sys/sysctl.h> 505cac2021SKonstantin Belousov #include <sys/mman.h> 51d49ca25dSKonstantin Belousov #include <errno.h> 52d49ca25dSKonstantin Belousov #include <stdarg.h> 53d49ca25dSKonstantin Belousov #include <stddef.h> 54d49ca25dSKonstantin Belousov #include <string.h> 55d49ca25dSKonstantin Belousov #include <unistd.h> 56d49ca25dSKonstantin Belousov #include "rtld.h" 57d49ca25dSKonstantin Belousov #include "rtld_printf.h" 58d49ca25dSKonstantin Belousov #include "paths.h" 59d49ca25dSKonstantin Belousov 60d49ca25dSKonstantin Belousov /* 61d49ca25dSKonstantin Belousov * Pre-allocate mmap'ed pages 62d49ca25dSKonstantin Belousov */ 63d49ca25dSKonstantin Belousov #define NPOOLPAGES (128*1024/pagesz) 64d49ca25dSKonstantin Belousov static caddr_t pagepool_start, pagepool_end; 65d49ca25dSKonstantin Belousov 66d49ca25dSKonstantin Belousov /* 67d49ca25dSKonstantin Belousov * The overhead on a block is at least 4 bytes. When free, this space 68d49ca25dSKonstantin Belousov * contains a pointer to the next free block, and the bottom two bits must 69d49ca25dSKonstantin Belousov * be zero. When in use, the first byte is set to MAGIC, and the second 70d49ca25dSKonstantin Belousov * byte is the size index. The remaining bytes are for alignment. 71d49ca25dSKonstantin Belousov * If range checking is enabled then a second word holds the size of the 72d49ca25dSKonstantin Belousov * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC). 73d49ca25dSKonstantin Belousov * The order of elements is critical: ov_magic must overlay the low order 74d49ca25dSKonstantin Belousov * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern. 75d49ca25dSKonstantin Belousov */ 76d49ca25dSKonstantin Belousov union overhead { 77d49ca25dSKonstantin Belousov union overhead *ov_next; /* when free */ 78d49ca25dSKonstantin Belousov struct { 79d49ca25dSKonstantin Belousov u_char ovu_magic; /* magic number */ 80d49ca25dSKonstantin Belousov u_char ovu_index; /* bucket # */ 81d49ca25dSKonstantin Belousov } ovu; 82d49ca25dSKonstantin Belousov #define ov_magic ovu.ovu_magic 83d49ca25dSKonstantin Belousov #define ov_index ovu.ovu_index 84d49ca25dSKonstantin Belousov }; 85d49ca25dSKonstantin Belousov 86d49ca25dSKonstantin Belousov static void morecore(int bucket); 87d49ca25dSKonstantin Belousov static int morepages(int n); 88d49ca25dSKonstantin Belousov static int findbucket(union overhead *freep, int srchlen); 89d49ca25dSKonstantin Belousov 90d49ca25dSKonstantin Belousov #define MAGIC 0xef /* magic # on accounting info */ 91d49ca25dSKonstantin Belousov 92d49ca25dSKonstantin Belousov /* 93d49ca25dSKonstantin Belousov * nextf[i] is the pointer to the next free block of size 2^(i+3). The 94d49ca25dSKonstantin Belousov * smallest allocatable block is 8 bytes. The overhead information 95d49ca25dSKonstantin Belousov * precedes the data area returned to the user. 96d49ca25dSKonstantin Belousov */ 97d49ca25dSKonstantin Belousov #define NBUCKETS 30 98d49ca25dSKonstantin Belousov static union overhead *nextf[NBUCKETS]; 99d49ca25dSKonstantin Belousov 100d49ca25dSKonstantin Belousov static int pagesz; /* page size */ 101d49ca25dSKonstantin Belousov static int pagebucket; /* page size bucket */ 102d49ca25dSKonstantin Belousov 103d49ca25dSKonstantin Belousov /* 104d49ca25dSKonstantin Belousov * The array of supported page sizes is provided by the user, i.e., the 105d49ca25dSKonstantin Belousov * program that calls this storage allocator. That program must initialize 106d49ca25dSKonstantin Belousov * the array before making its first call to allocate storage. The array 107d49ca25dSKonstantin Belousov * must contain at least one page size. The page sizes must be stored in 108d49ca25dSKonstantin Belousov * increasing order. 109d49ca25dSKonstantin Belousov */ 110d49ca25dSKonstantin Belousov 111d49ca25dSKonstantin Belousov void * 112d49ca25dSKonstantin Belousov __crt_malloc(size_t nbytes) 113d49ca25dSKonstantin Belousov { 114d49ca25dSKonstantin Belousov union overhead *op; 115d49ca25dSKonstantin Belousov int bucket; 116d49ca25dSKonstantin Belousov ssize_t n; 117d49ca25dSKonstantin Belousov size_t amt; 118d49ca25dSKonstantin Belousov 119d49ca25dSKonstantin Belousov /* 120d49ca25dSKonstantin Belousov * First time malloc is called, setup page size and 121d49ca25dSKonstantin Belousov * align break pointer so all data will be page aligned. 122d49ca25dSKonstantin Belousov */ 123d49ca25dSKonstantin Belousov if (pagesz == 0) { 124d49ca25dSKonstantin Belousov pagesz = n = pagesizes[0]; 125d49ca25dSKonstantin Belousov if (morepages(NPOOLPAGES) == 0) 126d49ca25dSKonstantin Belousov return NULL; 127d49ca25dSKonstantin Belousov op = (union overhead *)(pagepool_start); 128d49ca25dSKonstantin Belousov n = n - sizeof (*op) - ((long)op & (n - 1)); 129d49ca25dSKonstantin Belousov if (n < 0) 130d49ca25dSKonstantin Belousov n += pagesz; 131d49ca25dSKonstantin Belousov if (n) { 132d49ca25dSKonstantin Belousov pagepool_start += n; 133d49ca25dSKonstantin Belousov } 134d49ca25dSKonstantin Belousov bucket = 0; 135d49ca25dSKonstantin Belousov amt = 8; 136d49ca25dSKonstantin Belousov while ((unsigned)pagesz > amt) { 137d49ca25dSKonstantin Belousov amt <<= 1; 138d49ca25dSKonstantin Belousov bucket++; 139d49ca25dSKonstantin Belousov } 140d49ca25dSKonstantin Belousov pagebucket = bucket; 141d49ca25dSKonstantin Belousov } 142d49ca25dSKonstantin Belousov /* 143d49ca25dSKonstantin Belousov * Convert amount of memory requested into closest block size 144d49ca25dSKonstantin Belousov * stored in hash buckets which satisfies request. 145d49ca25dSKonstantin Belousov * Account for space used per block for accounting. 146d49ca25dSKonstantin Belousov */ 1475cac2021SKonstantin Belousov if (nbytes <= (unsigned long)(n = pagesz - sizeof(*op))) { 148d49ca25dSKonstantin Belousov amt = 8; /* size of first bucket */ 149d49ca25dSKonstantin Belousov bucket = 0; 1505cac2021SKonstantin Belousov n = -sizeof(*op); 151d49ca25dSKonstantin Belousov } else { 152d49ca25dSKonstantin Belousov amt = pagesz; 153d49ca25dSKonstantin Belousov bucket = pagebucket; 154d49ca25dSKonstantin Belousov } 155d49ca25dSKonstantin Belousov while (nbytes > amt + n) { 156d49ca25dSKonstantin Belousov amt <<= 1; 157d49ca25dSKonstantin Belousov if (amt == 0) 158d49ca25dSKonstantin Belousov return (NULL); 159d49ca25dSKonstantin Belousov bucket++; 160d49ca25dSKonstantin Belousov } 161d49ca25dSKonstantin Belousov /* 162d49ca25dSKonstantin Belousov * If nothing in hash bucket right now, 163d49ca25dSKonstantin Belousov * request more memory from the system. 164d49ca25dSKonstantin Belousov */ 165d49ca25dSKonstantin Belousov if ((op = nextf[bucket]) == NULL) { 166d49ca25dSKonstantin Belousov morecore(bucket); 167d49ca25dSKonstantin Belousov if ((op = nextf[bucket]) == NULL) 168d49ca25dSKonstantin Belousov return (NULL); 169d49ca25dSKonstantin Belousov } 170d49ca25dSKonstantin Belousov /* remove from linked list */ 171d49ca25dSKonstantin Belousov nextf[bucket] = op->ov_next; 172d49ca25dSKonstantin Belousov op->ov_magic = MAGIC; 173d49ca25dSKonstantin Belousov op->ov_index = bucket; 174d49ca25dSKonstantin Belousov return ((char *)(op + 1)); 175d49ca25dSKonstantin Belousov } 176d49ca25dSKonstantin Belousov 177d49ca25dSKonstantin Belousov void * 178d49ca25dSKonstantin Belousov __crt_calloc(size_t num, size_t size) 179d49ca25dSKonstantin Belousov { 180d49ca25dSKonstantin Belousov void *ret; 181d49ca25dSKonstantin Belousov 182d49ca25dSKonstantin Belousov if (size != 0 && (num * size) / size != num) { 183d49ca25dSKonstantin Belousov /* size_t overflow. */ 184d49ca25dSKonstantin Belousov return (NULL); 185d49ca25dSKonstantin Belousov } 186d49ca25dSKonstantin Belousov 187d49ca25dSKonstantin Belousov if ((ret = __crt_malloc(num * size)) != NULL) 188d49ca25dSKonstantin Belousov memset(ret, 0, num * size); 189d49ca25dSKonstantin Belousov 190d49ca25dSKonstantin Belousov return (ret); 191d49ca25dSKonstantin Belousov } 192d49ca25dSKonstantin Belousov 193d49ca25dSKonstantin Belousov /* 194d49ca25dSKonstantin Belousov * Allocate more memory to the indicated bucket. 195d49ca25dSKonstantin Belousov */ 196d49ca25dSKonstantin Belousov static void 197d49ca25dSKonstantin Belousov morecore(int bucket) 198d49ca25dSKonstantin Belousov { 199d49ca25dSKonstantin Belousov union overhead *op; 200d49ca25dSKonstantin Belousov int sz; /* size of desired block */ 201d49ca25dSKonstantin Belousov int amt; /* amount to allocate */ 202d49ca25dSKonstantin Belousov int nblks; /* how many blocks we get */ 203d49ca25dSKonstantin Belousov 204d49ca25dSKonstantin Belousov /* 205d49ca25dSKonstantin Belousov * sbrk_size <= 0 only for big, FLUFFY, requests (about 206d49ca25dSKonstantin Belousov * 2^30 bytes on a VAX, I think) or for a negative arg. 207d49ca25dSKonstantin Belousov */ 2085cac2021SKonstantin Belousov if ((unsigned)bucket >= NBBY * sizeof(int) - 4) 209d49ca25dSKonstantin Belousov return; 2105cac2021SKonstantin Belousov sz = 1 << (bucket + 3); 211d49ca25dSKonstantin Belousov if (sz < pagesz) { 212d49ca25dSKonstantin Belousov amt = pagesz; 213d49ca25dSKonstantin Belousov nblks = amt / sz; 214d49ca25dSKonstantin Belousov } else { 215d49ca25dSKonstantin Belousov amt = sz + pagesz; 216d49ca25dSKonstantin Belousov nblks = 1; 217d49ca25dSKonstantin Belousov } 218d49ca25dSKonstantin Belousov if (amt > pagepool_end - pagepool_start) 219d49ca25dSKonstantin Belousov if (morepages(amt/pagesz + NPOOLPAGES) == 0) 220d49ca25dSKonstantin Belousov return; 221d49ca25dSKonstantin Belousov op = (union overhead *)pagepool_start; 222d49ca25dSKonstantin Belousov pagepool_start += amt; 223d49ca25dSKonstantin Belousov 224d49ca25dSKonstantin Belousov /* 225d49ca25dSKonstantin Belousov * Add new memory allocated to that on 226d49ca25dSKonstantin Belousov * free list for this hash bucket. 227d49ca25dSKonstantin Belousov */ 228d49ca25dSKonstantin Belousov nextf[bucket] = op; 229d49ca25dSKonstantin Belousov while (--nblks > 0) { 230d49ca25dSKonstantin Belousov op->ov_next = (union overhead *)((caddr_t)op + sz); 231d49ca25dSKonstantin Belousov op = (union overhead *)((caddr_t)op + sz); 232d49ca25dSKonstantin Belousov } 233d49ca25dSKonstantin Belousov } 234d49ca25dSKonstantin Belousov 235d49ca25dSKonstantin Belousov void 236d49ca25dSKonstantin Belousov __crt_free(void *cp) 237d49ca25dSKonstantin Belousov { 238d49ca25dSKonstantin Belousov int size; 239d49ca25dSKonstantin Belousov union overhead *op; 240d49ca25dSKonstantin Belousov 241d49ca25dSKonstantin Belousov if (cp == NULL) 242d49ca25dSKonstantin Belousov return; 243d49ca25dSKonstantin Belousov op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 244d49ca25dSKonstantin Belousov if (op->ov_magic != MAGIC) 245d49ca25dSKonstantin Belousov return; /* sanity */ 246d49ca25dSKonstantin Belousov size = op->ov_index; 247d49ca25dSKonstantin Belousov op->ov_next = nextf[size]; /* also clobbers ov_magic */ 248d49ca25dSKonstantin Belousov nextf[size] = op; 249d49ca25dSKonstantin Belousov } 250d49ca25dSKonstantin Belousov 251d49ca25dSKonstantin Belousov /* 252d49ca25dSKonstantin Belousov * When a program attempts "storage compaction" as mentioned in the 253d49ca25dSKonstantin Belousov * old malloc man page, it realloc's an already freed block. Usually 254d49ca25dSKonstantin Belousov * this is the last block it freed; occasionally it might be farther 255d49ca25dSKonstantin Belousov * back. We have to search all the free lists for the block in order 256d49ca25dSKonstantin Belousov * to determine its bucket: 1st we make one pass through the lists 257d49ca25dSKonstantin Belousov * checking only the first block in each; if that fails we search 258d49ca25dSKonstantin Belousov * ``realloc_srchlen'' blocks in each list for a match (the variable 259d49ca25dSKonstantin Belousov * is extern so the caller can modify it). If that fails we just copy 260d49ca25dSKonstantin Belousov * however many bytes was given to realloc() and hope it's not huge. 261d49ca25dSKonstantin Belousov */ 262d49ca25dSKonstantin Belousov static int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ 263d49ca25dSKonstantin Belousov 264d49ca25dSKonstantin Belousov void * 265d49ca25dSKonstantin Belousov __crt_realloc(void *cp, size_t nbytes) 266d49ca25dSKonstantin Belousov { 267d49ca25dSKonstantin Belousov u_int onb; 268d49ca25dSKonstantin Belousov int i; 269d49ca25dSKonstantin Belousov union overhead *op; 270d49ca25dSKonstantin Belousov char *res; 271d49ca25dSKonstantin Belousov int was_alloced = 0; 272d49ca25dSKonstantin Belousov 273d49ca25dSKonstantin Belousov if (cp == NULL) 274d49ca25dSKonstantin Belousov return (__crt_malloc(nbytes)); 275d49ca25dSKonstantin Belousov op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 276d49ca25dSKonstantin Belousov if (op->ov_magic == MAGIC) { 277d49ca25dSKonstantin Belousov was_alloced++; 278d49ca25dSKonstantin Belousov i = op->ov_index; 279d49ca25dSKonstantin Belousov } else { 280d49ca25dSKonstantin Belousov /* 281d49ca25dSKonstantin Belousov * Already free, doing "compaction". 282d49ca25dSKonstantin Belousov * 283d49ca25dSKonstantin Belousov * Search for the old block of memory on the 284d49ca25dSKonstantin Belousov * free list. First, check the most common 285d49ca25dSKonstantin Belousov * case (last element free'd), then (this failing) 286d49ca25dSKonstantin Belousov * the last ``realloc_srchlen'' items free'd. 287d49ca25dSKonstantin Belousov * If all lookups fail, then assume the size of 288d49ca25dSKonstantin Belousov * the memory block being realloc'd is the 289d49ca25dSKonstantin Belousov * largest possible (so that all "nbytes" of new 290d49ca25dSKonstantin Belousov * memory are copied into). Note that this could cause 291d49ca25dSKonstantin Belousov * a memory fault if the old area was tiny, and the moon 292d49ca25dSKonstantin Belousov * is gibbous. However, that is very unlikely. 293d49ca25dSKonstantin Belousov */ 294d49ca25dSKonstantin Belousov if ((i = findbucket(op, 1)) < 0 && 295d49ca25dSKonstantin Belousov (i = findbucket(op, realloc_srchlen)) < 0) 296d49ca25dSKonstantin Belousov i = NBUCKETS; 297d49ca25dSKonstantin Belousov } 298d49ca25dSKonstantin Belousov onb = 1 << (i + 3); 299d49ca25dSKonstantin Belousov if (onb < (u_int)pagesz) 3005cac2021SKonstantin Belousov onb -= sizeof(*op); 301d49ca25dSKonstantin Belousov else 3025cac2021SKonstantin Belousov onb += pagesz - sizeof(*op); 303d49ca25dSKonstantin Belousov /* avoid the copy if same size block */ 304d49ca25dSKonstantin Belousov if (was_alloced) { 305d49ca25dSKonstantin Belousov if (i) { 306d49ca25dSKonstantin Belousov i = 1 << (i + 2); 307d49ca25dSKonstantin Belousov if (i < pagesz) 3085cac2021SKonstantin Belousov i -= sizeof(*op); 309d49ca25dSKonstantin Belousov else 3105cac2021SKonstantin Belousov i += pagesz - sizeof(*op); 311d49ca25dSKonstantin Belousov } 3125cac2021SKonstantin Belousov if (nbytes <= onb && nbytes > (size_t)i) 313d49ca25dSKonstantin Belousov return (cp); 314d49ca25dSKonstantin Belousov __crt_free(cp); 315d49ca25dSKonstantin Belousov } 316d49ca25dSKonstantin Belousov if ((res = __crt_malloc(nbytes)) == NULL) 317d49ca25dSKonstantin Belousov return (NULL); 318d49ca25dSKonstantin Belousov if (cp != res) /* common optimization if "compacting" */ 319d49ca25dSKonstantin Belousov bcopy(cp, res, (nbytes < onb) ? nbytes : onb); 320d49ca25dSKonstantin Belousov return (res); 321d49ca25dSKonstantin Belousov } 322d49ca25dSKonstantin Belousov 323d49ca25dSKonstantin Belousov /* 324d49ca25dSKonstantin Belousov * Search ``srchlen'' elements of each free list for a block whose 325d49ca25dSKonstantin Belousov * header starts at ``freep''. If srchlen is -1 search the whole list. 326d49ca25dSKonstantin Belousov * Return bucket number, or -1 if not found. 327d49ca25dSKonstantin Belousov */ 328d49ca25dSKonstantin Belousov static int 329d49ca25dSKonstantin Belousov findbucket(union overhead *freep, int srchlen) 330d49ca25dSKonstantin Belousov { 331d49ca25dSKonstantin Belousov union overhead *p; 332d49ca25dSKonstantin Belousov int i, j; 333d49ca25dSKonstantin Belousov 334d49ca25dSKonstantin Belousov for (i = 0; i < NBUCKETS; i++) { 335d49ca25dSKonstantin Belousov j = 0; 336d49ca25dSKonstantin Belousov for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { 337d49ca25dSKonstantin Belousov if (p == freep) 338d49ca25dSKonstantin Belousov return (i); 339d49ca25dSKonstantin Belousov j++; 340d49ca25dSKonstantin Belousov } 341d49ca25dSKonstantin Belousov } 342d49ca25dSKonstantin Belousov return (-1); 343d49ca25dSKonstantin Belousov } 344d49ca25dSKonstantin Belousov 345d49ca25dSKonstantin Belousov static int 346d49ca25dSKonstantin Belousov morepages(int n) 347d49ca25dSKonstantin Belousov { 348*3cac4083SKonstantin Belousov caddr_t addr; 349d49ca25dSKonstantin Belousov int offset; 350d49ca25dSKonstantin Belousov 351d49ca25dSKonstantin Belousov if (pagepool_end - pagepool_start > pagesz) { 352*3cac4083SKonstantin Belousov addr = (caddr_t)roundup2((long)pagepool_start, pagesz); 353d49ca25dSKonstantin Belousov if (munmap(addr, pagepool_end - addr) != 0) { 354d49ca25dSKonstantin Belousov #ifdef IN_RTLD 355d49ca25dSKonstantin Belousov rtld_fdprintf(STDERR_FILENO, _BASENAME_RTLD ": " 356d49ca25dSKonstantin Belousov "morepages: cannot munmap %p: %s\n", 357d49ca25dSKonstantin Belousov addr, rtld_strerror(errno)); 358d49ca25dSKonstantin Belousov #endif 359d49ca25dSKonstantin Belousov } 360d49ca25dSKonstantin Belousov } 361d49ca25dSKonstantin Belousov 362*3cac4083SKonstantin Belousov offset = (long)pagepool_start - rounddown2((long)pagepool_start, 363*3cac4083SKonstantin Belousov pagesz); 364d49ca25dSKonstantin Belousov 365*3cac4083SKonstantin Belousov pagepool_start = mmap(0, n * pagesz, PROT_READ | PROT_WRITE, 366*3cac4083SKonstantin Belousov MAP_ANON | MAP_PRIVATE, -1, 0); 367*3cac4083SKonstantin Belousov if (pagepool_start == MAP_FAILED) { 368d49ca25dSKonstantin Belousov #ifdef IN_RTLD 369d49ca25dSKonstantin Belousov rtld_fdprintf(STDERR_FILENO, _BASENAME_RTLD ": morepages: " 370d49ca25dSKonstantin Belousov "cannot mmap anonymous memory: %s\n", 371d49ca25dSKonstantin Belousov rtld_strerror(errno)); 372d49ca25dSKonstantin Belousov #endif 373*3cac4083SKonstantin Belousov return (0); 374d49ca25dSKonstantin Belousov } 375d49ca25dSKonstantin Belousov pagepool_end = pagepool_start + n * pagesz; 376d49ca25dSKonstantin Belousov pagepool_start += offset; 377d49ca25dSKonstantin Belousov 378*3cac4083SKonstantin Belousov return (n); 379d49ca25dSKonstantin Belousov } 380