1*d876124dSJohn Birrell /* 2*d876124dSJohn Birrell * CDDL HEADER START 3*d876124dSJohn Birrell * 4*d876124dSJohn Birrell * The contents of this file are subject to the terms of the 5*d876124dSJohn Birrell * Common Development and Distribution License, Version 1.0 only 6*d876124dSJohn Birrell * (the "License"). You may not use this file except in compliance 7*d876124dSJohn Birrell * with the License. 8*d876124dSJohn Birrell * 9*d876124dSJohn Birrell * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*d876124dSJohn Birrell * or http://www.opensolaris.org/os/licensing. 11*d876124dSJohn Birrell * See the License for the specific language governing permissions 12*d876124dSJohn Birrell * and limitations under the License. 13*d876124dSJohn Birrell * 14*d876124dSJohn Birrell * When distributing Covered Code, include this CDDL HEADER in each 15*d876124dSJohn Birrell * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*d876124dSJohn Birrell * If applicable, add the following below this CDDL HEADER, with the 17*d876124dSJohn Birrell * fields enclosed by brackets "[]" replaced with your own identifying 18*d876124dSJohn Birrell * information: Portions Copyright [yyyy] [name of copyright owner] 19*d876124dSJohn Birrell * 20*d876124dSJohn Birrell * CDDL HEADER END 21*d876124dSJohn Birrell */ 22*d876124dSJohn Birrell 23*d876124dSJohn Birrell /* 24*d876124dSJohn Birrell * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25*d876124dSJohn Birrell * Use is subject to license terms. 26*d876124dSJohn Birrell */ 27*d876124dSJohn Birrell 28*d876124dSJohn Birrell #pragma ident "%Z%%M% %I% %E% SMI" 29*d876124dSJohn Birrell 30*d876124dSJohn Birrell #include <ctf_impl.h> 31*d876124dSJohn Birrell 32*d876124dSJohn Birrell static const ushort_t _CTF_EMPTY[1] = { 0 }; 33*d876124dSJohn Birrell 34*d876124dSJohn Birrell int 35*d876124dSJohn Birrell ctf_hash_create(ctf_hash_t *hp, ulong_t nelems) 36*d876124dSJohn Birrell { 37*d876124dSJohn Birrell if (nelems > USHRT_MAX) 38*d876124dSJohn Birrell return (EOVERFLOW); 39*d876124dSJohn Birrell 40*d876124dSJohn Birrell /* 41*d876124dSJohn Birrell * If the hash table is going to be empty, don't bother allocating any 42*d876124dSJohn Birrell * memory and make the only bucket point to a zero so lookups fail. 43*d876124dSJohn Birrell */ 44*d876124dSJohn Birrell if (nelems == 0) { 45*d876124dSJohn Birrell bzero(hp, sizeof (ctf_hash_t)); 46*d876124dSJohn Birrell hp->h_buckets = (ushort_t *)_CTF_EMPTY; 47*d876124dSJohn Birrell hp->h_nbuckets = 1; 48*d876124dSJohn Birrell return (0); 49*d876124dSJohn Birrell } 50*d876124dSJohn Birrell 51*d876124dSJohn Birrell hp->h_nbuckets = 211; /* use a prime number of hash buckets */ 52*d876124dSJohn Birrell hp->h_nelems = nelems + 1; /* we use index zero as a sentinel */ 53*d876124dSJohn Birrell hp->h_free = 1; /* first free element is index 1 */ 54*d876124dSJohn Birrell 55*d876124dSJohn Birrell hp->h_buckets = ctf_alloc(sizeof (ushort_t) * hp->h_nbuckets); 56*d876124dSJohn Birrell hp->h_chains = ctf_alloc(sizeof (ctf_helem_t) * hp->h_nelems); 57*d876124dSJohn Birrell 58*d876124dSJohn Birrell if (hp->h_buckets == NULL || hp->h_chains == NULL) { 59*d876124dSJohn Birrell ctf_hash_destroy(hp); 60*d876124dSJohn Birrell return (EAGAIN); 61*d876124dSJohn Birrell } 62*d876124dSJohn Birrell 63*d876124dSJohn Birrell bzero(hp->h_buckets, sizeof (ushort_t) * hp->h_nbuckets); 64*d876124dSJohn Birrell bzero(hp->h_chains, sizeof (ctf_helem_t) * hp->h_nelems); 65*d876124dSJohn Birrell 66*d876124dSJohn Birrell return (0); 67*d876124dSJohn Birrell } 68*d876124dSJohn Birrell 69*d876124dSJohn Birrell uint_t 70*d876124dSJohn Birrell ctf_hash_size(const ctf_hash_t *hp) 71*d876124dSJohn Birrell { 72*d876124dSJohn Birrell return (hp->h_nelems ? hp->h_nelems - 1 : 0); 73*d876124dSJohn Birrell } 74*d876124dSJohn Birrell 75*d876124dSJohn Birrell static ulong_t 76*d876124dSJohn Birrell ctf_hash_compute(const char *key, size_t len) 77*d876124dSJohn Birrell { 78*d876124dSJohn Birrell ulong_t g, h = 0; 79*d876124dSJohn Birrell const char *p, *q = key + len; 80*d876124dSJohn Birrell size_t n = 0; 81*d876124dSJohn Birrell 82*d876124dSJohn Birrell for (p = key; p < q; p++, n++) { 83*d876124dSJohn Birrell h = (h << 4) + *p; 84*d876124dSJohn Birrell 85*d876124dSJohn Birrell if ((g = (h & 0xf0000000)) != 0) { 86*d876124dSJohn Birrell h ^= (g >> 24); 87*d876124dSJohn Birrell h ^= g; 88*d876124dSJohn Birrell } 89*d876124dSJohn Birrell } 90*d876124dSJohn Birrell 91*d876124dSJohn Birrell return (h); 92*d876124dSJohn Birrell } 93*d876124dSJohn Birrell 94*d876124dSJohn Birrell int 95*d876124dSJohn Birrell ctf_hash_insert(ctf_hash_t *hp, ctf_file_t *fp, ushort_t type, uint_t name) 96*d876124dSJohn Birrell { 97*d876124dSJohn Birrell ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID(name)]; 98*d876124dSJohn Birrell const char *str = ctsp->cts_strs + CTF_NAME_OFFSET(name); 99*d876124dSJohn Birrell ctf_helem_t *hep = &hp->h_chains[hp->h_free]; 100*d876124dSJohn Birrell ulong_t h; 101*d876124dSJohn Birrell 102*d876124dSJohn Birrell if (type == 0) 103*d876124dSJohn Birrell return (EINVAL); 104*d876124dSJohn Birrell 105*d876124dSJohn Birrell if (hp->h_free >= hp->h_nelems) 106*d876124dSJohn Birrell return (EOVERFLOW); 107*d876124dSJohn Birrell 108*d876124dSJohn Birrell if (ctsp->cts_strs == NULL) 109*d876124dSJohn Birrell return (ECTF_STRTAB); 110*d876124dSJohn Birrell 111*d876124dSJohn Birrell if (ctsp->cts_len <= CTF_NAME_OFFSET(name)) 112*d876124dSJohn Birrell return (ECTF_BADNAME); 113*d876124dSJohn Birrell 114*d876124dSJohn Birrell if (str[0] == '\0') 115*d876124dSJohn Birrell return (0); /* just ignore empty strings on behalf of caller */ 116*d876124dSJohn Birrell 117*d876124dSJohn Birrell hep->h_name = name; 118*d876124dSJohn Birrell hep->h_type = type; 119*d876124dSJohn Birrell h = ctf_hash_compute(str, strlen(str)) % hp->h_nbuckets; 120*d876124dSJohn Birrell hep->h_next = hp->h_buckets[h]; 121*d876124dSJohn Birrell hp->h_buckets[h] = hp->h_free++; 122*d876124dSJohn Birrell 123*d876124dSJohn Birrell return (0); 124*d876124dSJohn Birrell } 125*d876124dSJohn Birrell 126*d876124dSJohn Birrell /* 127*d876124dSJohn Birrell * Wrapper for ctf_hash_lookup/ctf_hash_insert: if the key is already in the 128*d876124dSJohn Birrell * hash, override the previous definition with this new official definition. 129*d876124dSJohn Birrell * If the key is not present, then call ctf_hash_insert() and hash it in. 130*d876124dSJohn Birrell */ 131*d876124dSJohn Birrell int 132*d876124dSJohn Birrell ctf_hash_define(ctf_hash_t *hp, ctf_file_t *fp, ushort_t type, uint_t name) 133*d876124dSJohn Birrell { 134*d876124dSJohn Birrell const char *str = ctf_strptr(fp, name); 135*d876124dSJohn Birrell ctf_helem_t *hep = ctf_hash_lookup(hp, fp, str, strlen(str)); 136*d876124dSJohn Birrell 137*d876124dSJohn Birrell if (hep == NULL) 138*d876124dSJohn Birrell return (ctf_hash_insert(hp, fp, type, name)); 139*d876124dSJohn Birrell 140*d876124dSJohn Birrell hep->h_type = type; 141*d876124dSJohn Birrell return (0); 142*d876124dSJohn Birrell } 143*d876124dSJohn Birrell 144*d876124dSJohn Birrell ctf_helem_t * 145*d876124dSJohn Birrell ctf_hash_lookup(ctf_hash_t *hp, ctf_file_t *fp, const char *key, size_t len) 146*d876124dSJohn Birrell { 147*d876124dSJohn Birrell ctf_helem_t *hep; 148*d876124dSJohn Birrell ctf_strs_t *ctsp; 149*d876124dSJohn Birrell const char *str; 150*d876124dSJohn Birrell ushort_t i; 151*d876124dSJohn Birrell 152*d876124dSJohn Birrell ulong_t h = ctf_hash_compute(key, len) % hp->h_nbuckets; 153*d876124dSJohn Birrell 154*d876124dSJohn Birrell for (i = hp->h_buckets[h]; i != 0; i = hep->h_next) { 155*d876124dSJohn Birrell hep = &hp->h_chains[i]; 156*d876124dSJohn Birrell ctsp = &fp->ctf_str[CTF_NAME_STID(hep->h_name)]; 157*d876124dSJohn Birrell str = ctsp->cts_strs + CTF_NAME_OFFSET(hep->h_name); 158*d876124dSJohn Birrell 159*d876124dSJohn Birrell if (strncmp(key, str, len) == 0 && str[len] == '\0') 160*d876124dSJohn Birrell return (hep); 161*d876124dSJohn Birrell } 162*d876124dSJohn Birrell 163*d876124dSJohn Birrell return (NULL); 164*d876124dSJohn Birrell } 165*d876124dSJohn Birrell 166*d876124dSJohn Birrell void 167*d876124dSJohn Birrell ctf_hash_destroy(ctf_hash_t *hp) 168*d876124dSJohn Birrell { 169*d876124dSJohn Birrell if (hp->h_buckets != NULL && hp->h_nbuckets != 1) { 170*d876124dSJohn Birrell ctf_free(hp->h_buckets, sizeof (ushort_t) * hp->h_nbuckets); 171*d876124dSJohn Birrell hp->h_buckets = NULL; 172*d876124dSJohn Birrell } 173*d876124dSJohn Birrell 174*d876124dSJohn Birrell if (hp->h_chains != NULL) { 175*d876124dSJohn Birrell ctf_free(hp->h_chains, sizeof (ctf_helem_t) * hp->h_nelems); 176*d876124dSJohn Birrell hp->h_chains = NULL; 177*d876124dSJohn Birrell } 178*d876124dSJohn Birrell } 179