xref: /dragonfly/lib/libc/sysvipc/sysvipc_hash.c (revision ff86f401)
182657471SMarkus Pfeiffer /*-
282657471SMarkus Pfeiffer  * Copyright (c) 2013 Larisa Grigore<larisagrigore@gmail.com>
382657471SMarkus Pfeiffer  * All rights reserved.
482657471SMarkus Pfeiffer  *
582657471SMarkus Pfeiffer  * Redistribution and use in source and binary forms, with or without
682657471SMarkus Pfeiffer  * modification, are permitted provided that the following conditions
782657471SMarkus Pfeiffer  * are met:
882657471SMarkus Pfeiffer  * 1. Redistributions of source code must retain the above copyright
982657471SMarkus Pfeiffer  *    notice, this list of conditions and the following disclaimer.
1082657471SMarkus Pfeiffer  * 2. Redistributions in binary form must reproduce the above copyright
1182657471SMarkus Pfeiffer  *    notice, this list of conditions and the following disclaimer in the
1282657471SMarkus Pfeiffer  *    documentation and/or other materials provided with the distribution.
1382657471SMarkus Pfeiffer  *
1482657471SMarkus Pfeiffer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1582657471SMarkus Pfeiffer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1682657471SMarkus Pfeiffer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1782657471SMarkus Pfeiffer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1882657471SMarkus Pfeiffer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1982657471SMarkus Pfeiffer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2082657471SMarkus Pfeiffer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2182657471SMarkus Pfeiffer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2282657471SMarkus Pfeiffer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2382657471SMarkus Pfeiffer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2482657471SMarkus Pfeiffer  * SUCH DAMAGE.
2582657471SMarkus Pfeiffer  */
2682657471SMarkus Pfeiffer 
2782657471SMarkus Pfeiffer #include <stdlib.h>
2882657471SMarkus Pfeiffer #include <stdio.h>
2982657471SMarkus Pfeiffer #include <errno.h>
3082657471SMarkus Pfeiffer 
3182657471SMarkus Pfeiffer #include "sysvipc_hash.h"
3282657471SMarkus Pfeiffer 
3382657471SMarkus Pfeiffer struct hashtable *
_hash_init(int nr_elems)34*ff86f401SSascha Wildner _hash_init(int nr_elems)
35*ff86f401SSascha Wildner {
3682657471SMarkus Pfeiffer 	long hashsize;
3782657471SMarkus Pfeiffer 	struct hashtable *hashtable;
3882657471SMarkus Pfeiffer 	int i;
3982657471SMarkus Pfeiffer 
4082657471SMarkus Pfeiffer 	if (nr_elems <= 0)
4182657471SMarkus Pfeiffer 		return NULL;
4282657471SMarkus Pfeiffer 	for (hashsize = 2; hashsize < nr_elems; hashsize <<= 1)
4382657471SMarkus Pfeiffer 		continue;
4482657471SMarkus Pfeiffer 
4582657471SMarkus Pfeiffer 	hashtable = malloc(sizeof(struct hashtable));
4682657471SMarkus Pfeiffer 	if (!hashtable) {
4782657471SMarkus Pfeiffer 		return NULL;
4882657471SMarkus Pfeiffer 	}
4982657471SMarkus Pfeiffer 
5082657471SMarkus Pfeiffer 	hashtable->entries = malloc(hashsize * sizeof(struct entries_list));
5182657471SMarkus Pfeiffer 	if (!hashtable->entries) {
5282657471SMarkus Pfeiffer 		free(hashtable);
5382657471SMarkus Pfeiffer 		hashtable = NULL;
5482657471SMarkus Pfeiffer 		goto out;
5582657471SMarkus Pfeiffer 	}
5682657471SMarkus Pfeiffer 
5782657471SMarkus Pfeiffer 	hashtable->nr_elems = hashsize;
5882657471SMarkus Pfeiffer 
5982657471SMarkus Pfeiffer 	for (i = 0; i < hashsize; i++)
6082657471SMarkus Pfeiffer 		LIST_INIT(&hashtable->entries[i]);
6182657471SMarkus Pfeiffer 
6282657471SMarkus Pfeiffer out:
6382657471SMarkus Pfeiffer 	return hashtable;
6482657471SMarkus Pfeiffer }
6582657471SMarkus Pfeiffer 
6682657471SMarkus Pfeiffer int
_hash_destroy(struct hashtable * hashtable)67*ff86f401SSascha Wildner _hash_destroy(struct hashtable *hashtable)
68*ff86f401SSascha Wildner {
6982657471SMarkus Pfeiffer 	struct entries_list *tmp;
7082657471SMarkus Pfeiffer 	u_long hashmask = hashtable->nr_elems -1;
7182657471SMarkus Pfeiffer 
7282657471SMarkus Pfeiffer 	for (tmp = &hashtable->entries[0]; tmp <= &hashtable->entries[hashmask]; tmp++) {
7382657471SMarkus Pfeiffer 		if (!LIST_EMPTY(tmp))
7482657471SMarkus Pfeiffer 			return -1;
7582657471SMarkus Pfeiffer 	}
7682657471SMarkus Pfeiffer 	free(hashtable->entries);
7782657471SMarkus Pfeiffer 	free(hashtable);
7882657471SMarkus Pfeiffer 	hashtable = NULL;
7982657471SMarkus Pfeiffer 	return 0;
8082657471SMarkus Pfeiffer }
8182657471SMarkus Pfeiffer 
8282657471SMarkus Pfeiffer void
_hash_insert(struct hashtable * hashtable,u_long key,void * value)83*ff86f401SSascha Wildner _hash_insert(struct hashtable *hashtable, u_long key, void *value)
84*ff86f401SSascha Wildner {
8582657471SMarkus Pfeiffer 
8682657471SMarkus Pfeiffer 	u_long hashmask = hashtable->nr_elems -1;
8782657471SMarkus Pfeiffer 	struct entries_list *list =
8882657471SMarkus Pfeiffer 		&hashtable->entries[key & hashmask];
8982657471SMarkus Pfeiffer 	struct hashentry *new_entry = malloc(sizeof(struct hashentry));
9082657471SMarkus Pfeiffer 	new_entry->value = value;
9182657471SMarkus Pfeiffer 	new_entry->key = key;
9282657471SMarkus Pfeiffer 	LIST_INSERT_HEAD(list, new_entry, entry_link);
9382657471SMarkus Pfeiffer }
9482657471SMarkus Pfeiffer 
9582657471SMarkus Pfeiffer void *
_hash_lookup(struct hashtable * hashtable,u_long key)96*ff86f401SSascha Wildner _hash_lookup(struct hashtable *hashtable, u_long key)
97*ff86f401SSascha Wildner {
9882657471SMarkus Pfeiffer 
9982657471SMarkus Pfeiffer 	u_long hashmask = hashtable->nr_elems -1;
10082657471SMarkus Pfeiffer 	struct entries_list *list =
10182657471SMarkus Pfeiffer 		&hashtable->entries[key & hashmask];
10282657471SMarkus Pfeiffer 	struct hashentry *tmp;
10382657471SMarkus Pfeiffer 
10482657471SMarkus Pfeiffer 	LIST_FOREACH(tmp, list, entry_link) {
10582657471SMarkus Pfeiffer 		if (tmp->key == key) {
10682657471SMarkus Pfeiffer 			return tmp->value;
10782657471SMarkus Pfeiffer 		}
10882657471SMarkus Pfeiffer 	}
10982657471SMarkus Pfeiffer 
11082657471SMarkus Pfeiffer 	return NULL;
11182657471SMarkus Pfeiffer }
11282657471SMarkus Pfeiffer 
11382657471SMarkus Pfeiffer void *
_hash_remove(struct hashtable * hashtable,u_long key)114*ff86f401SSascha Wildner _hash_remove(struct hashtable *hashtable, u_long key)
115*ff86f401SSascha Wildner {
11682657471SMarkus Pfeiffer 
11782657471SMarkus Pfeiffer 	void *value;
11882657471SMarkus Pfeiffer 	u_long hashmask = hashtable->nr_elems -1;
11982657471SMarkus Pfeiffer 	struct entries_list *list =
12082657471SMarkus Pfeiffer 		&hashtable->entries[key & hashmask];
12182657471SMarkus Pfeiffer 	struct hashentry *tmp;
12282657471SMarkus Pfeiffer 
12382657471SMarkus Pfeiffer 	LIST_FOREACH(tmp, list, entry_link) {
12482657471SMarkus Pfeiffer 		if (tmp->key == key)
12582657471SMarkus Pfeiffer 			goto done;
12682657471SMarkus Pfeiffer 	}
12782657471SMarkus Pfeiffer 
12882657471SMarkus Pfeiffer 	return NULL;
12982657471SMarkus Pfeiffer 
13082657471SMarkus Pfeiffer done:
13182657471SMarkus Pfeiffer 	LIST_REMOVE(tmp, entry_link);
13282657471SMarkus Pfeiffer 	value = tmp->value;
13382657471SMarkus Pfeiffer 	free(tmp);
13482657471SMarkus Pfeiffer 	return value;
13582657471SMarkus Pfeiffer }
13682657471SMarkus Pfeiffer 
13782657471SMarkus Pfeiffer int
get_hash_size(int nr_elems)138*ff86f401SSascha Wildner get_hash_size(int nr_elems)
139*ff86f401SSascha Wildner {
14082657471SMarkus Pfeiffer 	long hashsize = 0;
14182657471SMarkus Pfeiffer 
14282657471SMarkus Pfeiffer 	for (hashsize = 2; hashsize < nr_elems; hashsize <<= 1)
14382657471SMarkus Pfeiffer 		continue;
14482657471SMarkus Pfeiffer 
14582657471SMarkus Pfeiffer 	return hashsize;
14682657471SMarkus Pfeiffer }
147