17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*23a1cceaSRoger A. Faulkner  * Common Development and Distribution License (the "License").
6*23a1cceaSRoger A. Faulkner  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*23a1cceaSRoger A. Faulkner 
227c478bd9Sstevel@tonic-gate /*
23*23a1cceaSRoger A. Faulkner  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <fmd_alloc.h>
277c478bd9Sstevel@tonic-gate #include <fmd_subr.h>
287c478bd9Sstevel@tonic-gate #include <fmd_conf.h>
297c478bd9Sstevel@tonic-gate #include <fmd_error.h>
307c478bd9Sstevel@tonic-gate #include <fmd_string.h>
317c478bd9Sstevel@tonic-gate #include <fmd_idspace.h>
327c478bd9Sstevel@tonic-gate #include <fmd.h>
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate fmd_idspace_t *
fmd_idspace_create(const char * name,id_t min,id_t max)357c478bd9Sstevel@tonic-gate fmd_idspace_create(const char *name, id_t min, id_t max)
367c478bd9Sstevel@tonic-gate {
377c478bd9Sstevel@tonic-gate 	fmd_idspace_t *ids = fmd_alloc(sizeof (fmd_idspace_t), FMD_SLEEP);
387c478bd9Sstevel@tonic-gate 	uint_t ids_avg, ids_max, hashlen, hashmax;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate 	/*
417c478bd9Sstevel@tonic-gate 	 * Dynamically size the hash table bucket array based on the desired
427c478bd9Sstevel@tonic-gate 	 * chain length.  We hash by indexing on the low-order bits.
437c478bd9Sstevel@tonic-gate 	 * Do not permit the hash bucket array to exceed a reasonable size.
447c478bd9Sstevel@tonic-gate 	 */
457c478bd9Sstevel@tonic-gate 	ASSERT(min >= 0 && max >= 0);
467c478bd9Sstevel@tonic-gate 	ASSERT(max >= min);
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 	(void) fmd_conf_getprop(fmd.d_conf, "ids.avg", &ids_avg);
497c478bd9Sstevel@tonic-gate 	(void) fmd_conf_getprop(fmd.d_conf, "ids.max", &ids_max);
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate 	hashmax = max - min + 1;
52*23a1cceaSRoger A. Faulkner 	hashlen = 1 << fls(hashmax / ids_avg);
537c478bd9Sstevel@tonic-gate 	if (hashlen > ids_max)
547c478bd9Sstevel@tonic-gate 		hashlen = ids_max;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 	(void) strlcpy(ids->ids_name, name, sizeof (ids->ids_name));
577c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&ids->ids_lock, NULL);
58d9638e54Smws 	(void) pthread_cond_init(&ids->ids_cv, NULL);
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	ids->ids_hash = fmd_zalloc(sizeof (void *) * hashlen, FMD_SLEEP);
617c478bd9Sstevel@tonic-gate 	ids->ids_hashlen = hashlen;
62d9638e54Smws 	ids->ids_refs = 0;
637c478bd9Sstevel@tonic-gate 	ids->ids_nextid = min - 1;
647c478bd9Sstevel@tonic-gate 	ids->ids_minid = min;
657c478bd9Sstevel@tonic-gate 	ids->ids_maxid = max;
667c478bd9Sstevel@tonic-gate 	ids->ids_count = 0;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	return (ids);
697c478bd9Sstevel@tonic-gate }
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate void
fmd_idspace_destroy(fmd_idspace_t * ids)727c478bd9Sstevel@tonic-gate fmd_idspace_destroy(fmd_idspace_t *ids)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	fmd_idelem_t *ide, *nde;
757c478bd9Sstevel@tonic-gate 	uint_t i;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ids->ids_lock);
787c478bd9Sstevel@tonic-gate 
79d9638e54Smws 	while (ids->ids_refs != 0)
80d9638e54Smws 		(void) pthread_cond_wait(&ids->ids_cv, &ids->ids_lock);
81d9638e54Smws 
827c478bd9Sstevel@tonic-gate 	for (i = 0; i < ids->ids_hashlen; i++) {
837c478bd9Sstevel@tonic-gate 		for (ide = ids->ids_hash[i]; ide != NULL; ide = nde) {
847c478bd9Sstevel@tonic-gate 			nde = ide->ide_next;
857c478bd9Sstevel@tonic-gate 			fmd_free(ide, sizeof (fmd_idelem_t));
867c478bd9Sstevel@tonic-gate 		}
877c478bd9Sstevel@tonic-gate 	}
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	fmd_free(ids->ids_hash, sizeof (void *) * ids->ids_hashlen);
907c478bd9Sstevel@tonic-gate 	fmd_free(ids, sizeof (fmd_idspace_t));
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate void
fmd_idspace_apply(fmd_idspace_t * ids,void (* func)(fmd_idspace_t *,id_t,void *),void * arg)94d9638e54Smws fmd_idspace_apply(fmd_idspace_t *ids,
95d9638e54Smws     void (*func)(fmd_idspace_t *, id_t, void *), void *arg)
967c478bd9Sstevel@tonic-gate {
977c478bd9Sstevel@tonic-gate 	fmd_idelem_t *ide;
987c478bd9Sstevel@tonic-gate 	id_t *ida, *idp;
997c478bd9Sstevel@tonic-gate 	uint_t i, count;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ids->ids_lock);
1027c478bd9Sstevel@tonic-gate 	count = ids->ids_count;
1037c478bd9Sstevel@tonic-gate 	ida = idp = fmd_alloc(sizeof (id_t) * count, FMD_SLEEP);
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	for (i = 0; i < ids->ids_hashlen; i++) {
1067c478bd9Sstevel@tonic-gate 		for (ide = ids->ids_hash[i]; ide != NULL; ide = ide->ide_next)
1077c478bd9Sstevel@tonic-gate 			*idp++ = ide->ide_id;
1087c478bd9Sstevel@tonic-gate 	}
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	ASSERT(idp == ida + count);
1117c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ids->ids_lock);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	for (i = 0; i < count; i++)
114d9638e54Smws 		func(ids, ida[i], arg);
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	fmd_free(ida, sizeof (id_t) * count);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate static fmd_idelem_t *
fmd_idspace_lookup(fmd_idspace_t * ids,id_t id)1207c478bd9Sstevel@tonic-gate fmd_idspace_lookup(fmd_idspace_t *ids, id_t id)
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate 	fmd_idelem_t *ide;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ids->ids_lock));
1257c478bd9Sstevel@tonic-gate 	ide = ids->ids_hash[id & (ids->ids_hashlen - 1)];
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	for (; ide != NULL; ide = ide->ide_next) {
1287c478bd9Sstevel@tonic-gate 		if (ide->ide_id == id)
1297c478bd9Sstevel@tonic-gate 			break;
1307c478bd9Sstevel@tonic-gate 	}
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	return (ide);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate void *
fmd_idspace_getspecific(fmd_idspace_t * ids,id_t id)1367c478bd9Sstevel@tonic-gate fmd_idspace_getspecific(fmd_idspace_t *ids, id_t id)
1377c478bd9Sstevel@tonic-gate {
1387c478bd9Sstevel@tonic-gate 	fmd_idelem_t *ide;
1397c478bd9Sstevel@tonic-gate 	void *data;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ids->ids_lock);
1427c478bd9Sstevel@tonic-gate 	ide = fmd_idspace_lookup(ids, id);
1437c478bd9Sstevel@tonic-gate 	data = ide ? ide->ide_data : NULL;
1447c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ids->ids_lock);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	return (data);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate void
fmd_idspace_setspecific(fmd_idspace_t * ids,id_t id,void * data)1507c478bd9Sstevel@tonic-gate fmd_idspace_setspecific(fmd_idspace_t *ids, id_t id, void *data)
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate 	fmd_idelem_t *ide;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ids->ids_lock);
1557c478bd9Sstevel@tonic-gate 
156d9638e54Smws 	while (ids->ids_refs != 0)
157d9638e54Smws 		(void) pthread_cond_wait(&ids->ids_cv, &ids->ids_lock);
158d9638e54Smws 
1597c478bd9Sstevel@tonic-gate 	if ((ide = fmd_idspace_lookup(ids, id)) == NULL) {
1607c478bd9Sstevel@tonic-gate 		fmd_panic("idspace %p (%s) does not contain id %ld",
1617c478bd9Sstevel@tonic-gate 		    (void *)ids, ids->ids_name, id);
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	ide->ide_data = data;
1657c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ids->ids_lock);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate int
fmd_idspace_contains(fmd_idspace_t * ids,id_t id)1697c478bd9Sstevel@tonic-gate fmd_idspace_contains(fmd_idspace_t *ids, id_t id)
1707c478bd9Sstevel@tonic-gate {
1717c478bd9Sstevel@tonic-gate 	fmd_idelem_t *ide;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ids->ids_lock);
1747c478bd9Sstevel@tonic-gate 	ide = fmd_idspace_lookup(ids, id);
1757c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ids->ids_lock);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	return (ide != NULL);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate int
fmd_idspace_valid(fmd_idspace_t * ids,id_t id)1817c478bd9Sstevel@tonic-gate fmd_idspace_valid(fmd_idspace_t *ids, id_t id)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate 	return (id >= ids->ids_minid && id <= ids->ids_maxid);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate static id_t
fmd_idspace_xalloc_locked(fmd_idspace_t * ids,id_t id,void * data)1877c478bd9Sstevel@tonic-gate fmd_idspace_xalloc_locked(fmd_idspace_t *ids, id_t id, void *data)
1887c478bd9Sstevel@tonic-gate {
1897c478bd9Sstevel@tonic-gate 	fmd_idelem_t *ide;
1907c478bd9Sstevel@tonic-gate 	uint_t h;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	if (id < ids->ids_minid || id > ids->ids_maxid) {
1937c478bd9Sstevel@tonic-gate 		fmd_panic("%ld out of range [%ld .. %ld] for idspace %p (%s)\n",
1947c478bd9Sstevel@tonic-gate 		    id, ids->ids_minid, ids->ids_maxid,
1957c478bd9Sstevel@tonic-gate 		    (void *)ids, ids->ids_name);
1967c478bd9Sstevel@tonic-gate 	}
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	if (fmd_idspace_lookup(ids, id) != NULL)
1997c478bd9Sstevel@tonic-gate 		return (fmd_set_errno(EALREADY));
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	ide = fmd_alloc(sizeof (fmd_idelem_t), FMD_SLEEP);
2027c478bd9Sstevel@tonic-gate 	h = id & (ids->ids_hashlen - 1);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	ide->ide_next = ids->ids_hash[h];
2057c478bd9Sstevel@tonic-gate 	ide->ide_data = data;
2067c478bd9Sstevel@tonic-gate 	ide->ide_id = id;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	ids->ids_hash[h] = ide;
2097c478bd9Sstevel@tonic-gate 	ids->ids_count++;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	return (id);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate id_t
fmd_idspace_xalloc(fmd_idspace_t * ids,id_t id,void * data)2157c478bd9Sstevel@tonic-gate fmd_idspace_xalloc(fmd_idspace_t *ids, id_t id, void *data)
2167c478bd9Sstevel@tonic-gate {
2177c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ids->ids_lock);
2187c478bd9Sstevel@tonic-gate 	id = fmd_idspace_xalloc_locked(ids, id, data);
2197c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ids->ids_lock);
2207c478bd9Sstevel@tonic-gate 	return (id);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate 
223d9638e54Smws static id_t
fmd_idspace_alloc_locked(fmd_idspace_t * ids,void * data)224d9638e54Smws fmd_idspace_alloc_locked(fmd_idspace_t *ids, void *data)
2257c478bd9Sstevel@tonic-gate {
2267c478bd9Sstevel@tonic-gate 	id_t id;
2277c478bd9Sstevel@tonic-gate 
228d9638e54Smws 	ASSERT(MUTEX_HELD(&ids->ids_lock));
2297c478bd9Sstevel@tonic-gate 
230d9638e54Smws 	if (ids->ids_count == ids->ids_maxid - ids->ids_minid + 1)
2317c478bd9Sstevel@tonic-gate 		return (fmd_set_errno(ENOSPC));
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	do {
2347c478bd9Sstevel@tonic-gate 		if (++ids->ids_nextid > ids->ids_maxid)
2357c478bd9Sstevel@tonic-gate 			ids->ids_nextid = ids->ids_minid;
2367c478bd9Sstevel@tonic-gate 		id = ids->ids_nextid;
2377c478bd9Sstevel@tonic-gate 	} while (fmd_idspace_xalloc_locked(ids, id, data) != id);
2387c478bd9Sstevel@tonic-gate 
239d9638e54Smws 	return (id);
240d9638e54Smws }
241d9638e54Smws 
242d9638e54Smws id_t
fmd_idspace_alloc(fmd_idspace_t * ids,void * data)243d9638e54Smws fmd_idspace_alloc(fmd_idspace_t *ids, void *data)
244d9638e54Smws {
245d9638e54Smws 	id_t id;
246d9638e54Smws 
247d9638e54Smws 	(void) pthread_mutex_lock(&ids->ids_lock);
248d9638e54Smws 	id = fmd_idspace_alloc_locked(ids, data);
2497c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ids->ids_lock);
250d9638e54Smws 
251d9638e54Smws 	return (id);
252d9638e54Smws }
253d9638e54Smws 
254d9638e54Smws /*
255d9638e54Smws  * For the moment, we use a simple but slow implementation: reset ids_nextid to
256d9638e54Smws  * the minimum id and search in order from there.  If this becomes performance
257d9638e54Smws  * sensitive we can maintain a freelist of the unallocated identifiers, etc.
258d9638e54Smws  */
259d9638e54Smws id_t
fmd_idspace_alloc_min(fmd_idspace_t * ids,void * data)260d9638e54Smws fmd_idspace_alloc_min(fmd_idspace_t *ids, void *data)
261d9638e54Smws {
262d9638e54Smws 	id_t id;
263d9638e54Smws 
264d9638e54Smws 	(void) pthread_mutex_lock(&ids->ids_lock);
265d9638e54Smws 	ids->ids_nextid = ids->ids_minid - 1;
266d9638e54Smws 	id = fmd_idspace_alloc_locked(ids, data);
267d9638e54Smws 	(void) pthread_mutex_unlock(&ids->ids_lock);
268d9638e54Smws 
2697c478bd9Sstevel@tonic-gate 	return (id);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate void *
fmd_idspace_free(fmd_idspace_t * ids,id_t id)2737c478bd9Sstevel@tonic-gate fmd_idspace_free(fmd_idspace_t *ids, id_t id)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	fmd_idelem_t *ide, **pp;
2767c478bd9Sstevel@tonic-gate 	void *data;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&ids->ids_lock);
2797c478bd9Sstevel@tonic-gate 	pp = &ids->ids_hash[id & (ids->ids_hashlen - 1)];
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	for (ide = *pp; ide != NULL; ide = ide->ide_next) {
2827c478bd9Sstevel@tonic-gate 		if (ide->ide_id != id)
2837c478bd9Sstevel@tonic-gate 			pp = &ide->ide_next;
2847c478bd9Sstevel@tonic-gate 		else
2857c478bd9Sstevel@tonic-gate 			break;
2867c478bd9Sstevel@tonic-gate 	}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	if (ide == NULL) {
2897c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&ids->ids_lock);
2907c478bd9Sstevel@tonic-gate 		return (NULL);
2917c478bd9Sstevel@tonic-gate 	}
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	data = ide->ide_data;
2947c478bd9Sstevel@tonic-gate 	*pp = ide->ide_next;
2957c478bd9Sstevel@tonic-gate 	fmd_free(ide, sizeof (fmd_idelem_t));
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	ASSERT(ids->ids_count != 0);
2987c478bd9Sstevel@tonic-gate 	ids->ids_count--;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&ids->ids_lock);
3017c478bd9Sstevel@tonic-gate 	return (data);
3027c478bd9Sstevel@tonic-gate }
303d9638e54Smws 
304d9638e54Smws /*
305d9638e54Smws  * Retrieve the id-specific data for the specified id and place a hold on the
306d9638e54Smws  * id so that it cannot be or deleted until fmd_idspace_rele(ids, id) is
307d9638e54Smws  * called.  For simplicity, we now use a single global reference count for all
308d9638e54Smws  * holds.  If this feature needs to be used in a place where there is high
309d9638e54Smws  * contention between holders and deleters, the implementation can be modified
310d9638e54Smws  * to use either a per-hash-bucket or a per-id-element condition variable.
311d9638e54Smws  */
312d9638e54Smws void *
fmd_idspace_hold(fmd_idspace_t * ids,id_t id)313d9638e54Smws fmd_idspace_hold(fmd_idspace_t *ids, id_t id)
314d9638e54Smws {
315d9638e54Smws 	fmd_idelem_t *ide;
316d9638e54Smws 	void *data = NULL;
317d9638e54Smws 
318d9638e54Smws 	(void) pthread_mutex_lock(&ids->ids_lock);
319d9638e54Smws 
320d9638e54Smws 	if ((ide = fmd_idspace_lookup(ids, id)) != NULL) {
321d9638e54Smws 		ids->ids_refs++;
322d9638e54Smws 		ASSERT(ids->ids_refs != 0);
323d9638e54Smws 		data = ide->ide_data;
324d9638e54Smws 		ASSERT(data != NULL);
325d9638e54Smws 	}
326d9638e54Smws 
327d9638e54Smws 	(void) pthread_mutex_unlock(&ids->ids_lock);
328d9638e54Smws 	return (data);
329d9638e54Smws }
330d9638e54Smws 
331d9638e54Smws void
fmd_idspace_rele(fmd_idspace_t * ids,id_t id)332d9638e54Smws fmd_idspace_rele(fmd_idspace_t *ids, id_t id)
333d9638e54Smws {
334d9638e54Smws 	(void) pthread_mutex_lock(&ids->ids_lock);
335d9638e54Smws 
336d9638e54Smws 	ASSERT(fmd_idspace_lookup(ids, id) != NULL);
337d9638e54Smws 	ASSERT(ids->ids_refs != 0);
338d9638e54Smws 	ids->ids_refs--;
339d9638e54Smws 
340d9638e54Smws 	(void) pthread_cond_broadcast(&ids->ids_cv);
341d9638e54Smws 	(void) pthread_mutex_unlock(&ids->ids_lock);
342d9638e54Smws }
343