140cb5e5dSvi117747 /* 240cb5e5dSvi117747 * CDDL HEADER START 340cb5e5dSvi117747 * 440cb5e5dSvi117747 * The contents of this file are subject to the terms of the 540cb5e5dSvi117747 * Common Development and Distribution License (the "License"). 640cb5e5dSvi117747 * You may not use this file except in compliance with the License. 740cb5e5dSvi117747 * 840cb5e5dSvi117747 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 940cb5e5dSvi117747 * or http://www.opensolaris.org/os/licensing. 1040cb5e5dSvi117747 * See the License for the specific language governing permissions 1140cb5e5dSvi117747 * and limitations under the License. 1240cb5e5dSvi117747 * 1340cb5e5dSvi117747 * When distributing Covered Code, include this CDDL HEADER in each 1440cb5e5dSvi117747 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1540cb5e5dSvi117747 * If applicable, add the following below this CDDL HEADER, with the 1640cb5e5dSvi117747 * fields enclosed by brackets "[]" replaced with your own identifying 1740cb5e5dSvi117747 * information: Portions Copyright [yyyy] [name of copyright owner] 1840cb5e5dSvi117747 * 1940cb5e5dSvi117747 * CDDL HEADER END 2040cb5e5dSvi117747 */ 2140cb5e5dSvi117747 2240cb5e5dSvi117747 /* 23*2c2c4183Svi117747 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2440cb5e5dSvi117747 * Use is subject to license terms. 2540cb5e5dSvi117747 */ 2640cb5e5dSvi117747 2740cb5e5dSvi117747 #pragma ident "%Z%%M% %I% %E% SMI" 2840cb5e5dSvi117747 29*2c2c4183Svi117747 #include <stdlib.h> 30*2c2c4183Svi117747 #include <assert.h> 3140cb5e5dSvi117747 #include <pthread.h> 3240cb5e5dSvi117747 3340cb5e5dSvi117747 #include "sip_hash.h" 3440cb5e5dSvi117747 3540cb5e5dSvi117747 /* 3640cb5e5dSvi117747 * This file implements functions that add, search or remove an object 3740cb5e5dSvi117747 * from the hash table. The object is opaque to the hash functions. To add 3840cb5e5dSvi117747 * an object to the hash table, the caller provides the hash table, 3940cb5e5dSvi117747 * the object and the index into the hash table. To search an object, 4040cb5e5dSvi117747 * the caller provides the hash table, the digest (opaque), the index into 4140cb5e5dSvi117747 * the hash table and the function that does the actual match. Similarly, 4240cb5e5dSvi117747 * for removing an object, the caller provides the hash table, the digest 4340cb5e5dSvi117747 * (opaque), the index into the hash table and the function that does 4440cb5e5dSvi117747 * the acutal deletion of the object - if the deletion is successful, 4540cb5e5dSvi117747 * the object is taken off of the hash table. 4640cb5e5dSvi117747 */ 4740cb5e5dSvi117747 4840cb5e5dSvi117747 /* 4940cb5e5dSvi117747 * Given an object and the hash index, add it to the given hash table 5040cb5e5dSvi117747 */ 5140cb5e5dSvi117747 int 5240cb5e5dSvi117747 sip_hash_add(sip_hash_t *sip_hash, void *obj, int hindex) 5340cb5e5dSvi117747 { 5440cb5e5dSvi117747 sip_hash_obj_t *new_obj; 5540cb5e5dSvi117747 sip_hash_t *hash_entry; 5640cb5e5dSvi117747 5740cb5e5dSvi117747 assert(obj != NULL); 5840cb5e5dSvi117747 5940cb5e5dSvi117747 new_obj = (sip_hash_obj_t *)malloc(sizeof (*new_obj)); 6040cb5e5dSvi117747 if (new_obj == NULL) 6140cb5e5dSvi117747 return (-1); 6240cb5e5dSvi117747 new_obj->sip_obj = obj; 6340cb5e5dSvi117747 new_obj->next_obj = NULL; 6440cb5e5dSvi117747 new_obj->prev_obj = NULL; 6540cb5e5dSvi117747 hash_entry = &sip_hash[hindex]; 6640cb5e5dSvi117747 (void) pthread_mutex_lock(&hash_entry->sip_hash_mutex); 6740cb5e5dSvi117747 if (hash_entry->hash_count == 0) { 6840cb5e5dSvi117747 assert(hash_entry->hash_head == NULL); 6940cb5e5dSvi117747 assert(hash_entry->hash_tail == NULL); 7040cb5e5dSvi117747 hash_entry->hash_head = new_obj; 7140cb5e5dSvi117747 } else { 7240cb5e5dSvi117747 hash_entry->hash_tail->next_obj = new_obj; 7340cb5e5dSvi117747 new_obj->prev_obj = hash_entry->hash_tail; 7440cb5e5dSvi117747 } 7540cb5e5dSvi117747 hash_entry->hash_tail = new_obj; 7640cb5e5dSvi117747 hash_entry->hash_count++; 7740cb5e5dSvi117747 (void) pthread_mutex_unlock(&hash_entry->sip_hash_mutex); 7840cb5e5dSvi117747 return (0); 7940cb5e5dSvi117747 } 8040cb5e5dSvi117747 8140cb5e5dSvi117747 /* 8240cb5e5dSvi117747 * Given the hash table, the digest to be searched for, index into the hash 8340cb5e5dSvi117747 * table and the function to do the actual matching, return the object, 8440cb5e5dSvi117747 * if found. 8540cb5e5dSvi117747 */ 8640cb5e5dSvi117747 void * 8740cb5e5dSvi117747 sip_hash_find(sip_hash_t *sip_hash, void *digest, int hindex, 8840cb5e5dSvi117747 boolean_t (*match_func)(void *, void *)) 8940cb5e5dSvi117747 { 9040cb5e5dSvi117747 int count; 9140cb5e5dSvi117747 sip_hash_obj_t *tmp; 9240cb5e5dSvi117747 sip_hash_t *hash_entry; 9340cb5e5dSvi117747 9440cb5e5dSvi117747 hash_entry = &sip_hash[hindex]; 9540cb5e5dSvi117747 (void) pthread_mutex_lock(&hash_entry->sip_hash_mutex); 9640cb5e5dSvi117747 tmp = hash_entry->hash_head; 9740cb5e5dSvi117747 for (count = 0; count < hash_entry->hash_count; count++) { 9840cb5e5dSvi117747 if (match_func(tmp->sip_obj, digest)) { 9940cb5e5dSvi117747 (void) pthread_mutex_unlock( 10040cb5e5dSvi117747 &hash_entry->sip_hash_mutex); 10140cb5e5dSvi117747 return (tmp->sip_obj); 10240cb5e5dSvi117747 } 10340cb5e5dSvi117747 tmp = tmp->next_obj; 10440cb5e5dSvi117747 } 10540cb5e5dSvi117747 (void) pthread_mutex_unlock(&hash_entry->sip_hash_mutex); 10640cb5e5dSvi117747 return (NULL); 10740cb5e5dSvi117747 } 10840cb5e5dSvi117747 10940cb5e5dSvi117747 /* 11040cb5e5dSvi117747 * Walk the hash table and invoke func on each object. 'arg' is passed 11140cb5e5dSvi117747 * to 'func' 11240cb5e5dSvi117747 */ 11340cb5e5dSvi117747 void 11440cb5e5dSvi117747 sip_walk_hash(sip_hash_t *sip_hash, void (*func)(void *, void *), void *arg) 11540cb5e5dSvi117747 { 11640cb5e5dSvi117747 sip_hash_t *hash_entry; 11740cb5e5dSvi117747 int count; 11840cb5e5dSvi117747 int hcount; 11940cb5e5dSvi117747 sip_hash_obj_t *tmp; 12040cb5e5dSvi117747 12140cb5e5dSvi117747 for (count = 0; count < SIP_HASH_SZ; count++) { 12240cb5e5dSvi117747 hash_entry = &sip_hash[count]; 12340cb5e5dSvi117747 (void) pthread_mutex_lock(&hash_entry->sip_hash_mutex); 12440cb5e5dSvi117747 tmp = hash_entry->hash_head; 12540cb5e5dSvi117747 for (hcount = 0; hcount < hash_entry->hash_count; hcount++) { 12640cb5e5dSvi117747 assert(tmp->sip_obj != NULL); 12740cb5e5dSvi117747 func(tmp->sip_obj, arg); 12840cb5e5dSvi117747 tmp = tmp->next_obj; 12940cb5e5dSvi117747 } 13040cb5e5dSvi117747 (void) pthread_mutex_unlock(&hash_entry->sip_hash_mutex); 13140cb5e5dSvi117747 } 13240cb5e5dSvi117747 } 13340cb5e5dSvi117747 13440cb5e5dSvi117747 /* 13540cb5e5dSvi117747 * Given the hash table, the digest to be searched for, the index into the 13640cb5e5dSvi117747 * hash table and the delete function provided to do the actual deletion, 13740cb5e5dSvi117747 * remove the object from the hash table (i.e. only if the object is deleted). 13840cb5e5dSvi117747 */ 13940cb5e5dSvi117747 void 14040cb5e5dSvi117747 sip_hash_delete(sip_hash_t *sip_hash, void *digest, int hindex, 14140cb5e5dSvi117747 boolean_t (*del_func)(void *, void *, int *)) 14240cb5e5dSvi117747 { 14340cb5e5dSvi117747 sip_hash_t *hash_entry; 14440cb5e5dSvi117747 int count; 14540cb5e5dSvi117747 sip_hash_obj_t *tmp; 14640cb5e5dSvi117747 int found; 14740cb5e5dSvi117747 14840cb5e5dSvi117747 hash_entry = &sip_hash[hindex]; 14940cb5e5dSvi117747 (void) pthread_mutex_lock(&hash_entry->sip_hash_mutex); 15040cb5e5dSvi117747 tmp = hash_entry->hash_head; 15140cb5e5dSvi117747 for (count = 0; count < hash_entry->hash_count; count++) { 15240cb5e5dSvi117747 if (del_func(tmp->sip_obj, digest, &found)) { 15340cb5e5dSvi117747 if (tmp == hash_entry->hash_head) { 15440cb5e5dSvi117747 if (tmp->next_obj != NULL) { 15540cb5e5dSvi117747 hash_entry->hash_head = tmp->next_obj; 15640cb5e5dSvi117747 tmp->next_obj->prev_obj = NULL; 15740cb5e5dSvi117747 } else { 15840cb5e5dSvi117747 assert(hash_entry->hash_tail == 15940cb5e5dSvi117747 hash_entry->hash_head); 16040cb5e5dSvi117747 hash_entry->hash_head = NULL; 16140cb5e5dSvi117747 hash_entry->hash_tail = NULL; 16240cb5e5dSvi117747 } 16340cb5e5dSvi117747 } else { 16440cb5e5dSvi117747 sip_hash_obj_t *next = tmp->next_obj; 16540cb5e5dSvi117747 16640cb5e5dSvi117747 if (next != NULL) { 16740cb5e5dSvi117747 tmp->prev_obj->next_obj = next; 16840cb5e5dSvi117747 next->prev_obj = tmp->prev_obj; 16940cb5e5dSvi117747 } else { 17040cb5e5dSvi117747 assert(hash_entry->hash_tail == tmp); 17140cb5e5dSvi117747 tmp->prev_obj->next_obj = NULL; 17240cb5e5dSvi117747 hash_entry->hash_tail = 17340cb5e5dSvi117747 tmp->prev_obj; 17440cb5e5dSvi117747 } 17540cb5e5dSvi117747 } 17640cb5e5dSvi117747 tmp->prev_obj = NULL; 17740cb5e5dSvi117747 tmp->next_obj = NULL; 17840cb5e5dSvi117747 free(tmp); 17940cb5e5dSvi117747 hash_entry->hash_count--; 18040cb5e5dSvi117747 (void) pthread_mutex_unlock( 18140cb5e5dSvi117747 &hash_entry->sip_hash_mutex); 18240cb5e5dSvi117747 return; 18340cb5e5dSvi117747 /* 18440cb5e5dSvi117747 * If we found the object, we are done 18540cb5e5dSvi117747 */ 18640cb5e5dSvi117747 } else if (found == 1) { 18740cb5e5dSvi117747 (void) pthread_mutex_unlock( 18840cb5e5dSvi117747 &hash_entry->sip_hash_mutex); 18940cb5e5dSvi117747 return; 19040cb5e5dSvi117747 } 19140cb5e5dSvi117747 tmp = tmp->next_obj; 19240cb5e5dSvi117747 } 19340cb5e5dSvi117747 (void) pthread_mutex_unlock(&hash_entry->sip_hash_mutex); 19440cb5e5dSvi117747 } 195