Commit | Line | Data |
---|---|---|
a7e60862 WJ |
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 91/12/05 07:56:35 brennan | |
15 | * 1.1 pre-release | |
16 | * | |
17 | */ | |
18 | ||
19 | /* zmalloc.c */ | |
20 | #include "mawk.h" | |
21 | #include "zmalloc.h" | |
22 | ||
23 | void PROTO( mawk_exit, (int) ) ; | |
24 | ||
25 | extern struct yacc_mem *yacc_memp ; | |
26 | ||
27 | /* | |
28 | zmalloc() gets mem from malloc() in CHUNKS of 2048 bytes | |
29 | and cuts these blocks into smaller pieces that are multiples | |
30 | of eight bytes. When a piece is returned via zfree(), it goes | |
31 | on a linked linear list indexed by its size. The lists are | |
32 | an array, pool[]. | |
33 | ||
34 | E.g., if you ask for 22 bytes with p = zmalloc(22), you actually get | |
35 | a piece of size 24. When you free it with zfree(p,22) , it is added | |
36 | to the list at pool[2]. | |
37 | */ | |
38 | ||
39 | #define POOLSZ 16 | |
40 | ||
41 | #define CHUNK 256 | |
42 | /* number of blocks to get from malloc */ | |
43 | ||
44 | static PTR PROTO( emalloc, (unsigned) ) ; | |
45 | void PROTO( errmsg, (int , char *, ...) ) ; | |
46 | ||
47 | static PTR emalloc(size) | |
48 | unsigned size ; | |
49 | { PTR p ; | |
50 | static char out[] = "out of memory" ; | |
51 | ||
52 | if( !(p = (PTR) malloc(SIZE_T(size))) ) | |
53 | if ( mawk_state == EXECUTION ) rt_error(out) ; | |
54 | else /* I don't think this will ever happen */ | |
55 | { compile_error(out) ; mawk_exit(1) ; } | |
56 | return p ; | |
57 | } | |
58 | ||
59 | ||
60 | typedef union zblock { | |
61 | char dummy[ZBLOCKSZ] ; | |
62 | union zblock *link ; | |
63 | } ZBLOCK ; | |
64 | ||
65 | /* ZBLOCKS of sizes 1, 2, ... 16 | |
66 | which is bytes of sizes 8, 16, ... , 128 | |
67 | are stored on the linked linear lists in | |
68 | pool[0], pool[1], ... , pool[15] | |
69 | */ | |
70 | ||
71 | static ZBLOCK *pool[POOLSZ] ; | |
72 | ||
73 | PTR bmalloc( blocks ) | |
74 | register unsigned blocks ; | |
75 | { | |
76 | register ZBLOCK *p ; | |
77 | static unsigned amt_avail ; | |
78 | static ZBLOCK *avail ; | |
79 | ||
80 | if ( blocks > POOLSZ ) return emalloc(blocks<<ZSHIFT) ; | |
81 | ||
82 | if ( p = pool[blocks-1] ) | |
83 | { pool[blocks-1] = p->link ; return (PTR) p ; } | |
84 | ||
85 | if ( blocks > amt_avail ) | |
86 | { if ( amt_avail ) /* free avail */ | |
87 | { avail->link = pool[--amt_avail] ; pool[amt_avail] = avail ; } | |
88 | ||
89 | /* use parser tables first */ | |
90 | if ( yacc_memp->zblocks >= blocks ) | |
91 | { avail = (ZBLOCK *) yacc_memp->mem ; | |
92 | amt_avail = yacc_memp++ -> zblocks ; | |
93 | /* make sure its -- aligned */ | |
94 | if ( (int) avail & 7 ) | |
95 | { avail = (ZBLOCK*)((char *)avail + 8 - ((int)avail&7)) ; | |
96 | amt_avail-- ; | |
97 | } | |
98 | } | |
99 | else | |
100 | if ( !(avail = (ZBLOCK *) malloc(SIZE_T(CHUNK*ZBLOCKSZ))) ) | |
101 | { /* if we get here, almost out of memory */ | |
102 | amt_avail = 0 ; | |
103 | return emalloc(blocks << ZSHIFT) ; | |
104 | } | |
105 | else amt_avail = CHUNK ; | |
106 | } | |
107 | ||
108 | /* get p from the avail pile */ | |
109 | p = avail ; avail += blocks ; amt_avail -= blocks ; | |
110 | return (PTR) p ; | |
111 | } | |
112 | ||
113 | void bfree( p, blocks) | |
114 | register PTR p ; | |
115 | register unsigned blocks ; | |
116 | { | |
117 | ||
118 | if ( blocks > POOLSZ ) free(p) ; | |
119 | else | |
120 | { | |
121 | ((ZBLOCK *)p)->link = pool[--blocks] ; | |
122 | pool[blocks] = (ZBLOCK *) p ; | |
123 | } | |
124 | } | |
125 | ||
126 | PTR zrealloc( p, old_size, new_size ) | |
127 | register PTR p ; | |
128 | unsigned old_size, new_size ; | |
129 | { register PTR q ; | |
130 | ||
131 | (void) memcpy(q = zmalloc(new_size), p, | |
132 | SIZE_T(old_size < new_size ? old_size : new_size)) ; | |
133 | ||
134 | zfree(p, old_size) ; | |
135 | return q ; | |
136 | } | |
137 | ||
138 |