mem1.c revision 80284
1284254Ssjg/* $NetBSD: mem1.c,v 1.2 1995/07/03 21:24:25 cgd Exp $ */ 2246149Ssjg 3246149Ssjg/* 4246149Ssjg * Copyright (c) 1994, 1995 Jochen Pohl 5246149Ssjg * All Rights Reserved. 6246149Ssjg * 7246149Ssjg * Redistribution and use in source and binary forms, with or without 8246149Ssjg * modification, are permitted provided that the following conditions 9246149Ssjg * are met: 10246149Ssjg * 1. Redistributions of source code must retain the above copyright 11246149Ssjg * notice, this list of conditions and the following disclaimer. 12246149Ssjg * 2. Redistributions in binary form must reproduce the above copyright 13246149Ssjg * notice, this list of conditions and the following disclaimer in the 14246149Ssjg * documentation and/or other materials provided with the distribution. 15246149Ssjg * 3. All advertising materials mentioning features or use of this software 16246149Ssjg * must display the following acknowledgement: 17246149Ssjg * This product includes software developed by Jochen Pohl for 18246149Ssjg * The NetBSD Project. 19246149Ssjg * 4. The name of the author may not be used to endorse or promote products 20246149Ssjg * derived from this software without specific prior written permission. 21246149Ssjg * 22246149Ssjg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23246149Ssjg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24246149Ssjg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25246149Ssjg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26246149Ssjg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27246149Ssjg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28246149Ssjg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29246149Ssjg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30246149Ssjg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31246149Ssjg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32246149Ssjg */ 33246149Ssjg 34246149Ssjg#ifndef lint 35246149Ssjgstatic const char rcsid[] = 36246149Ssjg "$FreeBSD: head/usr.bin/xlint/lint1/mem1.c 80284 2001-07-24 14:02:07Z obrien $"; 37246149Ssjg#endif 38281812Ssjg 39281812Ssjg#include <sys/types.h> 40281812Ssjg#include <sys/mman.h> 41281812Ssjg#include <sys/param.h> 42246149Ssjg#include <stdlib.h> 43281812Ssjg#include <string.h> 44281812Ssjg#include <unistd.h> 45246149Ssjg#include <err.h> 46246149Ssjg 47246149Ssjg#include "lint1.h" 48246149Ssjg 49246149Ssjg/* 50246149Ssjg * Filenames allocated by fnalloc() and fnnalloc() are shared. 51246149Ssjg */ 52246149Ssjgtypedef struct fn { 53246149Ssjg char *fn_name; 54246149Ssjg size_t fn_len; 55281812Ssjg int fn_id; 56246149Ssjg struct fn *fn_nxt; 57249033Ssjg} fn_t; 58249033Ssjg 59249033Ssjgstatic fn_t *fnames; 60249033Ssjg 61249033Ssjgstatic fn_t *srchfn __P((const char *, size_t)); 62246149Ssjg 63246149Ssjg/* 64249033Ssjg * Look for a Filename of length l. 65246149Ssjg */ 66246149Ssjgstatic fn_t * 67246149Ssjgsrchfn(s, len) 68246149Ssjg const char *s; 69246149Ssjg size_t len; 70246149Ssjg{ 71249033Ssjg fn_t *fn; 72246149Ssjg 73246149Ssjg for (fn = fnames; fn != NULL; fn = fn->fn_nxt) { 74246149Ssjg if (fn->fn_len == len && memcmp(fn->fn_name, s, len) == 0) 75246149Ssjg break; 76246149Ssjg } 77249033Ssjg return (fn); 78246149Ssjg} 79246149Ssjg 80246149Ssjg/* 81246149Ssjg * Return a shared string for filename s. 82246149Ssjg */ 83246149Ssjgconst char * 84249033Ssjgfnalloc(s) 85249033Ssjg const char *s; 86246149Ssjg{ 87246149Ssjg return (s != NULL ? fnnalloc(s, strlen(s)) : NULL); 88246149Ssjg} 89249033Ssjg 90246149Ssjgconst char * 91246149Ssjgfnnalloc(s, len) 92246149Ssjg const char *s; 93246149Ssjg size_t len; 94246149Ssjg{ 95246149Ssjg fn_t *fn; 96246149Ssjg 97246149Ssjg static int nxt_id = 0; 98246149Ssjg 99246149Ssjg if (s == NULL) 100249033Ssjg return (NULL); 101246149Ssjg 102246149Ssjg if ((fn = srchfn(s, len)) == NULL) { 103246149Ssjg if ((fn = malloc(sizeof (fn_t))) == NULL) 104249033Ssjg nomem(); 105246149Ssjg /* Do not used strdup() because string is not NUL-terminated.*/ 106246149Ssjg if ((fn->fn_name = malloc(len + 1)) == NULL) 107246149Ssjg nomem(); 108246149Ssjg (void)memcpy(fn->fn_name, s, len); 109246149Ssjg fn->fn_name[len] = '\0'; 110246149Ssjg fn->fn_len = len; 111246149Ssjg fn->fn_id = nxt_id++; 112246149Ssjg fn->fn_nxt = fnames; 113246149Ssjg fnames = fn; 114249033Ssjg /* Write id of this filename to the output file. */ 115249033Ssjg outclr(); 116246149Ssjg outint(fn->fn_id); 117246149Ssjg outchar('s'); 118246149Ssjg outstrg(fn->fn_name); 119246149Ssjg } 120246149Ssjg return (fn->fn_name); 121246149Ssjg} 122281812Ssjg 123281812Ssjg/* 124281812Ssjg * Get id of a filename. 125246149Ssjg */ 126249033Ssjgint 127246149Ssjggetfnid(s) 128246149Ssjg const char *s; 129281812Ssjg{ 130246149Ssjg fn_t *fn; 131246149Ssjg 132246149Ssjg if (s == NULL || (fn = srchfn(s, strlen(s))) == NULL) 133246149Ssjg return (-1); 134246149Ssjg return (fn->fn_id); 135246149Ssjg} 136249033Ssjg 137246149Ssjg/* 138246149Ssjg * Memory for declarations and other things which must be available 139246149Ssjg * until the end of a block (or the end of the translation unit) 140246149Ssjg * are assoziated with the level (mblklev) of the block (or wiht 0). 141246149Ssjg * Because these memory is allocated in large blocks associated with 142281812Ssjg * a given level it can be freed easily at the end of a block. 143246149Ssjg */ 144246149Ssjg#define ML_INC ((size_t)32) /* Increment for length of *mblks */ 145246149Ssjg 146246149Ssjgtypedef struct mbl { 147246149Ssjg void *blk; /* beginning of memory block */ 148246149Ssjg void *ffree; /* first free byte */ 149281812Ssjg size_t nfree; /* # of free bytes */ 150246149Ssjg size_t size; /* total size of memory block */ 151246149Ssjg struct mbl *nxt; /* next block */ 152246149Ssjg} mbl_t; 153246149Ssjg 154246149Ssjg/* 155246149Ssjg * Array of pointers to lists of memory blocks. mblklev is used as 156246149Ssjg * index into this array. 157246149Ssjg */ 158246149Ssjgstatic mbl_t **mblks; 159246149Ssjg 160246149Ssjg/* number of elements in *mblks */ 161246149Ssjgstatic size_t nmblks; 162246149Ssjg 163246149Ssjg/* free list for memory blocks */ 164246149Ssjgstatic mbl_t *frmblks; 165246149Ssjg 166246149Ssjg/* length of new allocated memory blocks */ 167246149Ssjgstatic size_t mblklen; 168246149Ssjg 169246149Ssjgstatic void *xgetblk __P((mbl_t **, size_t)); 170246149Ssjgstatic void xfreeblk __P((mbl_t **)); 171246149Ssjgstatic mbl_t *xnewblk __P((void)); 172246149Ssjg 173246149Ssjgstatic mbl_t * 174246149Ssjgxnewblk() 175249033Ssjg{ 176246149Ssjg mbl_t *mb; 177246149Ssjg int prot, flags; 178246149Ssjg 179246149Ssjg if ((mb = malloc(sizeof (mbl_t))) == NULL) 180246149Ssjg nomem(); 181246149Ssjg 182246149Ssjg /* use mmap instead of malloc to avoid malloc's size overhead */ 183246149Ssjg 184246149Ssjg prot = PROT_READ | PROT_WRITE; 185249033Ssjg flags = MAP_ANON | MAP_PRIVATE; 186246149Ssjg mb->blk = mmap(NULL, mblklen, prot, flags, -1, (off_t)0); 187246149Ssjg if (mb->blk == (void *)MAP_FAILED) 188246149Ssjg err(1, "can't map memory"); 189246149Ssjg if (ALIGN((u_long)mb->blk) != (u_long)mb->blk) 190246149Ssjg errx(1, "mapped address is not aligned"); 191246149Ssjg 192246149Ssjg mb->size = mblklen; 193246149Ssjg 194246149Ssjg return (mb); 195249033Ssjg} 196246149Ssjg 197246149Ssjg/* 198246149Ssjg * Allocate new memory. If the first block of the list has not enough 199246149Ssjg * free space, or there is no first block, get a new block. The new 200246149Ssjg * block is taken from the free list or, if there is no block on the 201246149Ssjg * free list, is allocated using xnewblk(). If a new block is allocated 202246149Ssjg * it is initialized with zero. Blocks taken from the free list are 203246149Ssjg * zero'd in xfreeblk(). 204246149Ssjg */ 205246149Ssjgstatic void * 206246149Ssjgxgetblk(mbp, s) 207246149Ssjg mbl_t **mbp; 208246149Ssjg size_t s; 209246149Ssjg{ 210246149Ssjg mbl_t *mb; 211249033Ssjg void *p; 212249033Ssjg 213246149Ssjg s = ALIGN(s); 214246149Ssjg if ((mb = *mbp) == NULL || mb->nfree < s) { 215246149Ssjg if ((mb = frmblks) == NULL) { 216246149Ssjg mb = xnewblk(); 217246149Ssjg (void)memset(mb->blk, 0, mb->size); 218246149Ssjg } else { 219246149Ssjg frmblks = mb->nxt; 220246149Ssjg } 221284254Ssjg mb->ffree = mb->blk; 222246149Ssjg mb->nfree = mb->size;; 223246149Ssjg mb->nxt = *mbp; 224246149Ssjg *mbp = mb; 225246149Ssjg } 226246149Ssjg p = mb->ffree; 227281812Ssjg mb->ffree = (char *)mb->ffree + s; 228249033Ssjg mb->nfree -= s; 229249033Ssjg return (p); 230249033Ssjg} 231249033Ssjg 232249033Ssjg/* 233249033Ssjg * Move all blocks from list *fmbp to free list. For each block, set all 234249033Ssjg * used memory to zero. 235249033Ssjg */ 236249033Ssjgstatic void 237249033Ssjgxfreeblk(fmbp) 238249033Ssjg mbl_t **fmbp; 239249033Ssjg{ 240249033Ssjg mbl_t *mb; 241284254Ssjg 242249033Ssjg while ((mb = *fmbp) != NULL) { 243284254Ssjg *fmbp = mb->nxt; 244249033Ssjg mb->nxt = frmblks; 245250837Ssjg frmblks = mb; 246250837Ssjg (void)memset(mb->blk, 0, mb->size - mb->nfree); 247250837Ssjg } 248246149Ssjg} 249250837Ssjg 250250837Ssjgvoid 251250837Ssjginitmem() 252250837Ssjg{ 253250837Ssjg int pgsz; 254250837Ssjg 255250837Ssjg pgsz = getpagesize(); 256250837Ssjg mblklen = ((MBLKSIZ + pgsz - 1) / pgsz) * pgsz; 257281812Ssjg 258250837Ssjg if ((mblks = calloc(nmblks = ML_INC, sizeof (mbl_t *))) == NULL) 259281812Ssjg nomem(); 260281812Ssjg} 261281812Ssjg 262281812Ssjg 263281812Ssjg/* 264281812Ssjg * Allocate memory associated with level l. 265281812Ssjg */ 266281812Ssjgvoid * 267281812Ssjggetlblk(l, s) 268281812Ssjg int l; 269281812Ssjg size_t s; 270281812Ssjg{ 271281812Ssjg while (l >= nmblks) { 272281812Ssjg if ((mblks = realloc(mblks, (nmblks + ML_INC) * 273281812Ssjg sizeof (mbl_t *))) == NULL) 274281812Ssjg nomem(); 275281812Ssjg (void)memset(&mblks[nmblks], 0, ML_INC * sizeof (mbl_t *)); 276281812Ssjg nmblks += ML_INC; 277250837Ssjg } 278281812Ssjg return (xgetblk(&mblks[l], s)); 279281812Ssjg} 280 281void * 282getblk(s) 283 size_t s; 284{ 285 return (getlblk(mblklev, s)); 286} 287 288/* 289 * Free all memory associated with level l. 290 */ 291void 292freelblk(l) 293 int l; 294{ 295 xfreeblk(&mblks[l]); 296} 297 298void 299freeblk() 300{ 301 freelblk(mblklev); 302} 303 304/* 305 * tgetblk() returns memory which is associated with the current 306 * expression. 307 */ 308static mbl_t *tmblk; 309 310void * 311tgetblk(s) 312 size_t s; 313{ 314 return (xgetblk(&tmblk, s)); 315} 316 317/* 318 * Get memory for a new tree node. 319 */ 320tnode_t * 321getnode() 322{ 323 return (tgetblk(sizeof (tnode_t))); 324} 325 326/* 327 * Free all memory which is allocated by the the current expression. 328 */ 329void 330tfreeblk() 331{ 332 xfreeblk(&tmblk); 333} 334 335/* 336 * Save the memory which is used by the current expression. This memory 337 * is not freed by the next tfreeblk() call. The pointer returned can be 338 * used to restore the memory. 339 */ 340mbl_t * 341tsave() 342{ 343 mbl_t *tmem; 344 345 tmem = tmblk; 346 tmblk = NULL; 347 return (tmem); 348} 349 350/* 351 * Free all memory used for the current expression and the memory used 352 * be a previous expression and saved by tsave(). The next call to 353 * tfreeblk() frees the restored memory. 354 */ 355void 356trestor(tmem) 357 mbl_t *tmem; 358{ 359 tfreeblk(); 360 if (tmblk != NULL) { 361 free(tmblk->blk); 362 free(tmblk); 363 } 364 tmblk = tmem; 365} 366