xref: /aosp_15_r20/external/mesa3d/src/glx/glxhash.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /* glxhash.c -- Small hash table support for integer -> integer mapping
2*61046927SAndroid Build Coastguard Worker  * Taken from libdrm.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Created: Sun Apr 18 09:35:45 1999 by [email protected]
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
7*61046927SAndroid Build Coastguard Worker  * All Rights Reserved.
8*61046927SAndroid Build Coastguard Worker  *
9*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
10*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
11*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
12*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
14*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
15*61046927SAndroid Build Coastguard Worker  *
16*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
17*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
18*61046927SAndroid Build Coastguard Worker  * Software.
19*61046927SAndroid Build Coastguard Worker  *
20*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23*61046927SAndroid Build Coastguard Worker  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26*61046927SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
27*61046927SAndroid Build Coastguard Worker  *
28*61046927SAndroid Build Coastguard Worker  * Authors: Rickard E. (Rik) Faith <[email protected]>
29*61046927SAndroid Build Coastguard Worker  *
30*61046927SAndroid Build Coastguard Worker  * DESCRIPTION
31*61046927SAndroid Build Coastguard Worker  *
32*61046927SAndroid Build Coastguard Worker  * This file contains a straightforward implementation of a fixed-sized
33*61046927SAndroid Build Coastguard Worker  * hash table using self-organizing linked lists [Knuth73, pp. 398-399] for
34*61046927SAndroid Build Coastguard Worker  * collision resolution.  There are two potentially interesting things
35*61046927SAndroid Build Coastguard Worker  * about this implementation:
36*61046927SAndroid Build Coastguard Worker  *
37*61046927SAndroid Build Coastguard Worker  * 1) The table is power-of-two sized.  Prime sized tables are more
38*61046927SAndroid Build Coastguard Worker  * traditional, but do not have a significant advantage over power-of-two
39*61046927SAndroid Build Coastguard Worker  * sized table, especially when double hashing is not used for collision
40*61046927SAndroid Build Coastguard Worker  * resolution.
41*61046927SAndroid Build Coastguard Worker  *
42*61046927SAndroid Build Coastguard Worker  * 2) The hash computation uses a table of random integers [Hanson97,
43*61046927SAndroid Build Coastguard Worker  * pp. 39-41].
44*61046927SAndroid Build Coastguard Worker  *
45*61046927SAndroid Build Coastguard Worker  * FUTURE ENHANCEMENTS
46*61046927SAndroid Build Coastguard Worker  *
47*61046927SAndroid Build Coastguard Worker  * With a table size of 512, the current implementation is sufficient for a
48*61046927SAndroid Build Coastguard Worker  * few hundred keys.  Since this is well above the expected size of the
49*61046927SAndroid Build Coastguard Worker  * tables for which this implementation was designed, the implementation of
50*61046927SAndroid Build Coastguard Worker  * dynamic hash tables was postponed until the need arises.  A common (and
51*61046927SAndroid Build Coastguard Worker  * naive) approach to dynamic hash table implementation simply creates a
52*61046927SAndroid Build Coastguard Worker  * new hash table when necessary, rehashes all the data into the new table,
53*61046927SAndroid Build Coastguard Worker  * and destroys the old table.  The approach in [Larson88] is superior in
54*61046927SAndroid Build Coastguard Worker  * two ways: 1) only a portion of the table is expanded when needed,
55*61046927SAndroid Build Coastguard Worker  * distributing the expansion cost over several insertions, and 2) portions
56*61046927SAndroid Build Coastguard Worker  * of the table can be locked, enabling a scalable thread-safe
57*61046927SAndroid Build Coastguard Worker  * implementation.
58*61046927SAndroid Build Coastguard Worker  *
59*61046927SAndroid Build Coastguard Worker  * REFERENCES
60*61046927SAndroid Build Coastguard Worker  *
61*61046927SAndroid Build Coastguard Worker  * [Hanson97] David R. Hanson.  C Interfaces and Implementations:
62*61046927SAndroid Build Coastguard Worker  * Techniques for Creating Reusable Software.  Reading, Massachusetts:
63*61046927SAndroid Build Coastguard Worker  * Addison-Wesley, 1997.
64*61046927SAndroid Build Coastguard Worker  *
65*61046927SAndroid Build Coastguard Worker  * [Knuth73] Donald E. Knuth. The Art of Computer Programming.  Volume 3:
66*61046927SAndroid Build Coastguard Worker  * Sorting and Searching.  Reading, Massachusetts: Addison-Wesley, 1973.
67*61046927SAndroid Build Coastguard Worker  *
68*61046927SAndroid Build Coastguard Worker  * [Larson88] Per-Ake Larson. "Dynamic Hash Tables".  CACM 31(4), April
69*61046927SAndroid Build Coastguard Worker  * 1988, pp. 446-457.
70*61046927SAndroid Build Coastguard Worker  *
71*61046927SAndroid Build Coastguard Worker  */
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker #include "glxhash.h"
74*61046927SAndroid Build Coastguard Worker #include <X11/Xfuncproto.h>
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker #define HASH_MAIN 0
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker #include <stdio.h>
79*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
80*61046927SAndroid Build Coastguard Worker #include <string.h>
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker #define HASH_MAGIC 0xdeadbeef
83*61046927SAndroid Build Coastguard Worker #define HASH_DEBUG 0
84*61046927SAndroid Build Coastguard Worker #define HASH_SIZE  512          /* Good for about 100 entries */
85*61046927SAndroid Build Coastguard Worker                                 /* If you change this value, you probably
86*61046927SAndroid Build Coastguard Worker                                    have to change the HashHash hashing
87*61046927SAndroid Build Coastguard Worker                                    function! */
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker #define HASH_ALLOC malloc
90*61046927SAndroid Build Coastguard Worker #define HASH_FREE  free
91*61046927SAndroid Build Coastguard Worker #ifndef HAVE_RANDOM_R
92*61046927SAndroid Build Coastguard Worker #define HASH_RANDOM_DECL   char *ps, rs[256]
93*61046927SAndroid Build Coastguard Worker #define HASH_RANDOM_INIT(seed)   ps = initstate(seed, rs, sizeof(rs))
94*61046927SAndroid Build Coastguard Worker #define HASH_RANDOM      random()
95*61046927SAndroid Build Coastguard Worker #define HASH_RANDOM_DESTROY   setstate(ps)
96*61046927SAndroid Build Coastguard Worker #else
97*61046927SAndroid Build Coastguard Worker #define HASH_RANDOM_DECL   struct random_data rd; int32_t rv; char rs[256]
98*61046927SAndroid Build Coastguard Worker #define HASH_RANDOM_INIT(seed)               \
99*61046927SAndroid Build Coastguard Worker    do {                        \
100*61046927SAndroid Build Coastguard Worker       (void) memset(&rd, 0, sizeof(rd));         \
101*61046927SAndroid Build Coastguard Worker       (void) initstate_r(seed, rs, sizeof(rs), &rd);      \
102*61046927SAndroid Build Coastguard Worker    } while(0)
103*61046927SAndroid Build Coastguard Worker #define HASH_RANDOM             ((void) random_r(&rd, &rv), rv)
104*61046927SAndroid Build Coastguard Worker #define HASH_RANDOM_DESTROY
105*61046927SAndroid Build Coastguard Worker #endif
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker typedef struct __glxHashBucket
108*61046927SAndroid Build Coastguard Worker {
109*61046927SAndroid Build Coastguard Worker    unsigned long key;
110*61046927SAndroid Build Coastguard Worker    void *value;
111*61046927SAndroid Build Coastguard Worker    struct __glxHashBucket *next;
112*61046927SAndroid Build Coastguard Worker } __glxHashBucket, *__glxHashBucketPtr;
113*61046927SAndroid Build Coastguard Worker 
114*61046927SAndroid Build Coastguard Worker typedef struct __glxHashTable *__glxHashTablePtr;
115*61046927SAndroid Build Coastguard Worker struct __glxHashTable
116*61046927SAndroid Build Coastguard Worker {
117*61046927SAndroid Build Coastguard Worker    unsigned long magic;
118*61046927SAndroid Build Coastguard Worker    unsigned long hits;          /* At top of linked list */
119*61046927SAndroid Build Coastguard Worker    unsigned long partials;      /* Not at top of linked list */
120*61046927SAndroid Build Coastguard Worker    unsigned long misses;        /* Not in table */
121*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr buckets[HASH_SIZE];
122*61046927SAndroid Build Coastguard Worker    int p0;
123*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr p1;
124*61046927SAndroid Build Coastguard Worker };
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker static unsigned long
HashHash(unsigned long key)127*61046927SAndroid Build Coastguard Worker HashHash(unsigned long key)
128*61046927SAndroid Build Coastguard Worker {
129*61046927SAndroid Build Coastguard Worker    unsigned long hash = 0;
130*61046927SAndroid Build Coastguard Worker    unsigned long tmp = key;
131*61046927SAndroid Build Coastguard Worker    static int init = 0;
132*61046927SAndroid Build Coastguard Worker    static unsigned long scatter[256];
133*61046927SAndroid Build Coastguard Worker    int i;
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker    if (!init) {
136*61046927SAndroid Build Coastguard Worker       HASH_RANDOM_DECL;
137*61046927SAndroid Build Coastguard Worker       HASH_RANDOM_INIT(37);
138*61046927SAndroid Build Coastguard Worker       for (i = 0; i < 256; i++)
139*61046927SAndroid Build Coastguard Worker          scatter[i] = HASH_RANDOM;
140*61046927SAndroid Build Coastguard Worker       HASH_RANDOM_DESTROY;
141*61046927SAndroid Build Coastguard Worker       ++init;
142*61046927SAndroid Build Coastguard Worker    }
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    while (tmp) {
145*61046927SAndroid Build Coastguard Worker       hash = (hash << 1) + scatter[tmp & 0xff];
146*61046927SAndroid Build Coastguard Worker       tmp >>= 8;
147*61046927SAndroid Build Coastguard Worker    }
148*61046927SAndroid Build Coastguard Worker 
149*61046927SAndroid Build Coastguard Worker    hash %= HASH_SIZE;
150*61046927SAndroid Build Coastguard Worker #if HASH_DEBUG
151*61046927SAndroid Build Coastguard Worker    printf("Hash(%d) = %d\n", key, hash);
152*61046927SAndroid Build Coastguard Worker #endif
153*61046927SAndroid Build Coastguard Worker    return hash;
154*61046927SAndroid Build Coastguard Worker }
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker _X_HIDDEN __glxHashTable *
__glxHashCreate(void)157*61046927SAndroid Build Coastguard Worker __glxHashCreate(void)
158*61046927SAndroid Build Coastguard Worker {
159*61046927SAndroid Build Coastguard Worker    __glxHashTablePtr table;
160*61046927SAndroid Build Coastguard Worker    int i;
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker    table = HASH_ALLOC(sizeof(*table));
163*61046927SAndroid Build Coastguard Worker    if (!table)
164*61046927SAndroid Build Coastguard Worker       return NULL;
165*61046927SAndroid Build Coastguard Worker    table->magic = HASH_MAGIC;
166*61046927SAndroid Build Coastguard Worker    table->hits = 0;
167*61046927SAndroid Build Coastguard Worker    table->partials = 0;
168*61046927SAndroid Build Coastguard Worker    table->misses = 0;
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker    for (i = 0; i < HASH_SIZE; i++)
171*61046927SAndroid Build Coastguard Worker       table->buckets[i] = NULL;
172*61046927SAndroid Build Coastguard Worker    return table;
173*61046927SAndroid Build Coastguard Worker }
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker _X_HIDDEN int
__glxHashDestroy(__glxHashTable * t)176*61046927SAndroid Build Coastguard Worker __glxHashDestroy(__glxHashTable * t)
177*61046927SAndroid Build Coastguard Worker {
178*61046927SAndroid Build Coastguard Worker    __glxHashTablePtr table = (__glxHashTablePtr) t;
179*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr bucket;
180*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr next;
181*61046927SAndroid Build Coastguard Worker    int i;
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker    if (table->magic != HASH_MAGIC)
184*61046927SAndroid Build Coastguard Worker       return -1;                /* Bad magic */
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker    for (i = 0; i < HASH_SIZE; i++) {
187*61046927SAndroid Build Coastguard Worker       for (bucket = table->buckets[i]; bucket;) {
188*61046927SAndroid Build Coastguard Worker          next = bucket->next;
189*61046927SAndroid Build Coastguard Worker          HASH_FREE(bucket);
190*61046927SAndroid Build Coastguard Worker          bucket = next;
191*61046927SAndroid Build Coastguard Worker       }
192*61046927SAndroid Build Coastguard Worker    }
193*61046927SAndroid Build Coastguard Worker    HASH_FREE(table);
194*61046927SAndroid Build Coastguard Worker    return 0;
195*61046927SAndroid Build Coastguard Worker }
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker /* Find the bucket and organize the list so that this bucket is at the
198*61046927SAndroid Build Coastguard Worker    top. */
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker static __glxHashBucketPtr
HashFind(__glxHashTablePtr table,unsigned long key,unsigned long * h)201*61046927SAndroid Build Coastguard Worker HashFind(__glxHashTablePtr table, unsigned long key, unsigned long *h)
202*61046927SAndroid Build Coastguard Worker {
203*61046927SAndroid Build Coastguard Worker    unsigned long hash = HashHash(key);
204*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr prev = NULL;
205*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr bucket;
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker    if (h)
208*61046927SAndroid Build Coastguard Worker       *h = hash;
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) {
211*61046927SAndroid Build Coastguard Worker       if (bucket->key == key) {
212*61046927SAndroid Build Coastguard Worker          if (prev) {
213*61046927SAndroid Build Coastguard Worker             /* Organize */
214*61046927SAndroid Build Coastguard Worker             prev->next = bucket->next;
215*61046927SAndroid Build Coastguard Worker             bucket->next = table->buckets[hash];
216*61046927SAndroid Build Coastguard Worker             table->buckets[hash] = bucket;
217*61046927SAndroid Build Coastguard Worker             ++table->partials;
218*61046927SAndroid Build Coastguard Worker          }
219*61046927SAndroid Build Coastguard Worker          else {
220*61046927SAndroid Build Coastguard Worker             ++table->hits;
221*61046927SAndroid Build Coastguard Worker          }
222*61046927SAndroid Build Coastguard Worker          return bucket;
223*61046927SAndroid Build Coastguard Worker       }
224*61046927SAndroid Build Coastguard Worker       prev = bucket;
225*61046927SAndroid Build Coastguard Worker    }
226*61046927SAndroid Build Coastguard Worker    ++table->misses;
227*61046927SAndroid Build Coastguard Worker    return NULL;
228*61046927SAndroid Build Coastguard Worker }
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker _X_HIDDEN int
__glxHashLookup(__glxHashTable * t,unsigned long key,void ** value)231*61046927SAndroid Build Coastguard Worker __glxHashLookup(__glxHashTable * t, unsigned long key, void **value)
232*61046927SAndroid Build Coastguard Worker {
233*61046927SAndroid Build Coastguard Worker    __glxHashTablePtr table = (__glxHashTablePtr) t;
234*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr bucket;
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker    if (!table || table->magic != HASH_MAGIC)
237*61046927SAndroid Build Coastguard Worker       return -1;                /* Bad magic */
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    bucket = HashFind(table, key, NULL);
240*61046927SAndroid Build Coastguard Worker    if (!bucket)
241*61046927SAndroid Build Coastguard Worker       return 1;                 /* Not found */
242*61046927SAndroid Build Coastguard Worker    *value = bucket->value;
243*61046927SAndroid Build Coastguard Worker    return 0;                    /* Found */
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker _X_HIDDEN int
__glxHashInsert(__glxHashTable * t,unsigned long key,void * value)247*61046927SAndroid Build Coastguard Worker __glxHashInsert(__glxHashTable * t, unsigned long key, void *value)
248*61046927SAndroid Build Coastguard Worker {
249*61046927SAndroid Build Coastguard Worker    __glxHashTablePtr table = (__glxHashTablePtr) t;
250*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr bucket;
251*61046927SAndroid Build Coastguard Worker    unsigned long hash;
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker    if (table->magic != HASH_MAGIC)
254*61046927SAndroid Build Coastguard Worker       return -1;                /* Bad magic */
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker    if (HashFind(table, key, &hash))
257*61046927SAndroid Build Coastguard Worker       return 1;                 /* Already in table */
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker    bucket = HASH_ALLOC(sizeof(*bucket));
260*61046927SAndroid Build Coastguard Worker    if (!bucket)
261*61046927SAndroid Build Coastguard Worker       return -1;                /* Error */
262*61046927SAndroid Build Coastguard Worker    bucket->key = key;
263*61046927SAndroid Build Coastguard Worker    bucket->value = value;
264*61046927SAndroid Build Coastguard Worker    bucket->next = table->buckets[hash];
265*61046927SAndroid Build Coastguard Worker    table->buckets[hash] = bucket;
266*61046927SAndroid Build Coastguard Worker #if HASH_DEBUG
267*61046927SAndroid Build Coastguard Worker    printf("Inserted %d at %d/%p\n", key, hash, bucket);
268*61046927SAndroid Build Coastguard Worker #endif
269*61046927SAndroid Build Coastguard Worker    return 0;                    /* Added to table */
270*61046927SAndroid Build Coastguard Worker }
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker _X_HIDDEN int
__glxHashDelete(__glxHashTable * t,unsigned long key)273*61046927SAndroid Build Coastguard Worker __glxHashDelete(__glxHashTable * t, unsigned long key)
274*61046927SAndroid Build Coastguard Worker {
275*61046927SAndroid Build Coastguard Worker    __glxHashTablePtr table = (__glxHashTablePtr) t;
276*61046927SAndroid Build Coastguard Worker    unsigned long hash;
277*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr bucket;
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    if (table->magic != HASH_MAGIC)
280*61046927SAndroid Build Coastguard Worker       return -1;                /* Bad magic */
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker    bucket = HashFind(table, key, &hash);
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker    if (!bucket)
285*61046927SAndroid Build Coastguard Worker       return 1;                 /* Not found */
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker    table->buckets[hash] = bucket->next;
288*61046927SAndroid Build Coastguard Worker    HASH_FREE(bucket);
289*61046927SAndroid Build Coastguard Worker    return 0;
290*61046927SAndroid Build Coastguard Worker }
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker _X_HIDDEN int
__glxHashNext(__glxHashTable * t,unsigned long * key,void ** value)293*61046927SAndroid Build Coastguard Worker __glxHashNext(__glxHashTable * t, unsigned long *key, void **value)
294*61046927SAndroid Build Coastguard Worker {
295*61046927SAndroid Build Coastguard Worker    __glxHashTablePtr table = (__glxHashTablePtr) t;
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker    while (table->p0 < HASH_SIZE) {
298*61046927SAndroid Build Coastguard Worker       if (table->p1) {
299*61046927SAndroid Build Coastguard Worker          *key = table->p1->key;
300*61046927SAndroid Build Coastguard Worker          *value = table->p1->value;
301*61046927SAndroid Build Coastguard Worker          table->p1 = table->p1->next;
302*61046927SAndroid Build Coastguard Worker          return 1;
303*61046927SAndroid Build Coastguard Worker       }
304*61046927SAndroid Build Coastguard Worker       table->p1 = table->buckets[table->p0];
305*61046927SAndroid Build Coastguard Worker       ++table->p0;
306*61046927SAndroid Build Coastguard Worker    }
307*61046927SAndroid Build Coastguard Worker    return 0;
308*61046927SAndroid Build Coastguard Worker }
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker _X_HIDDEN int
__glxHashFirst(__glxHashTable * t,unsigned long * key,void ** value)311*61046927SAndroid Build Coastguard Worker __glxHashFirst(__glxHashTable * t, unsigned long *key, void **value)
312*61046927SAndroid Build Coastguard Worker {
313*61046927SAndroid Build Coastguard Worker    __glxHashTablePtr table = (__glxHashTablePtr) t;
314*61046927SAndroid Build Coastguard Worker 
315*61046927SAndroid Build Coastguard Worker    if (table->magic != HASH_MAGIC)
316*61046927SAndroid Build Coastguard Worker       return -1;                /* Bad magic */
317*61046927SAndroid Build Coastguard Worker 
318*61046927SAndroid Build Coastguard Worker    table->p0 = 0;
319*61046927SAndroid Build Coastguard Worker    table->p1 = table->buckets[0];
320*61046927SAndroid Build Coastguard Worker    return __glxHashNext(table, key, value);
321*61046927SAndroid Build Coastguard Worker }
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker #if HASH_MAIN
324*61046927SAndroid Build Coastguard Worker #define DIST_LIMIT 10
325*61046927SAndroid Build Coastguard Worker static int dist[DIST_LIMIT];
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker static void
clear_dist(void)328*61046927SAndroid Build Coastguard Worker clear_dist(void)
329*61046927SAndroid Build Coastguard Worker {
330*61046927SAndroid Build Coastguard Worker    int i;
331*61046927SAndroid Build Coastguard Worker 
332*61046927SAndroid Build Coastguard Worker    for (i = 0; i < DIST_LIMIT; i++)
333*61046927SAndroid Build Coastguard Worker       dist[i] = 0;
334*61046927SAndroid Build Coastguard Worker }
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker static int
count_entries(__glxHashBucketPtr bucket)337*61046927SAndroid Build Coastguard Worker count_entries(__glxHashBucketPtr bucket)
338*61046927SAndroid Build Coastguard Worker {
339*61046927SAndroid Build Coastguard Worker    int count = 0;
340*61046927SAndroid Build Coastguard Worker 
341*61046927SAndroid Build Coastguard Worker    for (; bucket; bucket = bucket->next)
342*61046927SAndroid Build Coastguard Worker       ++count;
343*61046927SAndroid Build Coastguard Worker    return count;
344*61046927SAndroid Build Coastguard Worker }
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker static void
update_dist(int count)347*61046927SAndroid Build Coastguard Worker update_dist(int count)
348*61046927SAndroid Build Coastguard Worker {
349*61046927SAndroid Build Coastguard Worker    if (count >= DIST_LIMIT)
350*61046927SAndroid Build Coastguard Worker       ++dist[DIST_LIMIT - 1];
351*61046927SAndroid Build Coastguard Worker    else
352*61046927SAndroid Build Coastguard Worker       ++dist[count];
353*61046927SAndroid Build Coastguard Worker }
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker static void
compute_dist(__glxHashTablePtr table)356*61046927SAndroid Build Coastguard Worker compute_dist(__glxHashTablePtr table)
357*61046927SAndroid Build Coastguard Worker {
358*61046927SAndroid Build Coastguard Worker    int i;
359*61046927SAndroid Build Coastguard Worker    __glxHashBucketPtr bucket;
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker    printf("Hits = %ld, partials = %ld, misses = %ld\n",
362*61046927SAndroid Build Coastguard Worker           table->hits, table->partials, table->misses);
363*61046927SAndroid Build Coastguard Worker    clear_dist();
364*61046927SAndroid Build Coastguard Worker    for (i = 0; i < HASH_SIZE; i++) {
365*61046927SAndroid Build Coastguard Worker       bucket = table->buckets[i];
366*61046927SAndroid Build Coastguard Worker       update_dist(count_entries(bucket));
367*61046927SAndroid Build Coastguard Worker    }
368*61046927SAndroid Build Coastguard Worker    for (i = 0; i < DIST_LIMIT; i++) {
369*61046927SAndroid Build Coastguard Worker       if (i != DIST_LIMIT - 1)
370*61046927SAndroid Build Coastguard Worker          printf("%5d %10d\n", i, dist[i]);
371*61046927SAndroid Build Coastguard Worker       else
372*61046927SAndroid Build Coastguard Worker          printf("other %10d\n", dist[i]);
373*61046927SAndroid Build Coastguard Worker    }
374*61046927SAndroid Build Coastguard Worker }
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker static void
check_table(__glxHashTablePtr table,unsigned long key,unsigned long value)377*61046927SAndroid Build Coastguard Worker check_table(__glxHashTablePtr table, unsigned long key, unsigned long value)
378*61046927SAndroid Build Coastguard Worker {
379*61046927SAndroid Build Coastguard Worker    unsigned long retval = 0;
380*61046927SAndroid Build Coastguard Worker    int retcode = __glxHashLookup(table, key, &retval);
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    switch (retcode) {
383*61046927SAndroid Build Coastguard Worker    case -1:
384*61046927SAndroid Build Coastguard Worker       printf("Bad magic = 0x%08lx:"
385*61046927SAndroid Build Coastguard Worker              " key = %lu, expected = %lu, returned = %lu\n",
386*61046927SAndroid Build Coastguard Worker              table->magic, key, value, retval);
387*61046927SAndroid Build Coastguard Worker       break;
388*61046927SAndroid Build Coastguard Worker    case 1:
389*61046927SAndroid Build Coastguard Worker       printf("Not found: key = %lu, expected = %lu returned = %lu\n",
390*61046927SAndroid Build Coastguard Worker              key, value, retval);
391*61046927SAndroid Build Coastguard Worker       break;
392*61046927SAndroid Build Coastguard Worker    case 0:
393*61046927SAndroid Build Coastguard Worker       if (value != retval)
394*61046927SAndroid Build Coastguard Worker          printf("Bad value: key = %lu, expected = %lu, returned = %lu\n",
395*61046927SAndroid Build Coastguard Worker                 key, value, retval);
396*61046927SAndroid Build Coastguard Worker       break;
397*61046927SAndroid Build Coastguard Worker    default:
398*61046927SAndroid Build Coastguard Worker       printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n",
399*61046927SAndroid Build Coastguard Worker              retcode, key, value, retval);
400*61046927SAndroid Build Coastguard Worker       break;
401*61046927SAndroid Build Coastguard Worker    }
402*61046927SAndroid Build Coastguard Worker }
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker int
main(void)405*61046927SAndroid Build Coastguard Worker main(void)
406*61046927SAndroid Build Coastguard Worker {
407*61046927SAndroid Build Coastguard Worker    __glxHashTablePtr table;
408*61046927SAndroid Build Coastguard Worker    int i;
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker    printf("\n***** 256 consecutive integers ****\n");
411*61046927SAndroid Build Coastguard Worker    table = __glxHashCreate();
412*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 256; i++)
413*61046927SAndroid Build Coastguard Worker       __glxHashInsert(table, i, i);
414*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 256; i++)
415*61046927SAndroid Build Coastguard Worker       check_table(table, i, i);
416*61046927SAndroid Build Coastguard Worker    for (i = 256; i >= 0; i--)
417*61046927SAndroid Build Coastguard Worker       check_table(table, i, i);
418*61046927SAndroid Build Coastguard Worker    compute_dist(table);
419*61046927SAndroid Build Coastguard Worker    __glxHashDestroy(table);
420*61046927SAndroid Build Coastguard Worker 
421*61046927SAndroid Build Coastguard Worker    printf("\n***** 1024 consecutive integers ****\n");
422*61046927SAndroid Build Coastguard Worker    table = __glxHashCreate();
423*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 1024; i++)
424*61046927SAndroid Build Coastguard Worker       __glxHashInsert(table, i, i);
425*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 1024; i++)
426*61046927SAndroid Build Coastguard Worker       check_table(table, i, i);
427*61046927SAndroid Build Coastguard Worker    for (i = 1024; i >= 0; i--)
428*61046927SAndroid Build Coastguard Worker       check_table(table, i, i);
429*61046927SAndroid Build Coastguard Worker    compute_dist(table);
430*61046927SAndroid Build Coastguard Worker    __glxHashDestroy(table);
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker    printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
433*61046927SAndroid Build Coastguard Worker    table = __glxHashCreate();
434*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 1024; i++)
435*61046927SAndroid Build Coastguard Worker       __glxHashInsert(table, i * 4096, i);
436*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 1024; i++)
437*61046927SAndroid Build Coastguard Worker       check_table(table, i * 4096, i);
438*61046927SAndroid Build Coastguard Worker    for (i = 1024; i >= 0; i--)
439*61046927SAndroid Build Coastguard Worker       check_table(table, i * 4096, i);
440*61046927SAndroid Build Coastguard Worker    compute_dist(table);
441*61046927SAndroid Build Coastguard Worker    __glxHashDestroy(table);
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker    printf("\n***** 1024 random integers ****\n");
444*61046927SAndroid Build Coastguard Worker    table = __glxHashCreate();
445*61046927SAndroid Build Coastguard Worker    srandom(0xbeefbeef);
446*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 1024; i++)
447*61046927SAndroid Build Coastguard Worker       __glxHashInsert(table, random(), i);
448*61046927SAndroid Build Coastguard Worker    srandom(0xbeefbeef);
449*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 1024; i++)
450*61046927SAndroid Build Coastguard Worker       check_table(table, random(), i);
451*61046927SAndroid Build Coastguard Worker    srandom(0xbeefbeef);
452*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 1024; i++)
453*61046927SAndroid Build Coastguard Worker       check_table(table, random(), i);
454*61046927SAndroid Build Coastguard Worker    compute_dist(table);
455*61046927SAndroid Build Coastguard Worker    __glxHashDestroy(table);
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker    printf("\n***** 5000 random integers ****\n");
458*61046927SAndroid Build Coastguard Worker    table = __glxHashCreate();
459*61046927SAndroid Build Coastguard Worker    srandom(0xbeefbeef);
460*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 5000; i++)
461*61046927SAndroid Build Coastguard Worker       __glxHashInsert(table, random(), i);
462*61046927SAndroid Build Coastguard Worker    srandom(0xbeefbeef);
463*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 5000; i++)
464*61046927SAndroid Build Coastguard Worker       check_table(table, random(), i);
465*61046927SAndroid Build Coastguard Worker    srandom(0xbeefbeef);
466*61046927SAndroid Build Coastguard Worker    for (i = 0; i < 5000; i++)
467*61046927SAndroid Build Coastguard Worker       check_table(table, random(), i);
468*61046927SAndroid Build Coastguard Worker    compute_dist(table);
469*61046927SAndroid Build Coastguard Worker    __glxHashDestroy(table);
470*61046927SAndroid Build Coastguard Worker 
471*61046927SAndroid Build Coastguard Worker    return 0;
472*61046927SAndroid Build Coastguard Worker }
473*61046927SAndroid Build Coastguard Worker #endif
474