4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * stable.c -- string table module
27 * simple string table module. all read-only strings are entered in
28 * this table, allowing us to compare pointers rather than characters
29 * to see if two strings are equal.
33 #pragma ident "%Z%%M% %I% %E% SMI"
42 #define MINPTR_ALIGN sizeof (char *) /* alignment boundary for pointers */
43 #define DEF_HASH_SIZE 11113 /* default hash table size */
44 #define CHUNK_SIZE 8192 /* grab more memory with this chunk size */
46 static char **Stable
; /* the hash table */
47 static unsigned Stablesz
;
48 static char *Stableblock
;
49 static char *Stablenext
;
51 static struct stats
*Stablecount
;
52 static struct stats
*Blockcount
;
53 static struct stats
*Add0
;
54 static struct stats
*Add1
;
55 static struct stats
*Add2
;
56 static struct stats
*Add3
;
57 static struct stats
*Addn
;
60 struct chunklst
*next
;
64 struct chunklst
*Stablechunks
;
67 * stable_init -- initialize the stable module
69 * hash table is sized according to sz. sz of zero means pick
70 * reasonable default size.
74 stable_init(unsigned sz
)
76 /* allocate hash table */
78 Stablesz
= DEF_HASH_SIZE
;
82 Stable
= MALLOC(Stablesz
* sizeof (*Stable
));
83 bzero((void *)Stable
, Stablesz
* sizeof (*Stable
));
85 Stablecount
= stats_new_counter("stable.size", "hash table size", 1);
86 Blockcount
= stats_new_counter("stable.blocks", "blocks allocated", 1);
87 Add0
= stats_new_counter("stable.add0", "adds to empty buckets", 1);
88 Add1
= stats_new_counter("stable.add1", "adds to 1-entry buckets", 1);
89 Add2
= stats_new_counter("stable.add2", "adds to 2-entry buckets", 1);
90 Add3
= stats_new_counter("stable.add3", "adds to 3-entry buckets", 1);
91 Addn
= stats_new_counter("stable.addn", "adds to n-entry buckets", 1);
93 stats_counter_add(Stablecount
, Stablesz
);
99 struct chunklst
*cp
, *nc
;
101 stats_delete(Stablecount
);
102 stats_delete(Blockcount
);
122 stable_newchunk(void)
124 struct chunklst
*save
= Stablechunks
;
127 n
= MALLOC(CHUNK_SIZE
);
128 bzero((void *)n
, CHUNK_SIZE
);
129 stats_counter_bump(Blockcount
);
131 Stablechunks
= MALLOC(sizeof (struct chunklst
));
132 Stablechunks
->next
= save
;
133 Stablechunks
->chunkp
= n
;
138 * stable -- create/lookup a string table entry
142 stable(const char *s
)
145 unsigned hash
= DEF_HASH_SIZE
^ ((unsigned)*s
<< 2);
153 out(O_DIE
, "internal error: Stablesz not set");
155 for (sptr
= &s
[1]; *sptr
; sptr
++) {
157 hash
^= (((unsigned)*sptr
) << (slen
% 3)) +
158 ((unsigned)*(sptr
- 1) << ((slen
% 3 + 7)));
161 if (slen
> CHUNK_SIZE
- sizeof (char *) - 1 - 4)
162 out(O_DIE
, "too big for string table %.20s...", s
);
165 ptrp
= &Stable
[hash
];
168 /* hash brought us to something, see if it is the string */
171 while (*sptr
&& *eptr
&& *sptr
++ == *eptr
++)
173 if (*sptr
== '\0' && *eptr
== '\0')
174 return (ptr
); /* found it */
175 /* strings didn't match, advance eptr to end of string */
178 eptr
++; /* move past '\0' */
179 while ((uintptr_t)eptr
% MINPTR_ALIGN
)
181 /* pull in next pointer in bucket */
182 ptrp
= (char **)(void *)eptr
;
187 /* string wasn't in table, add it and point ptr to it */
188 if (Stablenext
== NULL
|| (&Stableblock
[CHUNK_SIZE
] - Stablenext
) <
189 (slen
+ sizeof (char *) + MINPTR_ALIGN
+ 4)) {
191 Stablenext
= Stableblock
= stable_newchunk();
193 /* current chunk has room in it */
194 ptr
= *ptrp
= Stablenext
;
196 while (*Stablenext
++ = *sptr
++)
198 while ((uintptr_t)Stablenext
% MINPTR_ALIGN
)
200 ptrp
= (char **)(void *)Stablenext
;
201 Stablenext
+= sizeof (char *);
204 /* just did an add, update stats */
206 stats_counter_bump(Add0
);
207 else if (collisions
== 1)
208 stats_counter_bump(Add1
);
209 else if (collisions
== 2)
210 stats_counter_bump(Add2
);
211 else if (collisions
== 3)
212 stats_counter_bump(Add3
);
214 stats_counter_bump(Addn
);