xref: /386bsd/usr/src/usr.bin/awk/zmalloc.c (revision a2142627)
1 
2 /********************************************
3 zmalloc.c
4 copyright 1991, Michael D. Brennan
5 
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
8 
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
12 
13 /*$Log: zmalloc.c,v $
14  * Revision 5.1.1.1  1993/02/06  11:12:19  mike
15  * fix bug in reuse of parser table memory
16  * for most users ifdef the mess out
17  *
18  * Revision 5.1  1991/12/05  07:56:35  brennan
19  * 1.1 pre-release
20  *
21 */
22 
23 /*  zmalloc.c  */
24 #include  "mawk.h"
25 #include  "zmalloc.h"
26 
27 void PROTO( mawk_exit, (int) ) ;
28 
29 extern  struct yacc_mem  *yacc_memp ;
30 
31 /*
32   zmalloc() gets mem from malloc() in CHUNKS of 2048 bytes
33   and cuts these blocks into smaller pieces that are multiples
34   of eight bytes.  When a piece is returned via zfree(), it goes
35   on a linked linear list indexed by its size.  The lists are
36   an array, pool[].
37 
38   E.g., if you ask for 22 bytes with p = zmalloc(22), you actually get
39   a piece of size 24.  When you free it with zfree(p,22) , it is added
40   to the list at pool[2].
41 */
42 
43 #define POOLSZ      16
44 
45 #define  CHUNK          256
46         /* number of blocks to get from malloc */
47 
48 static PTR  PROTO( emalloc, (unsigned) ) ;
49 void PROTO( errmsg, (int , char *, ...) ) ;
50 
emalloc(size)51 static PTR emalloc(size)
52   unsigned size ;
53 { PTR p ;
54   static char out[] = "out of memory" ;
55 
56   if( !(p = (PTR) malloc(SIZE_T(size))) )
57 	if ( mawk_state == EXECUTION ) rt_error(out) ;
58 	else /* I don't think this will ever happen */
59 	{ compile_error(out) ; mawk_exit(1) ; }
60   return p ;
61 }
62 
63 
64 typedef  union  zblock {
65 char dummy[ZBLOCKSZ] ;
66 union zblock *link ;
67 }  ZBLOCK  ;
68 
69 /* ZBLOCKS of sizes 1, 2, ... 16
70    which is bytes of sizes 8, 16, ... , 128
71    are stored on the linked linear lists in
72    pool[0], pool[1], ... , pool[15]
73 */
74 
75 static  ZBLOCK  *pool[POOLSZ] ;
76 
bmalloc(blocks)77 PTR   bmalloc( blocks )
78   register unsigned blocks ;
79 {
80   register ZBLOCK *p ;
81   static  unsigned amt_avail ;
82   static  ZBLOCK  *avail ;
83 
84   if ( blocks > POOLSZ )  return emalloc(blocks<<ZSHIFT) ;
85 
86   if ( p = pool[blocks-1] )
87   { pool[blocks-1] = p->link ; return (PTR) p ; }
88 
89   if ( blocks > amt_avail )
90   {
91     if ( amt_avail != 0 ) /* free avail */
92     {
93       avail->link = pool[--amt_avail] ;
94       pool[amt_avail] = avail ;
95     }
96 
97 #if MSDOS || HAVE_SMALL_MEMORY
98 /* this hack is dangerous (I've blown it twice), not portable,
99    and counts on byacc not changing, but it is a big win on
100    DOS.  On paged vmem systems it is a nop so ifdef it out.
101 */
102     /* use parser tables first */
103     if ( yacc_memp->zblocks > blocks )
104     {
105       avail = (ZBLOCK *) yacc_memp->mem ;
106       amt_avail = yacc_memp++ -> zblocks ;
107       /* make sure its -- aligned */
108       {
109 	int k = (int) avail & 7 ;
110         if ( k )
111         {
112 	  avail = (ZBLOCK*)((char *)avail + (8-k)) ;
113 	  amt_avail-- ;
114 	}
115       }
116     }
117     else
118 #endif
119 
120     if ( !(avail = (ZBLOCK *) malloc(SIZE_T(CHUNK*ZBLOCKSZ))) )
121     { /* if we get here, almost out of memory */
122         amt_avail = 0 ;
123 	return  emalloc(blocks << ZSHIFT) ;
124     }
125     else  amt_avail = CHUNK ;
126   }
127 
128   /* get p from the avail pile */
129   p = avail ; avail += blocks ; amt_avail -= blocks ;
130   return (PTR) p ;
131 }
132 
bfree(p,blocks)133 void  bfree( p, blocks)
134   register PTR p ;
135   register unsigned blocks ;
136 {
137 
138   if ( blocks > POOLSZ )  free(p) ;
139   else
140   {
141     ((ZBLOCK *)p)->link = pool[--blocks] ;
142     pool[blocks] = (ZBLOCK *) p ;
143   }
144 }
145 
zrealloc(p,old_size,new_size)146 PTR  zrealloc( p, old_size, new_size )
147   register PTR  p ;
148   unsigned old_size, new_size ;
149 { register PTR q ;
150 
151   (void) memcpy(q = zmalloc(new_size), p,
152                 SIZE_T(old_size < new_size ? old_size : new_size)) ;
153 
154   zfree(p, old_size) ;
155   return q ;
156 }
157 
158 
159