19e39c5baSBill Taylor /*
29e39c5baSBill Taylor  * CDDL HEADER START
39e39c5baSBill Taylor  *
49e39c5baSBill Taylor  * The contents of this file are subject to the terms of the
59e39c5baSBill Taylor  * Common Development and Distribution License (the "License").
69e39c5baSBill Taylor  * You may not use this file except in compliance with the License.
79e39c5baSBill Taylor  *
89e39c5baSBill Taylor  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99e39c5baSBill Taylor  * or http://www.opensolaris.org/os/licensing.
109e39c5baSBill Taylor  * See the License for the specific language governing permissions
119e39c5baSBill Taylor  * and limitations under the License.
129e39c5baSBill Taylor  *
139e39c5baSBill Taylor  * When distributing Covered Code, include this CDDL HEADER in each
149e39c5baSBill Taylor  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159e39c5baSBill Taylor  * If applicable, add the following below this CDDL HEADER, with the
169e39c5baSBill Taylor  * fields enclosed by brackets "[]" replaced with your own identifying
179e39c5baSBill Taylor  * information: Portions Copyright [yyyy] [name of copyright owner]
189e39c5baSBill Taylor  *
199e39c5baSBill Taylor  * CDDL HEADER END
209e39c5baSBill Taylor  */
219e39c5baSBill Taylor 
229e39c5baSBill Taylor /*
239e39c5baSBill Taylor  * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
249e39c5baSBill Taylor  */
259e39c5baSBill Taylor 
269e39c5baSBill Taylor /*
279e39c5baSBill Taylor  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
289e39c5baSBill Taylor  * Use is subject to license terms.
299e39c5baSBill Taylor  */
309e39c5baSBill Taylor 
319e39c5baSBill Taylor /*
329e39c5baSBill Taylor  *
339e39c5baSBill Taylor  * MODULE: dapl_osd.c
349e39c5baSBill Taylor  *
359e39c5baSBill Taylor  * PURPOSE: Operating System Dependent layer
369e39c5baSBill Taylor  * Description:
379e39c5baSBill Taylor  *	Provide OS dependent functions with a canonical DAPL
389e39c5baSBill Taylor  *	interface. Designed to be portable and hide OS specific quirks
399e39c5baSBill Taylor  *	of common functions.
409e39c5baSBill Taylor  *
419e39c5baSBill Taylor  *
429e39c5baSBill Taylor  * $Id: dapl_osd.c,v 1.26 2003/07/31 14:04:18 jlentini Exp $
439e39c5baSBill Taylor  */
449e39c5baSBill Taylor 
459e39c5baSBill Taylor #include "dapl_osd.h"
469e39c5baSBill Taylor #include "dapl.h"
479e39c5baSBill Taylor #include "dapl_hca_util.h"
489e39c5baSBill Taylor #include "dapl_ia_util.h"
499e39c5baSBill Taylor #include "dapl_rmr_util.h"
509e39c5baSBill Taylor #include "dapl_lmr_util.h"
519e39c5baSBill Taylor #include "dapl_pz_util.h"
529e39c5baSBill Taylor #include "dapl_ep_util.h"
539e39c5baSBill Taylor #include "dapl_cr_util.h"
549e39c5baSBill Taylor #include "dapl_evd_util.h"
559e39c5baSBill Taylor #include "dapl_sp_util.h"
569e39c5baSBill Taylor #include "dapl_adapter_util.h"
579e39c5baSBill Taylor #include "dapl_provider.h"
589e39c5baSBill Taylor #include "dapl_hash.h"
599e39c5baSBill Taylor #include "dapl_debug.h"
609e39c5baSBill Taylor 
619e39c5baSBill Taylor #include <sys/time.h>
629e39c5baSBill Taylor #include <stdlib.h>			/* needed for getenv() */
639e39c5baSBill Taylor #include <pthread.h>			/* needed for pthread_atfork() */
649e39c5baSBill Taylor #include <signal.h>			/* needed for thread setup */
659e39c5baSBill Taylor 
669e39c5baSBill Taylor static void dapls_osd_fork_cleanup(void);
679e39c5baSBill Taylor 
689e39c5baSBill Taylor /*
699e39c5baSBill Taylor  * dapl_osd_init
709e39c5baSBill Taylor  *
719e39c5baSBill Taylor  * Do Linux initialization:
729e39c5baSBill Taylor  * - Set up fork handler to clean up DAPL resources in the child
739e39c5baSBill Taylor  *   process after a fork().
749e39c5baSBill Taylor  *
759e39c5baSBill Taylor  * Input:
769e39c5baSBill Taylor  *      none
779e39c5baSBill Taylor  *
789e39c5baSBill Taylor  * Returns:
799e39c5baSBill Taylor  *	DAT_SUCCESS
809e39c5baSBill Taylor  */
819e39c5baSBill Taylor void
dapl_os_init()829e39c5baSBill Taylor dapl_os_init()
839e39c5baSBill Taylor {
849e39c5baSBill Taylor 	int status;
859e39c5baSBill Taylor 
869e39c5baSBill Taylor 	/*
879e39c5baSBill Taylor 	 * Set up fork control
889e39c5baSBill Taylor 	 */
899e39c5baSBill Taylor 	status = pthread_atfork(NULL, NULL, dapls_osd_fork_cleanup);
909e39c5baSBill Taylor 	if (status != 0) {
919e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_WARN,
929e39c5baSBill Taylor 		    "WARNING: pthread_atfork %d\n", status);
939e39c5baSBill Taylor 	}
949e39c5baSBill Taylor }
959e39c5baSBill Taylor 
969e39c5baSBill Taylor 
979e39c5baSBill Taylor /*
989e39c5baSBill Taylor  * dapl_os_get_time
999e39c5baSBill Taylor  *
1009e39c5baSBill Taylor  * Return 64 bit value of current time in microseconds.
1019e39c5baSBill Taylor  *
1029e39c5baSBill Taylor  * Input:
1039e39c5baSBill Taylor  *      loc       User location to place current time
1049e39c5baSBill Taylor  *
1059e39c5baSBill Taylor  * Returns:
1069e39c5baSBill Taylor  *	DAT_SUCCESS
1079e39c5baSBill Taylor  */
1089e39c5baSBill Taylor 
1099e39c5baSBill Taylor DAT_RETURN
dapl_os_get_time(OUT DAPL_OS_TIMEVAL * loc)1109e39c5baSBill Taylor dapl_os_get_time(
1119e39c5baSBill Taylor     OUT DAPL_OS_TIMEVAL * loc)
1129e39c5baSBill Taylor {
1139e39c5baSBill Taylor 	struct timeval	tv;
1149e39c5baSBill Taylor 	struct timezone	tz;
1159e39c5baSBill Taylor 
1169e39c5baSBill Taylor 
1179e39c5baSBill Taylor 	(void) gettimeofday(&tv, &tz);
1189e39c5baSBill Taylor 	*loc = ((DAT_UINT64)(tv.tv_sec) * 1000000L) + (DAT_UINT64) tv.tv_usec;
1199e39c5baSBill Taylor 
1209e39c5baSBill Taylor 	return (DAT_SUCCESS);
1219e39c5baSBill Taylor }
1229e39c5baSBill Taylor 
1239e39c5baSBill Taylor 
1249e39c5baSBill Taylor /*
1259e39c5baSBill Taylor  * dapl_os_get__env_bool
1269e39c5baSBill Taylor  *
1279e39c5baSBill Taylor  * Return boolean value of passed in environment variable: 1 if present,
1289e39c5baSBill Taylor  * 0 if not
1299e39c5baSBill Taylor  *
1309e39c5baSBill Taylor  * Input:
1319e39c5baSBill Taylor  *
1329e39c5baSBill Taylor  *
1339e39c5baSBill Taylor  * Returns:
1349e39c5baSBill Taylor  *	TRUE or FALSE
1359e39c5baSBill Taylor  */
1369e39c5baSBill Taylor int
dapl_os_get_env_bool(char * env_str)1379e39c5baSBill Taylor dapl_os_get_env_bool(
1389e39c5baSBill Taylor 	char		*env_str)
1399e39c5baSBill Taylor {
1409e39c5baSBill Taylor 	char		*env_var;
1419e39c5baSBill Taylor 
1429e39c5baSBill Taylor 	env_var = getenv(env_str);
1439e39c5baSBill Taylor 	if (env_var != NULL) {
1449e39c5baSBill Taylor 		return (1);
1459e39c5baSBill Taylor 	}
1469e39c5baSBill Taylor 
1479e39c5baSBill Taylor 	return (0);
1489e39c5baSBill Taylor }
1499e39c5baSBill Taylor 
1509e39c5baSBill Taylor 
1519e39c5baSBill Taylor /*
1529e39c5baSBill Taylor  * dapl_os_get_env_val
1539e39c5baSBill Taylor  *
1549e39c5baSBill Taylor  * Update val to  value of passed in environment variable if present
1559e39c5baSBill Taylor  *
1569e39c5baSBill Taylor  * Input:
1579e39c5baSBill Taylor  *      env_str
1589e39c5baSBill Taylor  *	def_val		default value if environment variable does not exist
1599e39c5baSBill Taylor  *
1609e39c5baSBill Taylor  * Returns:
1619e39c5baSBill Taylor  *	TRUE or FALSE
1629e39c5baSBill Taylor  */
1639e39c5baSBill Taylor int
dapl_os_get_env_val(char * env_str,int def_val)1649e39c5baSBill Taylor dapl_os_get_env_val(
1659e39c5baSBill Taylor 	char		*env_str,
1669e39c5baSBill Taylor 	int		def_val)
1679e39c5baSBill Taylor {
1689e39c5baSBill Taylor 	char		*env_var;
1699e39c5baSBill Taylor 
1709e39c5baSBill Taylor 	env_var = getenv(env_str);
1719e39c5baSBill Taylor 	if (env_var != NULL) {
1729e39c5baSBill Taylor 		def_val = strtol(env_var, NULL, 0);
1739e39c5baSBill Taylor 	}
1749e39c5baSBill Taylor 
1759e39c5baSBill Taylor 	return (def_val);
1769e39c5baSBill Taylor }
1779e39c5baSBill Taylor 
1789e39c5baSBill Taylor 
1799e39c5baSBill Taylor /*
1809e39c5baSBill Taylor  * Wait object routines
1819e39c5baSBill Taylor  */
1829e39c5baSBill Taylor 
1839e39c5baSBill Taylor /*
1849e39c5baSBill Taylor  * dapl_os_wait_object_init
1859e39c5baSBill Taylor  *
1869e39c5baSBill Taylor  * Initialize a wait object
1879e39c5baSBill Taylor  *
1889e39c5baSBill Taylor  * Input:
1899e39c5baSBill Taylor  *	wait_obj
1909e39c5baSBill Taylor  *
1919e39c5baSBill Taylor  * Returns:
1929e39c5baSBill Taylor  *	DAT_SUCCESS
1939e39c5baSBill Taylor  *	DAT_INTERNAL_ERROR
1949e39c5baSBill Taylor  */
1959e39c5baSBill Taylor DAT_RETURN
dapl_os_wait_object_init(IN DAPL_OS_WAIT_OBJECT * wait_obj)1969e39c5baSBill Taylor dapl_os_wait_object_init(
1979e39c5baSBill Taylor     IN DAPL_OS_WAIT_OBJECT *wait_obj)
1989e39c5baSBill Taylor {
1999e39c5baSBill Taylor 	wait_obj->signaled = DAT_FALSE;
2009e39c5baSBill Taylor 	if (0 != pthread_cond_init(&wait_obj->cv, NULL)) {
2019e39c5baSBill Taylor 		return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
2029e39c5baSBill Taylor 	}
2039e39c5baSBill Taylor 
2049e39c5baSBill Taylor 	/* Always returns 0.  */
2059e39c5baSBill Taylor 	(void) pthread_mutex_init(&wait_obj->lock, NULL);
2069e39c5baSBill Taylor 
2079e39c5baSBill Taylor 	return (DAT_SUCCESS);
2089e39c5baSBill Taylor }
2099e39c5baSBill Taylor 
2109e39c5baSBill Taylor 
2119e39c5baSBill Taylor /*
2129e39c5baSBill Taylor  * Wait on the supplied wait object, up to the specified time_out.
2139e39c5baSBill Taylor  * A timeout of DAT_TIMEOUT_INFINITE will wait indefinitely.
2149e39c5baSBill Taylor  * Timeout should be specified in micro seconds.
2159e39c5baSBill Taylor  *
2169e39c5baSBill Taylor  * Functional returns:
2179e39c5baSBill Taylor  *	DAT_SUCCESS -- another thread invoked dapl_os_wait object_wakeup
2189e39c5baSBill Taylor  * 	DAT_INVALID_STATE -- someone else is already waiting in this wait
2199e39c5baSBill Taylor  * 	object.
2209e39c5baSBill Taylor  *			     only one waiter is allowed at a time.
2219e39c5baSBill Taylor  *	DAT_ABORT -- another thread invoked dapl_os_wait_object_destroy
2229e39c5baSBill Taylor  *	DAT_TIMEOUT -- the specified time limit was reached.
2239e39c5baSBill Taylor  */
2249e39c5baSBill Taylor 
2259e39c5baSBill Taylor DAT_RETURN
dapl_os_wait_object_wait(IN DAPL_OS_WAIT_OBJECT * wait_obj,IN DAT_TIMEOUT timeout_val)2269e39c5baSBill Taylor dapl_os_wait_object_wait(
2279e39c5baSBill Taylor 	IN  DAPL_OS_WAIT_OBJECT *wait_obj,
2289e39c5baSBill Taylor 	IN  DAT_TIMEOUT timeout_val)
2299e39c5baSBill Taylor {
2309e39c5baSBill Taylor 	DAT_RETURN 		dat_status;
2319e39c5baSBill Taylor 	int			pthread_status;
2329e39c5baSBill Taylor 	struct timespec 	future;
2339e39c5baSBill Taylor 
2349e39c5baSBill Taylor 	dat_status = DAT_SUCCESS;
2359e39c5baSBill Taylor 	pthread_status = 0;
2369e39c5baSBill Taylor 
2379e39c5baSBill Taylor 	if (timeout_val != DAT_TIMEOUT_INFINITE) {
2389e39c5baSBill Taylor 		struct timeval now;
2399e39c5baSBill Taylor 		struct timezone tz;
2409e39c5baSBill Taylor 		unsigned int microsecs;
2419e39c5baSBill Taylor 
2429e39c5baSBill Taylor 		(void) gettimeofday(&now, &tz);
2439e39c5baSBill Taylor 		microsecs = now.tv_usec + (timeout_val % 1000000);
2449e39c5baSBill Taylor 		if (microsecs > 1000000) {
2459e39c5baSBill Taylor 			now.tv_sec = now.tv_sec + timeout_val / 1000000 + 1;
2469e39c5baSBill Taylor 			now.tv_usec = microsecs - 1000000;
2479e39c5baSBill Taylor 		} else {
2489e39c5baSBill Taylor 			now.tv_sec = now.tv_sec + timeout_val / 1000000;
2499e39c5baSBill Taylor 			now.tv_usec = microsecs;
2509e39c5baSBill Taylor 		}
2519e39c5baSBill Taylor 
2529e39c5baSBill Taylor 		/* Convert timeval to timespec */
2539e39c5baSBill Taylor 		future.tv_sec = now.tv_sec;
2549e39c5baSBill Taylor 		future.tv_nsec = now.tv_usec * 1000;
2559e39c5baSBill Taylor 
2569e39c5baSBill Taylor 		(void) pthread_mutex_lock(&wait_obj->lock);
2579e39c5baSBill Taylor 		while (wait_obj->signaled == DAT_FALSE && pthread_status == 0) {
2589e39c5baSBill Taylor 			pthread_status = pthread_cond_timedwait(
2599e39c5baSBill Taylor 			    &wait_obj->cv, &wait_obj->lock, &future);
2609e39c5baSBill Taylor 
2619e39c5baSBill Taylor 			/*
2629e39c5baSBill Taylor 			 * No need to reset &future if we go around the loop;
2639e39c5baSBill Taylor 			 * It's an absolute time.
2649e39c5baSBill Taylor 			 */
2659e39c5baSBill Taylor 		}
2669e39c5baSBill Taylor 		/* Reset the signaled status if we were woken up.  */
2679e39c5baSBill Taylor 		if (pthread_status == 0) {
2689e39c5baSBill Taylor 			wait_obj->signaled = DAT_FALSE;
2699e39c5baSBill Taylor 		}
2709e39c5baSBill Taylor 		(void) pthread_mutex_unlock(&wait_obj->lock);
2719e39c5baSBill Taylor 	} else {
2729e39c5baSBill Taylor 		(void) pthread_mutex_lock(&wait_obj->lock);
2739e39c5baSBill Taylor 		while (wait_obj->signaled == DAT_FALSE && pthread_status == 0) {
2749e39c5baSBill Taylor 			pthread_status = pthread_cond_wait(
2759e39c5baSBill Taylor 			    &wait_obj->cv, &wait_obj->lock);
2769e39c5baSBill Taylor 		}
2779e39c5baSBill Taylor 		/* Reset the signaled status if we were woken up.  */
2789e39c5baSBill Taylor 		if (pthread_status == 0) {
2799e39c5baSBill Taylor 			wait_obj->signaled = DAT_FALSE;
2809e39c5baSBill Taylor 		}
2819e39c5baSBill Taylor 		(void) pthread_mutex_unlock(&wait_obj->lock);
2829e39c5baSBill Taylor 	}
2839e39c5baSBill Taylor 
2849e39c5baSBill Taylor 	if (ETIMEDOUT == pthread_status) {
2859e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_TIMEOUT_EXPIRED, 0);
2869e39c5baSBill Taylor 	} else if (0 != pthread_status) {
2879e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INTERNAL_ERROR, 0);
2889e39c5baSBill Taylor 	}
2899e39c5baSBill Taylor 
2909e39c5baSBill Taylor 	return (dat_status);
2919e39c5baSBill Taylor }
2929e39c5baSBill Taylor 
2939e39c5baSBill Taylor 
2949e39c5baSBill Taylor /*
2959e39c5baSBill Taylor  * dapl_os_wait_object_wakeup
2969e39c5baSBill Taylor  *
2979e39c5baSBill Taylor  * Wakeup a thread waiting on a wait object
2989e39c5baSBill Taylor  *
2999e39c5baSBill Taylor  * Input:
3009e39c5baSBill Taylor  *      wait_obj
3019e39c5baSBill Taylor  *
3029e39c5baSBill Taylor  * Returns:
3039e39c5baSBill Taylor  *	DAT_SUCCESS
3049e39c5baSBill Taylor  *	DAT_INTERNAL_ERROR
3059e39c5baSBill Taylor  */
3069e39c5baSBill Taylor DAT_RETURN
dapl_os_wait_object_wakeup(IN DAPL_OS_WAIT_OBJECT * wait_obj)3079e39c5baSBill Taylor dapl_os_wait_object_wakeup(
3089e39c5baSBill Taylor     IN	DAPL_OS_WAIT_OBJECT *wait_obj)
3099e39c5baSBill Taylor {
3109e39c5baSBill Taylor 	(void) pthread_mutex_lock(&wait_obj->lock);
3119e39c5baSBill Taylor 	wait_obj->signaled = DAT_TRUE;
3129e39c5baSBill Taylor 	(void) pthread_mutex_unlock(&wait_obj->lock);
3139e39c5baSBill Taylor 	if (0 != pthread_cond_signal(&wait_obj->cv)) {
3149e39c5baSBill Taylor 		return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
3159e39c5baSBill Taylor 	}
3169e39c5baSBill Taylor 
3179e39c5baSBill Taylor 	return (DAT_SUCCESS);
3189e39c5baSBill Taylor }
3199e39c5baSBill Taylor 
3209e39c5baSBill Taylor 
3219e39c5baSBill Taylor /*
3229e39c5baSBill Taylor  * dapl_os_wait_object_destroy
3239e39c5baSBill Taylor  *
3249e39c5baSBill Taylor  * Destroy a wait object
3259e39c5baSBill Taylor  *
3269e39c5baSBill Taylor  * Input:
3279e39c5baSBill Taylor  *      wait_obj
3289e39c5baSBill Taylor  *
3299e39c5baSBill Taylor  * Returns:
3309e39c5baSBill Taylor  *	DAT_SUCCESS
3319e39c5baSBill Taylor  *	DAT_INTERNAL_ERROR
3329e39c5baSBill Taylor  */
3339e39c5baSBill Taylor DAT_RETURN
dapl_os_wait_object_destroy(IN DAPL_OS_WAIT_OBJECT * wait_obj)3349e39c5baSBill Taylor dapl_os_wait_object_destroy(
3359e39c5baSBill Taylor     IN	DAPL_OS_WAIT_OBJECT *wait_obj)
3369e39c5baSBill Taylor {
3379e39c5baSBill Taylor 	if (0 != pthread_cond_destroy(&wait_obj->cv)) {
3389e39c5baSBill Taylor 		return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
3399e39c5baSBill Taylor 	}
3409e39c5baSBill Taylor 	if (0 != pthread_mutex_destroy(&wait_obj->lock)) {
3419e39c5baSBill Taylor 		return (DAT_ERROR(DAT_INTERNAL_ERROR, 0));
3429e39c5baSBill Taylor 	}
3439e39c5baSBill Taylor 
3449e39c5baSBill Taylor 	return (DAT_SUCCESS);
3459e39c5baSBill Taylor }
3469e39c5baSBill Taylor 
3479e39c5baSBill Taylor 
3489e39c5baSBill Taylor /*
3499e39c5baSBill Taylor  * dapls_osd_fork_cleanup
3509e39c5baSBill Taylor  *
3519e39c5baSBill Taylor  * Update val to  value of passed in environment variable if present
3529e39c5baSBill Taylor  *
3539e39c5baSBill Taylor  * Input:
3549e39c5baSBill Taylor  *      env_str
3559e39c5baSBill Taylor  *	val		Updated if environment variable exists
3569e39c5baSBill Taylor  *
3579e39c5baSBill Taylor  * Returns:
3589e39c5baSBill Taylor  *	TRUE or FALSE
3599e39c5baSBill Taylor  */
3609e39c5baSBill Taylor void
dapls_osd_fork_cleanup(void)3619e39c5baSBill Taylor dapls_osd_fork_cleanup(void)
3629e39c5baSBill Taylor {
3639e39c5baSBill Taylor 	DAPL_PROVIDER_LIST_NODE 	*cur_node;
3649e39c5baSBill Taylor 	DAPL_HCA			*hca_ptr;
3659e39c5baSBill Taylor 	DAPL_IA				*ia_ptr;
3669e39c5baSBill Taylor 	DAPL_LMR 			*lmr_ptr;
3679e39c5baSBill Taylor 	DAPL_RMR			*rmr_ptr;
3689e39c5baSBill Taylor 	DAPL_PZ				*pz_ptr;
3699e39c5baSBill Taylor 	DAPL_CR				*cr_ptr;
3709e39c5baSBill Taylor 	DAPL_EP				*ep_ptr;
3719e39c5baSBill Taylor 	DAPL_EVD			*evd_ptr;
3729e39c5baSBill Taylor 	DAT_EP_PARAM			*param;
3739e39c5baSBill Taylor 	DAPL_SP				*sp_ptr;
3749e39c5baSBill Taylor 
3759e39c5baSBill Taylor 	while (NULL != g_dapl_provider_list.head) {
3769e39c5baSBill Taylor 		cur_node = g_dapl_provider_list.head;
3779e39c5baSBill Taylor 		g_dapl_provider_list.head = cur_node->next;
3789e39c5baSBill Taylor 
3799e39c5baSBill Taylor 		hca_ptr = (DAPL_HCA *) cur_node->data.extension;
3809e39c5baSBill Taylor 
3819e39c5baSBill Taylor 		/*
3829e39c5baSBill Taylor 		 * Walk the list of IA ptrs & clean up. This is purposely
3839e39c5baSBill Taylor 		 * a destructive list walk, we really don't want to preserve
3849e39c5baSBill Taylor 		 * any of it.
3859e39c5baSBill Taylor 		 */
3869e39c5baSBill Taylor 		while (!dapl_llist_is_empty(&hca_ptr->ia_list_head)) {
3879e39c5baSBill Taylor 			ia_ptr = (DAPL_IA *)
3889e39c5baSBill Taylor 			    dapl_llist_peek_head(&hca_ptr->ia_list_head);
3899e39c5baSBill Taylor 
3909e39c5baSBill Taylor 			/*
3919e39c5baSBill Taylor 			 * The rest of the cleanup code is similar to
3929e39c5baSBill Taylor 			 * dapl_ia_close, the big difference is that we don't
3939e39c5baSBill Taylor 			 * release IB resources, only memory; the underlying IB
3949e39c5baSBill Taylor 			 * subsystem doesn't deal with fork at all, so leave
3959e39c5baSBill Taylor 			 * IB handles alone.
3969e39c5baSBill Taylor 			 */
3979e39c5baSBill Taylor 			while (!dapl_llist_is_empty(&ia_ptr->rmr_list_head)) {
3989e39c5baSBill Taylor 				rmr_ptr = (DAPL_RMR *)
3999e39c5baSBill Taylor 				    dapl_llist_peek_head(&ia_ptr->
4009e39c5baSBill Taylor 				    rmr_list_head);
4019e39c5baSBill Taylor 				if (rmr_ptr->param.lmr_triplet.
4029e39c5baSBill Taylor 				    virtual_address != 0) {
403*fb4cdc19SToomas Soome 					dapl_os_atomic_dec(&rmr_ptr->
4049e39c5baSBill Taylor 					    lmr->lmr_ref_count);
4059e39c5baSBill Taylor 					rmr_ptr->param.lmr_triplet.
4069e39c5baSBill Taylor 					    virtual_address = 0;
4079e39c5baSBill Taylor 				}
4089e39c5baSBill Taylor 				dapl_os_atomic_dec(&rmr_ptr->pz->pz_ref_count);
4099e39c5baSBill Taylor 				dapl_ia_unlink_rmr(rmr_ptr->header.owner_ia,
4109e39c5baSBill Taylor 				    rmr_ptr);
4119e39c5baSBill Taylor 				dapl_rmr_dealloc(rmr_ptr);
4129e39c5baSBill Taylor 			}
4139e39c5baSBill Taylor 
4149e39c5baSBill Taylor 			while (!dapl_llist_is_empty(&ia_ptr->rsp_list_head)) {
4159e39c5baSBill Taylor 				sp_ptr = (DAPL_SP *) dapl_llist_peek_head(
4169e39c5baSBill Taylor 				    &ia_ptr->rsp_list_head);
4179e39c5baSBill Taylor 				dapl_os_atomic_dec(&((DAPL_EVD *)sp_ptr->
4189e39c5baSBill Taylor 				    evd_handle)->evd_ref_count);
4199e39c5baSBill Taylor 				dapls_ia_unlink_sp(ia_ptr, sp_ptr);
4209e39c5baSBill Taylor 				dapls_sp_free_sp(sp_ptr);
4219e39c5baSBill Taylor 			}
4229e39c5baSBill Taylor 
4239e39c5baSBill Taylor 			while (!dapl_llist_is_empty(&ia_ptr->ep_list_head)) {
4249e39c5baSBill Taylor 				ep_ptr = (DAPL_EP *) dapl_llist_peek_head(
4259e39c5baSBill Taylor 				    &ia_ptr->ep_list_head);
4269e39c5baSBill Taylor 				param = &ep_ptr->param;
4279e39c5baSBill Taylor 				if (param->pz_handle != NULL) {
4289e39c5baSBill Taylor 					dapl_os_atomic_dec(&((DAPL_PZ *)param->
4299e39c5baSBill Taylor 					    pz_handle)->pz_ref_count);
4309e39c5baSBill Taylor 				}
4319e39c5baSBill Taylor 				if (param->recv_evd_handle != NULL) {
4329e39c5baSBill Taylor 					dapl_os_atomic_dec(&((DAPL_EVD *)param->
4339e39c5baSBill Taylor 					    recv_evd_handle)->evd_ref_count);
4349e39c5baSBill Taylor 				}
4359e39c5baSBill Taylor 				if (param->request_evd_handle) {
4369e39c5baSBill Taylor 					dapl_os_atomic_dec(&((DAPL_EVD *)param->
4379e39c5baSBill Taylor 					    request_evd_handle)->evd_ref_count);
4389e39c5baSBill Taylor 				}
4399e39c5baSBill Taylor 				if (param->connect_evd_handle != NULL) {
4409e39c5baSBill Taylor 					dapl_os_atomic_dec(&((DAPL_EVD *)param->
4419e39c5baSBill Taylor 					    connect_evd_handle)->evd_ref_count);
4429e39c5baSBill Taylor 				}
4439e39c5baSBill Taylor 
4449e39c5baSBill Taylor 				/* ...and free the resource */
4459e39c5baSBill Taylor 				dapl_ia_unlink_ep(ia_ptr, ep_ptr);
4469e39c5baSBill Taylor 				dapl_ep_dealloc(ep_ptr);
4479e39c5baSBill Taylor 			}
4489e39c5baSBill Taylor 
4499e39c5baSBill Taylor 			while (!dapl_llist_is_empty(&ia_ptr->lmr_list_head)) {
4509e39c5baSBill Taylor 				lmr_ptr = (DAPL_LMR *) dapl_llist_peek_head(
4519e39c5baSBill Taylor 				    &ia_ptr->lmr_list_head);
4529e39c5baSBill Taylor 
4539e39c5baSBill Taylor 				(void) dapls_hash_remove(lmr_ptr->header.
4549e39c5baSBill Taylor 				    owner_ia->hca_ptr->lmr_hash_table,
4559e39c5baSBill Taylor 				    lmr_ptr->param.lmr_context, NULL);
4569e39c5baSBill Taylor 
4579e39c5baSBill Taylor 				pz_ptr = (DAPL_PZ *) lmr_ptr->param.pz_handle;
4589e39c5baSBill Taylor 				dapl_os_atomic_dec(&pz_ptr->pz_ref_count);
4599e39c5baSBill Taylor 				dapl_ia_unlink_lmr(lmr_ptr->header.owner_ia,
4609e39c5baSBill Taylor 				    lmr_ptr);
4619e39c5baSBill Taylor 				dapl_lmr_dealloc(lmr_ptr);
4629e39c5baSBill Taylor 			}
4639e39c5baSBill Taylor 
4649e39c5baSBill Taylor 			while (!dapl_llist_is_empty(&ia_ptr->psp_list_head)) {
4659e39c5baSBill Taylor 				sp_ptr = (DAPL_SP *) dapl_llist_peek_head(
4669e39c5baSBill Taylor 				    &ia_ptr->psp_list_head);
4679e39c5baSBill Taylor 				while (!dapl_llist_is_empty(&sp_ptr->
4689e39c5baSBill Taylor 				    cr_list_head)) {
4699e39c5baSBill Taylor 					cr_ptr = (DAPL_CR *)
4709e39c5baSBill Taylor 					    dapl_llist_peek_head(
4719e39c5baSBill Taylor 					    &sp_ptr->cr_list_head);
4729e39c5baSBill Taylor 					dapl_sp_remove_cr(sp_ptr, cr_ptr);
4739e39c5baSBill Taylor 					dapls_cr_free(cr_ptr);
4749e39c5baSBill Taylor 				}
4759e39c5baSBill Taylor 
4769e39c5baSBill Taylor 				dapls_ia_unlink_sp(ia_ptr, sp_ptr);
4779e39c5baSBill Taylor 				dapl_os_atomic_dec(&((DAPL_EVD *)sp_ptr->
4789e39c5baSBill Taylor 				    evd_handle)->evd_ref_count);
4799e39c5baSBill Taylor 				dapls_sp_free_sp(sp_ptr);
4809e39c5baSBill Taylor 			}
4819e39c5baSBill Taylor 
4829e39c5baSBill Taylor 			while (!dapl_llist_is_empty(&ia_ptr->pz_list_head)) {
4839e39c5baSBill Taylor 				pz_ptr = (DAPL_PZ *)
4849e39c5baSBill Taylor 				    dapl_llist_peek_head(&ia_ptr->pz_list_head);
4859e39c5baSBill Taylor 				dapl_ia_unlink_pz(pz_ptr->header.owner_ia,
4869e39c5baSBill Taylor 				    pz_ptr);
4879e39c5baSBill Taylor 				dapl_pz_dealloc(pz_ptr);
4889e39c5baSBill Taylor 			}
4899e39c5baSBill Taylor 
4909e39c5baSBill Taylor 			while (!dapl_llist_is_empty(&ia_ptr->evd_list_head)) {
4919e39c5baSBill Taylor 				evd_ptr = (DAPL_EVD *) dapl_llist_peek_head(
4929e39c5baSBill Taylor 				    &ia_ptr->evd_list_head);
4939e39c5baSBill Taylor 				dapl_ia_unlink_evd(evd_ptr->header.owner_ia,
4949e39c5baSBill Taylor 				    evd_ptr);
4959e39c5baSBill Taylor 				/*
4969e39c5baSBill Taylor 				 * reset the cq_handle to avoid having it
4979e39c5baSBill Taylor 				 * removed
4989e39c5baSBill Taylor 				 */
4999e39c5baSBill Taylor 				evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;
5009e39c5baSBill Taylor 				(void) dapls_evd_dealloc(evd_ptr);
5019e39c5baSBill Taylor 			}
5029e39c5baSBill Taylor 
5039e39c5baSBill Taylor 			dapl_hca_unlink_ia(ia_ptr->hca_ptr, ia_ptr);
5049e39c5baSBill Taylor 			/*
5059e39c5baSBill Taylor 			 * asycn error evd was taken care of above, reset the
5069e39c5baSBill Taylor 			 * pointer
5079e39c5baSBill Taylor 			 */
5089e39c5baSBill Taylor 			ia_ptr->async_error_evd = NULL;
5099e39c5baSBill Taylor 			dapls_ia_free(ia_ptr);
5109e39c5baSBill Taylor 		}	/* end while( ia_ptr != NULL ) */
5119e39c5baSBill Taylor 
5129e39c5baSBill Taylor 
5139e39c5baSBill Taylor 		dapl_os_free(cur_node, sizeof (DAPL_PROVIDER_LIST_NODE));
5149e39c5baSBill Taylor 	} /* end while (NULL != g_dapl_provider_list.head) */
5159e39c5baSBill Taylor }
5169e39c5baSBill Taylor 
5179e39c5baSBill Taylor 
5189e39c5baSBill Taylor /*
5199e39c5baSBill Taylor  * Local variables:
5209e39c5baSBill Taylor  *  c-indent-level: 4
5219e39c5baSBill Taylor  *  c-basic-offset: 4
5229e39c5baSBill Taylor  *  tab-width: 8
5239e39c5baSBill Taylor  * End:
5249e39c5baSBill Taylor  */
525