xref: /aosp_15_r20/external/libdrm/tests/hash.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
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