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