Home | History | Annotate | Line # | Download | only in lint1
mem1.c revision 1.15.8.1
      1  1.15.8.1       tls /*	$NetBSD: mem1.c,v 1.15.8.1 2014/08/20 00:05:06 tls Exp $	*/
      2       1.2       cgd 
      3       1.1       cgd /*
      4       1.1       cgd  * Copyright (c) 1994, 1995 Jochen Pohl
      5       1.1       cgd  * All Rights Reserved.
      6       1.1       cgd  *
      7       1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8       1.1       cgd  * modification, are permitted provided that the following conditions
      9       1.1       cgd  * are met:
     10       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15       1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16       1.1       cgd  *    must display the following acknowledgement:
     17       1.1       cgd  *      This product includes software developed by Jochen Pohl for
     18       1.1       cgd  *	The NetBSD Project.
     19       1.1       cgd  * 4. The name of the author may not be used to endorse or promote products
     20       1.1       cgd  *    derived from this software without specific prior written permission.
     21       1.1       cgd  *
     22       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23       1.1       cgd  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24       1.1       cgd  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25       1.1       cgd  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26       1.1       cgd  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27       1.1       cgd  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28       1.1       cgd  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29       1.1       cgd  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30       1.1       cgd  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31       1.1       cgd  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32       1.1       cgd  */
     33       1.1       cgd 
     34      1.11       jmc #if HAVE_NBTOOL_CONFIG_H
     35      1.11       jmc #include "nbtool_config.h"
     36      1.11       jmc #endif
     37      1.11       jmc 
     38       1.3  christos #include <sys/cdefs.h>
     39       1.7        tv #if defined(__RCSID) && !defined(lint)
     40  1.15.8.1       tls __RCSID("$NetBSD: mem1.c,v 1.15.8.1 2014/08/20 00:05:06 tls Exp $");
     41       1.1       cgd #endif
     42       1.1       cgd 
     43       1.1       cgd #include <sys/types.h>
     44       1.1       cgd #include <sys/param.h>
     45       1.1       cgd #include <stdlib.h>
     46       1.1       cgd #include <string.h>
     47       1.1       cgd #include <unistd.h>
     48       1.1       cgd 
     49       1.1       cgd #include "lint1.h"
     50       1.1       cgd 
     51       1.1       cgd /*
     52       1.1       cgd  * Filenames allocated by fnalloc() and fnnalloc() are shared.
     53       1.1       cgd  */
     54       1.1       cgd typedef struct fn {
     55       1.1       cgd 	char	*fn_name;
     56       1.1       cgd 	size_t	fn_len;
     57       1.1       cgd 	int	fn_id;
     58       1.1       cgd 	struct	fn *fn_nxt;
     59       1.1       cgd } fn_t;
     60       1.1       cgd 
     61       1.1       cgd static	fn_t	*fnames;
     62       1.1       cgd 
     63       1.5     lukem static	fn_t	*srchfn(const char *, size_t);
     64       1.1       cgd 
     65       1.1       cgd /*
     66       1.1       cgd  * Look for a Filename of length l.
     67       1.1       cgd  */
     68       1.1       cgd static fn_t *
     69       1.5     lukem srchfn(const char *s, size_t len)
     70       1.1       cgd {
     71       1.1       cgd 	fn_t	*fn;
     72       1.1       cgd 
     73       1.1       cgd 	for (fn = fnames; fn != NULL; fn = fn->fn_nxt) {
     74       1.1       cgd 		if (fn->fn_len == len && memcmp(fn->fn_name, s, len) == 0)
     75       1.1       cgd 			break;
     76       1.1       cgd 	}
     77       1.1       cgd 	return (fn);
     78       1.1       cgd }
     79       1.1       cgd 
     80       1.1       cgd /*
     81       1.1       cgd  * Return a shared string for filename s.
     82       1.1       cgd  */
     83       1.1       cgd const char *
     84       1.5     lukem fnalloc(const char *s)
     85       1.1       cgd {
     86       1.5     lukem 
     87       1.1       cgd 	return (s != NULL ? fnnalloc(s, strlen(s)) : NULL);
     88       1.1       cgd }
     89       1.1       cgd 
     90       1.1       cgd const char *
     91       1.5     lukem fnnalloc(const char *s, size_t len)
     92       1.1       cgd {
     93       1.1       cgd 	fn_t	*fn;
     94       1.1       cgd 
     95       1.1       cgd 	static	int	nxt_id = 0;
     96       1.1       cgd 
     97       1.1       cgd 	if (s == NULL)
     98       1.1       cgd 		return (NULL);
     99       1.1       cgd 
    100       1.1       cgd 	if ((fn = srchfn(s, len)) == NULL) {
    101       1.1       cgd 		fn = xmalloc(sizeof (fn_t));
    102       1.1       cgd 		/* Do not used strdup() because string is not NUL-terminated.*/
    103       1.1       cgd 		fn->fn_name = xmalloc(len + 1);
    104       1.1       cgd 		(void)memcpy(fn->fn_name, s, len);
    105       1.1       cgd 		fn->fn_name[len] = '\0';
    106       1.1       cgd 		fn->fn_len = len;
    107       1.1       cgd 		fn->fn_id = nxt_id++;
    108       1.1       cgd 		fn->fn_nxt = fnames;
    109       1.1       cgd 		fnames = fn;
    110       1.1       cgd 		/* Write id of this filename to the output file. */
    111       1.1       cgd 		outclr();
    112       1.1       cgd 		outint(fn->fn_id);
    113       1.1       cgd 		outchar('s');
    114       1.1       cgd 		outstrg(fn->fn_name);
    115       1.1       cgd 	}
    116       1.1       cgd 	return (fn->fn_name);
    117       1.1       cgd }
    118       1.1       cgd 
    119       1.1       cgd /*
    120       1.1       cgd  * Get id of a filename.
    121       1.1       cgd  */
    122       1.1       cgd int
    123       1.5     lukem getfnid(const char *s)
    124       1.1       cgd {
    125       1.1       cgd 	fn_t	*fn;
    126       1.1       cgd 
    127       1.1       cgd 	if (s == NULL || (fn = srchfn(s, strlen(s))) == NULL)
    128       1.1       cgd 		return (-1);
    129       1.1       cgd 	return (fn->fn_id);
    130       1.1       cgd }
    131       1.1       cgd 
    132       1.1       cgd /*
    133       1.1       cgd  * Memory for declarations and other things which must be available
    134       1.1       cgd  * until the end of a block (or the end of the translation unit)
    135      1.13       wiz  * are associated with the level (mblklev) of the block (or with 0).
    136      1.13       wiz  * Because this memory is allocated in large blocks associated with
    137       1.1       cgd  * a given level it can be freed easily at the end of a block.
    138       1.1       cgd  */
    139       1.1       cgd #define	ML_INC	((size_t)32)		/* Increment for length of *mblks */
    140       1.1       cgd 
    141       1.1       cgd typedef struct mbl {
    142       1.1       cgd 	void	*blk;			/* beginning of memory block */
    143       1.1       cgd 	void	*ffree;			/* first free byte */
    144       1.1       cgd 	size_t	nfree;			/* # of free bytes */
    145       1.1       cgd 	size_t	size;			/* total size of memory block */
    146       1.1       cgd 	struct	mbl *nxt;		/* next block */
    147       1.1       cgd } mbl_t;
    148       1.1       cgd 
    149       1.1       cgd /*
    150       1.1       cgd  * Array of pointers to lists of memory blocks. mblklev is used as
    151       1.1       cgd  * index into this array.
    152       1.1       cgd  */
    153       1.1       cgd static	mbl_t	**mblks;
    154       1.1       cgd 
    155       1.1       cgd /* number of elements in *mblks */
    156       1.1       cgd static	size_t	nmblks;
    157       1.1       cgd 
    158       1.1       cgd /* free list for memory blocks */
    159       1.1       cgd static	mbl_t	*frmblks;
    160       1.1       cgd 
    161       1.1       cgd /* length of new allocated memory blocks */
    162       1.1       cgd static	size_t	mblklen;
    163       1.1       cgd 
    164       1.5     lukem static	void	*xgetblk(mbl_t **, size_t);
    165       1.5     lukem static	void	xfreeblk(mbl_t **);
    166       1.5     lukem static	mbl_t	*xnewblk(void);
    167       1.1       cgd 
    168       1.1       cgd static mbl_t *
    169       1.5     lukem xnewblk(void)
    170       1.1       cgd {
    171      1.10  christos 	mbl_t	*mb = xmalloc(sizeof (mbl_t));
    172       1.1       cgd 
    173       1.1       cgd 	/* use mmap instead of malloc to avoid malloc's size overhead */
    174      1.10  christos 	mb->blk = xmapalloc(mblklen);
    175       1.1       cgd 	mb->size = mblklen;
    176       1.1       cgd 
    177       1.1       cgd 	return (mb);
    178       1.1       cgd }
    179       1.1       cgd 
    180       1.1       cgd /*
    181       1.1       cgd  * Allocate new memory. If the first block of the list has not enough
    182       1.1       cgd  * free space, or there is no first block, get a new block. The new
    183       1.1       cgd  * block is taken from the free list or, if there is no block on the
    184       1.1       cgd  * free list, is allocated using xnewblk(). If a new block is allocated
    185       1.1       cgd  * it is initialized with zero. Blocks taken from the free list are
    186       1.1       cgd  * zero'd in xfreeblk().
    187       1.1       cgd  */
    188       1.1       cgd static void *
    189       1.5     lukem xgetblk(mbl_t **mbp, size_t s)
    190       1.1       cgd {
    191       1.1       cgd 	mbl_t	*mb;
    192       1.1       cgd 	void	*p;
    193       1.8       jmc 	size_t	t = 0;
    194       1.1       cgd 
    195      1.15  christos 	s = WORST_ALIGN(s);
    196       1.1       cgd 	if ((mb = *mbp) == NULL || mb->nfree < s) {
    197      1.14  christos 		if ((mb = frmblks) == NULL || mb->size < s) {
    198       1.8       jmc 			if (s > mblklen) {
    199       1.8       jmc 				t = mblklen;
    200       1.8       jmc 				mblklen = s;
    201       1.8       jmc 			}
    202       1.1       cgd 			mb = xnewblk();
    203  1.15.8.1       tls #ifndef BLKDEBUG
    204  1.15.8.1       tls 			(void)memset(mb->blk, 0, mb->size);
    205  1.15.8.1       tls #endif
    206       1.8       jmc 			if (t)
    207       1.8       jmc 				mblklen = t;
    208       1.1       cgd 		} else {
    209       1.1       cgd 			frmblks = mb->nxt;
    210       1.1       cgd 		}
    211       1.1       cgd 		mb->ffree = mb->blk;
    212       1.9    simonb 		mb->nfree = mb->size;
    213       1.1       cgd 		mb->nxt = *mbp;
    214       1.1       cgd 		*mbp = mb;
    215       1.1       cgd 	}
    216       1.1       cgd 	p = mb->ffree;
    217       1.1       cgd 	mb->ffree = (char *)mb->ffree + s;
    218       1.1       cgd 	mb->nfree -= s;
    219  1.15.8.1       tls #ifdef BLKDEBUG
    220  1.15.8.1       tls 	(void)memset(p, 0, s);
    221  1.15.8.1       tls #endif
    222       1.1       cgd 	return (p);
    223       1.1       cgd }
    224       1.1       cgd 
    225       1.1       cgd /*
    226       1.1       cgd  * Move all blocks from list *fmbp to free list. For each block, set all
    227       1.1       cgd  * used memory to zero.
    228       1.1       cgd  */
    229       1.1       cgd static void
    230       1.5     lukem xfreeblk(mbl_t **fmbp)
    231       1.1       cgd {
    232       1.1       cgd 	mbl_t	*mb;
    233       1.1       cgd 
    234       1.1       cgd 	while ((mb = *fmbp) != NULL) {
    235       1.1       cgd 		*fmbp = mb->nxt;
    236       1.1       cgd 		mb->nxt = frmblks;
    237       1.1       cgd 		frmblks = mb;
    238  1.15.8.1       tls 		(void)memset(mb->blk, ZERO, mb->size - mb->nfree);
    239       1.1       cgd 	}
    240       1.1       cgd }
    241       1.1       cgd 
    242       1.1       cgd void
    243       1.5     lukem initmem(void)
    244       1.1       cgd {
    245       1.1       cgd 	int	pgsz;
    246       1.1       cgd 
    247       1.1       cgd 	pgsz = getpagesize();
    248       1.1       cgd 	mblklen = ((MBLKSIZ + pgsz - 1) / pgsz) * pgsz;
    249       1.1       cgd 
    250       1.1       cgd 	mblks = xcalloc(nmblks = ML_INC, sizeof (mbl_t *));
    251       1.1       cgd }
    252       1.1       cgd 
    253       1.5     lukem 
    254       1.1       cgd /*
    255       1.1       cgd  * Allocate memory associated with level l.
    256       1.1       cgd  */
    257       1.1       cgd void *
    258      1.12  christos getlblk(size_t l, size_t s)
    259       1.1       cgd {
    260       1.5     lukem 
    261       1.1       cgd 	while (l >= nmblks) {
    262       1.1       cgd 		mblks = xrealloc(mblks, (nmblks + ML_INC) * sizeof (mbl_t *));
    263       1.1       cgd 		(void)memset(&mblks[nmblks], 0, ML_INC * sizeof (mbl_t *));
    264       1.1       cgd 		nmblks += ML_INC;
    265       1.1       cgd 	}
    266       1.1       cgd 	return (xgetblk(&mblks[l], s));
    267       1.1       cgd }
    268       1.1       cgd 
    269       1.1       cgd void *
    270       1.5     lukem getblk(size_t s)
    271       1.1       cgd {
    272       1.5     lukem 
    273       1.1       cgd 	return (getlblk(mblklev, s));
    274       1.1       cgd }
    275       1.1       cgd 
    276       1.1       cgd /*
    277       1.1       cgd  * Free all memory associated with level l.
    278       1.1       cgd  */
    279       1.1       cgd void
    280       1.5     lukem freelblk(int l)
    281       1.1       cgd {
    282       1.5     lukem 
    283       1.1       cgd 	xfreeblk(&mblks[l]);
    284       1.1       cgd }
    285       1.1       cgd 
    286       1.1       cgd void
    287       1.5     lukem freeblk(void)
    288       1.1       cgd {
    289       1.5     lukem 
    290       1.1       cgd 	freelblk(mblklev);
    291       1.1       cgd }
    292       1.1       cgd 
    293       1.1       cgd /*
    294       1.1       cgd  * tgetblk() returns memory which is associated with the current
    295       1.1       cgd  * expression.
    296       1.1       cgd  */
    297       1.1       cgd static	mbl_t	*tmblk;
    298       1.1       cgd 
    299       1.1       cgd void *
    300       1.5     lukem tgetblk(size_t s)
    301       1.1       cgd {
    302       1.5     lukem 
    303       1.1       cgd 	return (xgetblk(&tmblk, s));
    304       1.1       cgd }
    305       1.1       cgd 
    306       1.1       cgd /*
    307       1.1       cgd  * Get memory for a new tree node.
    308       1.1       cgd  */
    309       1.1       cgd tnode_t *
    310       1.5     lukem getnode(void)
    311       1.1       cgd {
    312       1.5     lukem 
    313       1.1       cgd 	return (tgetblk(sizeof (tnode_t)));
    314       1.1       cgd }
    315       1.1       cgd 
    316       1.1       cgd /*
    317       1.4     soren  * Free all memory which is allocated by the current expression.
    318       1.1       cgd  */
    319       1.1       cgd void
    320       1.5     lukem tfreeblk(void)
    321       1.1       cgd {
    322       1.5     lukem 
    323       1.1       cgd 	xfreeblk(&tmblk);
    324       1.1       cgd }
    325       1.1       cgd 
    326       1.1       cgd /*
    327       1.1       cgd  * Save the memory which is used by the current expression. This memory
    328       1.1       cgd  * is not freed by the next tfreeblk() call. The pointer returned can be
    329       1.1       cgd  * used to restore the memory.
    330       1.1       cgd  */
    331       1.1       cgd mbl_t *
    332       1.5     lukem tsave(void)
    333       1.1       cgd {
    334       1.1       cgd 	mbl_t	*tmem;
    335       1.1       cgd 
    336       1.1       cgd 	tmem = tmblk;
    337       1.1       cgd 	tmblk = NULL;
    338       1.1       cgd 	return (tmem);
    339       1.1       cgd }
    340       1.1       cgd 
    341       1.1       cgd /*
    342       1.1       cgd  * Free all memory used for the current expression and the memory used
    343       1.1       cgd  * be a previous expression and saved by tsave(). The next call to
    344       1.1       cgd  * tfreeblk() frees the restored memory.
    345       1.1       cgd  */
    346       1.1       cgd void
    347       1.5     lukem trestor(mbl_t *tmem)
    348       1.1       cgd {
    349       1.5     lukem 
    350       1.1       cgd 	tfreeblk();
    351       1.1       cgd 	if (tmblk != NULL) {
    352       1.1       cgd 		free(tmblk->blk);
    353       1.1       cgd 		free(tmblk);
    354       1.1       cgd 	}
    355       1.1       cgd 	tmblk = tmem;
    356       1.1       cgd }
    357