1*7688df22SAndroid Build Coastguard Worker /* xf86drmHash.c -- Small hash table support for integer -> integer mapping
2*7688df22SAndroid Build Coastguard Worker * Created: Sun Apr 18 09:35:45 1999 by [email protected]
3*7688df22SAndroid Build Coastguard Worker *
4*7688df22SAndroid Build Coastguard Worker * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5*7688df22SAndroid Build Coastguard Worker * All Rights Reserved.
6*7688df22SAndroid Build Coastguard Worker *
7*7688df22SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
8*7688df22SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
9*7688df22SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
10*7688df22SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*7688df22SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
12*7688df22SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
13*7688df22SAndroid Build Coastguard Worker *
14*7688df22SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
15*7688df22SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
16*7688df22SAndroid Build Coastguard Worker * Software.
17*7688df22SAndroid Build Coastguard Worker *
18*7688df22SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*7688df22SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*7688df22SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21*7688df22SAndroid Build Coastguard Worker * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22*7688df22SAndroid Build Coastguard Worker * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23*7688df22SAndroid Build Coastguard Worker * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24*7688df22SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
25*7688df22SAndroid Build Coastguard Worker *
26*7688df22SAndroid Build Coastguard Worker * Authors: Rickard E. (Rik) Faith <[email protected]>
27*7688df22SAndroid Build Coastguard Worker *
28*7688df22SAndroid Build Coastguard Worker * DESCRIPTION
29*7688df22SAndroid Build Coastguard Worker *
30*7688df22SAndroid Build Coastguard Worker * This file contains a straightforward implementation of a fixed-sized
31*7688df22SAndroid Build Coastguard Worker * hash table using self-organizing linked lists [Knuth73, pp. 398-399] for
32*7688df22SAndroid Build Coastguard Worker * collision resolution. There are two potentially interesting things
33*7688df22SAndroid Build Coastguard Worker * about this implementation:
34*7688df22SAndroid Build Coastguard Worker *
35*7688df22SAndroid Build Coastguard Worker * 1) The table is power-of-two sized. Prime sized tables are more
36*7688df22SAndroid Build Coastguard Worker * traditional, but do not have a significant advantage over power-of-two
37*7688df22SAndroid Build Coastguard Worker * sized table, especially when double hashing is not used for collision
38*7688df22SAndroid Build Coastguard Worker * resolution.
39*7688df22SAndroid Build Coastguard Worker *
40*7688df22SAndroid Build Coastguard Worker * 2) The hash computation uses a table of random integers [Hanson97,
41*7688df22SAndroid Build Coastguard Worker * pp. 39-41].
42*7688df22SAndroid Build Coastguard Worker *
43*7688df22SAndroid Build Coastguard Worker * FUTURE ENHANCEMENTS
44*7688df22SAndroid Build Coastguard Worker *
45*7688df22SAndroid Build Coastguard Worker * With a table size of 512, the current implementation is sufficient for a
46*7688df22SAndroid Build Coastguard Worker * few hundred keys. Since this is well above the expected size of the
47*7688df22SAndroid Build Coastguard Worker * tables for which this implementation was designed, the implementation of
48*7688df22SAndroid Build Coastguard Worker * dynamic hash tables was postponed until the need arises. A common (and
49*7688df22SAndroid Build Coastguard Worker * naive) approach to dynamic hash table implementation simply creates a
50*7688df22SAndroid Build Coastguard Worker * new hash table when necessary, rehashes all the data into the new table,
51*7688df22SAndroid Build Coastguard Worker * and destroys the old table. The approach in [Larson88] is superior in
52*7688df22SAndroid Build Coastguard Worker * two ways: 1) only a portion of the table is expanded when needed,
53*7688df22SAndroid Build Coastguard Worker * distributing the expansion cost over several insertions, and 2) portions
54*7688df22SAndroid Build Coastguard Worker * of the table can be locked, enabling a scalable thread-safe
55*7688df22SAndroid Build Coastguard Worker * implementation.
56*7688df22SAndroid Build Coastguard Worker *
57*7688df22SAndroid Build Coastguard Worker * REFERENCES
58*7688df22SAndroid Build Coastguard Worker *
59*7688df22SAndroid Build Coastguard Worker * [Hanson97] David R. Hanson. C Interfaces and Implementations:
60*7688df22SAndroid Build Coastguard Worker * Techniques for Creating Reusable Software. Reading, Massachusetts:
61*7688df22SAndroid Build Coastguard Worker * Addison-Wesley, 1997.
62*7688df22SAndroid Build Coastguard Worker *
63*7688df22SAndroid Build Coastguard Worker * [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3:
64*7688df22SAndroid Build Coastguard Worker * Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973.
65*7688df22SAndroid Build Coastguard Worker *
66*7688df22SAndroid Build Coastguard Worker * [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April
67*7688df22SAndroid Build Coastguard Worker * 1988, pp. 446-457.
68*7688df22SAndroid Build Coastguard Worker *
69*7688df22SAndroid Build Coastguard Worker */
70*7688df22SAndroid Build Coastguard Worker
71*7688df22SAndroid Build Coastguard Worker #include <stdio.h>
72*7688df22SAndroid Build Coastguard Worker #include <stdlib.h>
73*7688df22SAndroid Build Coastguard Worker
74*7688df22SAndroid Build Coastguard Worker #include "xf86drm.h"
75*7688df22SAndroid Build Coastguard Worker #include "xf86drmHash.h"
76*7688df22SAndroid Build Coastguard Worker
77*7688df22SAndroid Build Coastguard Worker #define DIST_LIMIT 10
78*7688df22SAndroid Build Coastguard Worker static int dist[DIST_LIMIT];
79*7688df22SAndroid Build Coastguard Worker
clear_dist(void)80*7688df22SAndroid Build Coastguard Worker static void clear_dist(void) {
81*7688df22SAndroid Build Coastguard Worker int i;
82*7688df22SAndroid Build Coastguard Worker
83*7688df22SAndroid Build Coastguard Worker for (i = 0; i < DIST_LIMIT; i++)
84*7688df22SAndroid Build Coastguard Worker dist[i] = 0;
85*7688df22SAndroid Build Coastguard Worker }
86*7688df22SAndroid Build Coastguard Worker
count_entries(HashBucketPtr bucket)87*7688df22SAndroid Build Coastguard Worker static int count_entries(HashBucketPtr bucket)
88*7688df22SAndroid Build Coastguard Worker {
89*7688df22SAndroid Build Coastguard Worker int count = 0;
90*7688df22SAndroid Build Coastguard Worker
91*7688df22SAndroid Build Coastguard Worker for (; bucket; bucket = bucket->next)
92*7688df22SAndroid Build Coastguard Worker ++count;
93*7688df22SAndroid Build Coastguard Worker return count;
94*7688df22SAndroid Build Coastguard Worker }
95*7688df22SAndroid Build Coastguard Worker
update_dist(int count)96*7688df22SAndroid Build Coastguard Worker static void update_dist(int count)
97*7688df22SAndroid Build Coastguard Worker {
98*7688df22SAndroid Build Coastguard Worker if (count >= DIST_LIMIT)
99*7688df22SAndroid Build Coastguard Worker ++dist[DIST_LIMIT-1];
100*7688df22SAndroid Build Coastguard Worker else
101*7688df22SAndroid Build Coastguard Worker ++dist[count];
102*7688df22SAndroid Build Coastguard Worker }
103*7688df22SAndroid Build Coastguard Worker
compute_dist(HashTablePtr table)104*7688df22SAndroid Build Coastguard Worker static void compute_dist(HashTablePtr table)
105*7688df22SAndroid Build Coastguard Worker {
106*7688df22SAndroid Build Coastguard Worker int i;
107*7688df22SAndroid Build Coastguard Worker HashBucketPtr bucket;
108*7688df22SAndroid Build Coastguard Worker
109*7688df22SAndroid Build Coastguard Worker printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n",
110*7688df22SAndroid Build Coastguard Worker table->entries, table->hits, table->partials, table->misses);
111*7688df22SAndroid Build Coastguard Worker clear_dist();
112*7688df22SAndroid Build Coastguard Worker for (i = 0; i < HASH_SIZE; i++) {
113*7688df22SAndroid Build Coastguard Worker bucket = table->buckets[i];
114*7688df22SAndroid Build Coastguard Worker update_dist(count_entries(bucket));
115*7688df22SAndroid Build Coastguard Worker }
116*7688df22SAndroid Build Coastguard Worker for (i = 0; i < DIST_LIMIT; i++) {
117*7688df22SAndroid Build Coastguard Worker if (i != DIST_LIMIT-1)
118*7688df22SAndroid Build Coastguard Worker printf("%5d %10d\n", i, dist[i]);
119*7688df22SAndroid Build Coastguard Worker else
120*7688df22SAndroid Build Coastguard Worker printf("other %10d\n", dist[i]);
121*7688df22SAndroid Build Coastguard Worker }
122*7688df22SAndroid Build Coastguard Worker }
123*7688df22SAndroid Build Coastguard Worker
check_table(HashTablePtr table,unsigned long key,void * value)124*7688df22SAndroid Build Coastguard Worker static int check_table(HashTablePtr table,
125*7688df22SAndroid Build Coastguard Worker unsigned long key, void * value)
126*7688df22SAndroid Build Coastguard Worker {
127*7688df22SAndroid Build Coastguard Worker void *retval;
128*7688df22SAndroid Build Coastguard Worker int retcode = drmHashLookup(table, key, &retval);
129*7688df22SAndroid Build Coastguard Worker
130*7688df22SAndroid Build Coastguard Worker switch (retcode) {
131*7688df22SAndroid Build Coastguard Worker case -1:
132*7688df22SAndroid Build Coastguard Worker printf("Bad magic = 0x%08lx:"
133*7688df22SAndroid Build Coastguard Worker " key = %lu, expected = %p, returned = %p\n",
134*7688df22SAndroid Build Coastguard Worker table->magic, key, value, retval);
135*7688df22SAndroid Build Coastguard Worker break;
136*7688df22SAndroid Build Coastguard Worker case 1:
137*7688df22SAndroid Build Coastguard Worker printf("Not found: key = %lu, expected = %p, returned = %p\n",
138*7688df22SAndroid Build Coastguard Worker key, value, retval);
139*7688df22SAndroid Build Coastguard Worker break;
140*7688df22SAndroid Build Coastguard Worker case 0:
141*7688df22SAndroid Build Coastguard Worker if (value != retval) {
142*7688df22SAndroid Build Coastguard Worker printf("Bad value: key = %lu, expected = %p, returned = %p\n",
143*7688df22SAndroid Build Coastguard Worker key, value, retval);
144*7688df22SAndroid Build Coastguard Worker retcode = -1;
145*7688df22SAndroid Build Coastguard Worker }
146*7688df22SAndroid Build Coastguard Worker break;
147*7688df22SAndroid Build Coastguard Worker default:
148*7688df22SAndroid Build Coastguard Worker printf("Bad retcode = %d: key = %lu, expected = %p, returned = %p\n",
149*7688df22SAndroid Build Coastguard Worker retcode, key, value, retval);
150*7688df22SAndroid Build Coastguard Worker break;
151*7688df22SAndroid Build Coastguard Worker }
152*7688df22SAndroid Build Coastguard Worker return retcode;
153*7688df22SAndroid Build Coastguard Worker }
154*7688df22SAndroid Build Coastguard Worker
main(void)155*7688df22SAndroid Build Coastguard Worker int main(void)
156*7688df22SAndroid Build Coastguard Worker {
157*7688df22SAndroid Build Coastguard Worker HashTablePtr table;
158*7688df22SAndroid Build Coastguard Worker unsigned long i;
159*7688df22SAndroid Build Coastguard Worker int ret = 0;
160*7688df22SAndroid Build Coastguard Worker
161*7688df22SAndroid Build Coastguard Worker printf("\n***** 256 consecutive integers ****\n");
162*7688df22SAndroid Build Coastguard Worker table = drmHashCreate();
163*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 256; i++)
164*7688df22SAndroid Build Coastguard Worker drmHashInsert(table, i, (void *)(i << 16 | i));
165*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 256; i++)
166*7688df22SAndroid Build Coastguard Worker ret |= check_table(table, i, (void *)(i << 16 | i));
167*7688df22SAndroid Build Coastguard Worker compute_dist(table);
168*7688df22SAndroid Build Coastguard Worker drmHashDestroy(table);
169*7688df22SAndroid Build Coastguard Worker
170*7688df22SAndroid Build Coastguard Worker printf("\n***** 1024 consecutive integers ****\n");
171*7688df22SAndroid Build Coastguard Worker table = drmHashCreate();
172*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 1024; i++)
173*7688df22SAndroid Build Coastguard Worker drmHashInsert(table, i, (void *)(i << 16 | i));
174*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 1024; i++)
175*7688df22SAndroid Build Coastguard Worker ret |= check_table(table, i, (void *)(i << 16 | i));
176*7688df22SAndroid Build Coastguard Worker compute_dist(table);
177*7688df22SAndroid Build Coastguard Worker drmHashDestroy(table);
178*7688df22SAndroid Build Coastguard Worker
179*7688df22SAndroid Build Coastguard Worker printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
180*7688df22SAndroid Build Coastguard Worker table = drmHashCreate();
181*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 1024; i++)
182*7688df22SAndroid Build Coastguard Worker drmHashInsert(table, i*4096, (void *)(i << 16 | i));
183*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 1024; i++)
184*7688df22SAndroid Build Coastguard Worker ret |= check_table(table, i*4096, (void *)(i << 16 | i));
185*7688df22SAndroid Build Coastguard Worker compute_dist(table);
186*7688df22SAndroid Build Coastguard Worker drmHashDestroy(table);
187*7688df22SAndroid Build Coastguard Worker
188*7688df22SAndroid Build Coastguard Worker printf("\n***** 1024 random integers ****\n");
189*7688df22SAndroid Build Coastguard Worker table = drmHashCreate();
190*7688df22SAndroid Build Coastguard Worker srandom(0xbeefbeef);
191*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 1024; i++)
192*7688df22SAndroid Build Coastguard Worker drmHashInsert(table, random(), (void *)(i << 16 | i));
193*7688df22SAndroid Build Coastguard Worker srandom(0xbeefbeef);
194*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 1024; i++)
195*7688df22SAndroid Build Coastguard Worker ret |= check_table(table, random(), (void *)(i << 16 | i));
196*7688df22SAndroid Build Coastguard Worker srandom(0xbeefbeef);
197*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 1024; i++)
198*7688df22SAndroid Build Coastguard Worker ret |= check_table(table, random(), (void *)(i << 16 | i));
199*7688df22SAndroid Build Coastguard Worker compute_dist(table);
200*7688df22SAndroid Build Coastguard Worker drmHashDestroy(table);
201*7688df22SAndroid Build Coastguard Worker
202*7688df22SAndroid Build Coastguard Worker printf("\n***** 5000 random integers ****\n");
203*7688df22SAndroid Build Coastguard Worker table = drmHashCreate();
204*7688df22SAndroid Build Coastguard Worker srandom(0xbeefbeef);
205*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 5000; i++)
206*7688df22SAndroid Build Coastguard Worker drmHashInsert(table, random(), (void *)(i << 16 | i));
207*7688df22SAndroid Build Coastguard Worker srandom(0xbeefbeef);
208*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 5000; i++)
209*7688df22SAndroid Build Coastguard Worker ret |= check_table(table, random(), (void *)(i << 16 | i));
210*7688df22SAndroid Build Coastguard Worker srandom(0xbeefbeef);
211*7688df22SAndroid Build Coastguard Worker for (i = 0; i < 5000; i++)
212*7688df22SAndroid Build Coastguard Worker ret |= check_table(table, random(), (void *)(i << 16 | i));
213*7688df22SAndroid Build Coastguard Worker compute_dist(table);
214*7688df22SAndroid Build Coastguard Worker drmHashDestroy(table);
215*7688df22SAndroid Build Coastguard Worker
216*7688df22SAndroid Build Coastguard Worker return ret;
217*7688df22SAndroid Build Coastguard Worker }
218