xref: /titanic_50/usr/src/cmd/cmd-inet/lib/nwamd/objects.c (revision 6ba597c56d749c61b4f783157f63196d7b2445f0)
1*6ba597c5SAnurag S. Maskey /*
2*6ba597c5SAnurag S. Maskey  * CDDL HEADER START
3*6ba597c5SAnurag S. Maskey  *
4*6ba597c5SAnurag S. Maskey  * The contents of this file are subject to the terms of the
5*6ba597c5SAnurag S. Maskey  * Common Development and Distribution License (the "License").
6*6ba597c5SAnurag S. Maskey  * You may not use this file except in compliance with the License.
7*6ba597c5SAnurag S. Maskey  *
8*6ba597c5SAnurag S. Maskey  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6ba597c5SAnurag S. Maskey  * or http://www.opensolaris.org/os/licensing.
10*6ba597c5SAnurag S. Maskey  * See the License for the specific language governing permissions
11*6ba597c5SAnurag S. Maskey  * and limitations under the License.
12*6ba597c5SAnurag S. Maskey  *
13*6ba597c5SAnurag S. Maskey  * When distributing Covered Code, include this CDDL HEADER in each
14*6ba597c5SAnurag S. Maskey  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6ba597c5SAnurag S. Maskey  * If applicable, add the following below this CDDL HEADER, with the
16*6ba597c5SAnurag S. Maskey  * fields enclosed by brackets "[]" replaced with your own identifying
17*6ba597c5SAnurag S. Maskey  * information: Portions Copyright [yyyy] [name of copyright owner]
18*6ba597c5SAnurag S. Maskey  *
19*6ba597c5SAnurag S. Maskey  * CDDL HEADER END
20*6ba597c5SAnurag S. Maskey  */
21*6ba597c5SAnurag S. Maskey 
22*6ba597c5SAnurag S. Maskey /*
23*6ba597c5SAnurag S. Maskey  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*6ba597c5SAnurag S. Maskey  * Use is subject to license terms.
25*6ba597c5SAnurag S. Maskey  */
26*6ba597c5SAnurag S. Maskey 
27*6ba597c5SAnurag S. Maskey #include <assert.h>
28*6ba597c5SAnurag S. Maskey #include <stdlib.h>
29*6ba597c5SAnurag S. Maskey #include <string.h>
30*6ba597c5SAnurag S. Maskey #include <pthread.h>
31*6ba597c5SAnurag S. Maskey #include <signal.h>
32*6ba597c5SAnurag S. Maskey #include <errno.h>
33*6ba597c5SAnurag S. Maskey #include <syslog.h>
34*6ba597c5SAnurag S. Maskey #include <libuutil.h>
35*6ba597c5SAnurag S. Maskey #include <errno.h>
36*6ba597c5SAnurag S. Maskey 
37*6ba597c5SAnurag S. Maskey #include "events.h"
38*6ba597c5SAnurag S. Maskey #include "objects.h"
39*6ba597c5SAnurag S. Maskey #include "util.h"
40*6ba597c5SAnurag S. Maskey 
41*6ba597c5SAnurag S. Maskey /*
42*6ba597c5SAnurag S. Maskey  * objects.c - contains routines which manipulate object lists of NCUs,
43*6ba597c5SAnurag S. Maskey  * locations, ENMs and known WLANs.
44*6ba597c5SAnurag S. Maskey  */
45*6ba597c5SAnurag S. Maskey 
46*6ba597c5SAnurag S. Maskey typedef struct nwamd_object_list {
47*6ba597c5SAnurag S. Maskey 	nwam_object_type_t object_type;
48*6ba597c5SAnurag S. Maskey 	uu_list_t *object_list;
49*6ba597c5SAnurag S. Maskey 	nwamd_event_method_t *object_event_methods;
50*6ba597c5SAnurag S. Maskey 	pthread_rwlock_t object_list_lock;
51*6ba597c5SAnurag S. Maskey } nwamd_object_list_t;
52*6ba597c5SAnurag S. Maskey 
53*6ba597c5SAnurag S. Maskey nwamd_event_method_t enm_event_methods[] =
54*6ba597c5SAnurag S. Maskey {
55*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_INIT, nwamd_enm_handle_init_event },
56*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_FINI, nwamd_enm_handle_fini_event },
57*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_ACTION, nwamd_enm_handle_action_event },
58*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_STATE, nwamd_enm_handle_state_event },
59*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_NOOP, NULL }
60*6ba597c5SAnurag S. Maskey };
61*6ba597c5SAnurag S. Maskey 
62*6ba597c5SAnurag S. Maskey nwamd_event_method_t loc_event_methods[] =
63*6ba597c5SAnurag S. Maskey {
64*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_INIT, nwamd_loc_handle_init_event },
65*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_FINI, nwamd_loc_handle_fini_event },
66*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_ACTION, nwamd_loc_handle_action_event },
67*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_STATE, nwamd_loc_handle_state_event },
68*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_NOOP, NULL }
69*6ba597c5SAnurag S. Maskey };
70*6ba597c5SAnurag S. Maskey 
71*6ba597c5SAnurag S. Maskey nwamd_event_method_t ncu_event_methods[] =
72*6ba597c5SAnurag S. Maskey {
73*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_IF_STATE, nwamd_ncu_handle_if_state_event },
74*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_IF_ACTION, nwamd_ncu_handle_if_action_event },
75*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_LINK_STATE, nwamd_ncu_handle_link_state_event },
76*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_LINK_ACTION, nwamd_ncu_handle_link_action_event },
77*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_INIT, nwamd_ncu_handle_init_event },
78*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_FINI, nwamd_ncu_handle_fini_event },
79*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_ACTION, nwamd_ncu_handle_action_event },
80*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_STATE, nwamd_ncu_handle_state_event },
81*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_PERIODIC_SCAN, nwamd_ncu_handle_periodic_scan_event },
82*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_NOOP, NULL }
83*6ba597c5SAnurag S. Maskey };
84*6ba597c5SAnurag S. Maskey 
85*6ba597c5SAnurag S. Maskey nwamd_event_method_t ncp_event_methods[] =
86*6ba597c5SAnurag S. Maskey {
87*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_ACTION, nwamd_ncp_handle_action_event },
88*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_STATE, nwamd_ncp_handle_state_event },
89*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_UPGRADE, nwamd_handle_upgrade },
90*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_NOOP, NULL }
91*6ba597c5SAnurag S. Maskey };
92*6ba597c5SAnurag S. Maskey 
93*6ba597c5SAnurag S. Maskey nwamd_event_method_t known_wlan_event_methods[] =
94*6ba597c5SAnurag S. Maskey {
95*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_INIT, nwamd_known_wlan_handle_init_event },
96*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_FINI, NULL },
97*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_OBJECT_ACTION, nwamd_known_wlan_handle_action_event },
98*6ba597c5SAnurag S. Maskey 	{ NWAM_EVENT_TYPE_NOOP, NULL }
99*6ba597c5SAnurag S. Maskey };
100*6ba597c5SAnurag S. Maskey 
101*6ba597c5SAnurag S. Maskey /* Should be kept in same order as object types */
102*6ba597c5SAnurag S. Maskey nwamd_object_list_t object_lists[] = {
103*6ba597c5SAnurag S. Maskey 	{ NWAM_OBJECT_TYPE_NCP, NULL, ncp_event_methods,
104*6ba597c5SAnurag S. Maskey 	PTHREAD_RWLOCK_INITIALIZER },
105*6ba597c5SAnurag S. Maskey 	{ NWAM_OBJECT_TYPE_NCU, NULL, ncu_event_methods,
106*6ba597c5SAnurag S. Maskey 	PTHREAD_RWLOCK_INITIALIZER },
107*6ba597c5SAnurag S. Maskey 	{ NWAM_OBJECT_TYPE_LOC, NULL, loc_event_methods,
108*6ba597c5SAnurag S. Maskey 	PTHREAD_RWLOCK_INITIALIZER },
109*6ba597c5SAnurag S. Maskey 	{ NWAM_OBJECT_TYPE_ENM, NULL, enm_event_methods,
110*6ba597c5SAnurag S. Maskey 	PTHREAD_RWLOCK_INITIALIZER },
111*6ba597c5SAnurag S. Maskey 	{ NWAM_OBJECT_TYPE_KNOWN_WLAN, NULL, known_wlan_event_methods,
112*6ba597c5SAnurag S. Maskey 	PTHREAD_RWLOCK_INITIALIZER }
113*6ba597c5SAnurag S. Maskey };
114*6ba597c5SAnurag S. Maskey 
115*6ba597c5SAnurag S. Maskey uu_list_pool_t *object_list_pool = NULL;
116*6ba597c5SAnurag S. Maskey 
117*6ba597c5SAnurag S. Maskey /*
118*6ba597c5SAnurag S. Maskey  * Comparison function for objects, passed in as callback to
119*6ba597c5SAnurag S. Maskey  * uu_list_pool_create().
120*6ba597c5SAnurag S. Maskey  */
121*6ba597c5SAnurag S. Maskey /* ARGSUSED */
122*6ba597c5SAnurag S. Maskey static int
nwamd_object_compare(const void * l_arg,const void * r_arg,void * private)123*6ba597c5SAnurag S. Maskey nwamd_object_compare(const void *l_arg, const void *r_arg, void *private)
124*6ba597c5SAnurag S. Maskey {
125*6ba597c5SAnurag S. Maskey 	nwamd_object_t l = (nwamd_object_t)l_arg;
126*6ba597c5SAnurag S. Maskey 	nwamd_object_t r = (nwamd_object_t)r_arg;
127*6ba597c5SAnurag S. Maskey 	int rv;
128*6ba597c5SAnurag S. Maskey 
129*6ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&l->nwamd_object_mutex);
130*6ba597c5SAnurag S. Maskey 	if (l != r)
131*6ba597c5SAnurag S. Maskey 		(void) pthread_mutex_lock(&r->nwamd_object_mutex);
132*6ba597c5SAnurag S. Maskey 
133*6ba597c5SAnurag S. Maskey 	rv = strcmp(l->nwamd_object_name, r->nwamd_object_name);
134*6ba597c5SAnurag S. Maskey 	if (l != r)
135*6ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&r->nwamd_object_mutex);
136*6ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&l->nwamd_object_mutex);
137*6ba597c5SAnurag S. Maskey 
138*6ba597c5SAnurag S. Maskey 	return (rv);
139*6ba597c5SAnurag S. Maskey }
140*6ba597c5SAnurag S. Maskey 
141*6ba597c5SAnurag S. Maskey void
nwamd_object_lists_init(void)142*6ba597c5SAnurag S. Maskey nwamd_object_lists_init(void)
143*6ba597c5SAnurag S. Maskey {
144*6ba597c5SAnurag S. Maskey 	int i;
145*6ba597c5SAnurag S. Maskey 
146*6ba597c5SAnurag S. Maskey 	object_list_pool = uu_list_pool_create("object_list_pool",
147*6ba597c5SAnurag S. Maskey 	    sizeof (struct nwamd_object),
148*6ba597c5SAnurag S. Maskey 	    offsetof(struct nwamd_object, nwamd_object_node),
149*6ba597c5SAnurag S. Maskey 	    nwamd_object_compare, UU_LIST_POOL_DEBUG);
150*6ba597c5SAnurag S. Maskey 	if (object_list_pool == NULL)
151*6ba597c5SAnurag S. Maskey 		pfail("uu_list_pool_create failed with error %d", uu_error());
152*6ba597c5SAnurag S. Maskey 
153*6ba597c5SAnurag S. Maskey 	for (i = 0;
154*6ba597c5SAnurag S. Maskey 	    i < sizeof (object_lists) / sizeof (struct nwamd_object_list);
155*6ba597c5SAnurag S. Maskey 	    i++) {
156*6ba597c5SAnurag S. Maskey 		object_lists[i].object_list = uu_list_create(object_list_pool,
157*6ba597c5SAnurag S. Maskey 		    NULL, 0);
158*6ba597c5SAnurag S. Maskey 		if (object_lists[i].object_list == NULL)
159*6ba597c5SAnurag S. Maskey 			pfail("uu_list_create failed with error %d",
160*6ba597c5SAnurag S. Maskey 			    uu_error());
161*6ba597c5SAnurag S. Maskey 	}
162*6ba597c5SAnurag S. Maskey }
163*6ba597c5SAnurag S. Maskey 
164*6ba597c5SAnurag S. Maskey void
nwamd_object_lists_fini(void)165*6ba597c5SAnurag S. Maskey nwamd_object_lists_fini(void)
166*6ba597c5SAnurag S. Maskey {
167*6ba597c5SAnurag S. Maskey 	int i;
168*6ba597c5SAnurag S. Maskey 	nwamd_object_t object;
169*6ba597c5SAnurag S. Maskey 	void *cookie = NULL;
170*6ba597c5SAnurag S. Maskey 
171*6ba597c5SAnurag S. Maskey 	for (i = 0;
172*6ba597c5SAnurag S. Maskey 	    i < sizeof (object_lists) / sizeof (struct nwamd_object_list);
173*6ba597c5SAnurag S. Maskey 	    i++) {
174*6ba597c5SAnurag S. Maskey 		while ((object = uu_list_teardown(object_lists[i].object_list,
175*6ba597c5SAnurag S. Maskey 		    &cookie)) != NULL) {
176*6ba597c5SAnurag S. Maskey 			free(object);
177*6ba597c5SAnurag S. Maskey 		}
178*6ba597c5SAnurag S. Maskey 		uu_list_destroy(object_lists[i].object_list);
179*6ba597c5SAnurag S. Maskey 	}
180*6ba597c5SAnurag S. Maskey 	if (object_list_pool != NULL)
181*6ba597c5SAnurag S. Maskey 		uu_list_pool_destroy(object_list_pool);
182*6ba597c5SAnurag S. Maskey }
183*6ba597c5SAnurag S. Maskey 
184*6ba597c5SAnurag S. Maskey static nwamd_object_list_t *
nwamd_get_object_list(nwam_object_type_t type)185*6ba597c5SAnurag S. Maskey nwamd_get_object_list(nwam_object_type_t type)
186*6ba597c5SAnurag S. Maskey {
187*6ba597c5SAnurag S. Maskey 	assert(type < sizeof (object_lists) / sizeof (object_lists[0]));
188*6ba597c5SAnurag S. Maskey 	return (&object_lists[type]);
189*6ba597c5SAnurag S. Maskey }
190*6ba597c5SAnurag S. Maskey 
191*6ba597c5SAnurag S. Maskey static int
nwamd_object_list_lock(nwam_object_type_t type)192*6ba597c5SAnurag S. Maskey nwamd_object_list_lock(nwam_object_type_t type)
193*6ba597c5SAnurag S. Maskey {
194*6ba597c5SAnurag S. Maskey 	nwamd_object_list_t *object_list = nwamd_get_object_list(type);
195*6ba597c5SAnurag S. Maskey 
196*6ba597c5SAnurag S. Maskey 	(void) pthread_rwlock_wrlock(&object_list->object_list_lock);
197*6ba597c5SAnurag S. Maskey 	return (0);
198*6ba597c5SAnurag S. Maskey }
199*6ba597c5SAnurag S. Maskey 
200*6ba597c5SAnurag S. Maskey static int
nwamd_object_list_rlock(nwam_object_type_t type)201*6ba597c5SAnurag S. Maskey nwamd_object_list_rlock(nwam_object_type_t type)
202*6ba597c5SAnurag S. Maskey {
203*6ba597c5SAnurag S. Maskey 	nwamd_object_list_t *object_list = nwamd_get_object_list(type);
204*6ba597c5SAnurag S. Maskey 
205*6ba597c5SAnurag S. Maskey 	if (pthread_rwlock_rdlock(&object_list->object_list_lock) == -1) {
206*6ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "cannot get lock for object list: %s",
207*6ba597c5SAnurag S. Maskey 		    strerror(errno));
208*6ba597c5SAnurag S. Maskey 		return (-1);
209*6ba597c5SAnurag S. Maskey 	}
210*6ba597c5SAnurag S. Maskey 	return (0);
211*6ba597c5SAnurag S. Maskey }
212*6ba597c5SAnurag S. Maskey 
213*6ba597c5SAnurag S. Maskey static void
nwamd_object_list_unlock(nwam_object_type_t type)214*6ba597c5SAnurag S. Maskey nwamd_object_list_unlock(nwam_object_type_t type)
215*6ba597c5SAnurag S. Maskey {
216*6ba597c5SAnurag S. Maskey 	nwamd_object_list_t *object_list = nwamd_get_object_list(type);
217*6ba597c5SAnurag S. Maskey 
218*6ba597c5SAnurag S. Maskey 	(void) pthread_rwlock_unlock(&object_list->object_list_lock);
219*6ba597c5SAnurag S. Maskey }
220*6ba597c5SAnurag S. Maskey 
221*6ba597c5SAnurag S. Maskey /*
222*6ba597c5SAnurag S. Maskey  * Initialize object and return it in locked state.
223*6ba597c5SAnurag S. Maskey  */
224*6ba597c5SAnurag S. Maskey nwamd_object_t
nwamd_object_init(nwam_object_type_t type,const char * name,void * handle,void * data)225*6ba597c5SAnurag S. Maskey nwamd_object_init(nwam_object_type_t type, const char *name, void *handle,
226*6ba597c5SAnurag S. Maskey     void *data)
227*6ba597c5SAnurag S. Maskey {
228*6ba597c5SAnurag S. Maskey 	nwamd_object_t object;
229*6ba597c5SAnurag S. Maskey 	struct nwamd_object_list *object_list = nwamd_get_object_list(type);
230*6ba597c5SAnurag S. Maskey 
231*6ba597c5SAnurag S. Maskey 	object = calloc(1, sizeof (struct nwamd_object));
232*6ba597c5SAnurag S. Maskey 	if (object == NULL)
233*6ba597c5SAnurag S. Maskey 		return (NULL);
234*6ba597c5SAnurag S. Maskey 
235*6ba597c5SAnurag S. Maskey 	(void) strlcpy(object->nwamd_object_name, name, NWAM_MAX_NAME_LEN);
236*6ba597c5SAnurag S. Maskey 
237*6ba597c5SAnurag S. Maskey 	/* 1 for the list and 1 for the returned object */
238*6ba597c5SAnurag S. Maskey 	object->nwamd_object_refcount = 2;
239*6ba597c5SAnurag S. Maskey 	object->nwamd_object_handle = handle;
240*6ba597c5SAnurag S. Maskey 	object->nwamd_object_data = data;
241*6ba597c5SAnurag S. Maskey 	object->nwamd_object_type = type;
242*6ba597c5SAnurag S. Maskey 	object->nwamd_object_state = NWAM_STATE_INITIALIZED;
243*6ba597c5SAnurag S. Maskey 	object->nwamd_object_aux_state = NWAM_AUX_STATE_INITIALIZED;
244*6ba597c5SAnurag S. Maskey 
245*6ba597c5SAnurag S. Maskey 	/* Add object to appropriate object list */
246*6ba597c5SAnurag S. Maskey 	if (nwamd_object_list_lock(type) != 0) {
247*6ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "nwamd_object_init: could not lock list to init "
248*6ba597c5SAnurag S. Maskey 		    "object %s", name);
249*6ba597c5SAnurag S. Maskey 		free(object);
250*6ba597c5SAnurag S. Maskey 		return (NULL);
251*6ba597c5SAnurag S. Maskey 	}
252*6ba597c5SAnurag S. Maskey 
253*6ba597c5SAnurag S. Maskey 	if (pthread_mutex_init(&object->nwamd_object_mutex, NULL) == -1) {
254*6ba597c5SAnurag S. Maskey 		nlog(LOG_ERR, "pthread_mutex_init failed: %s",
255*6ba597c5SAnurag S. Maskey 		    strerror(errno));
256*6ba597c5SAnurag S. Maskey 		free(object);
257*6ba597c5SAnurag S. Maskey 		nwamd_object_list_unlock(type);
258*6ba597c5SAnurag S. Maskey 		return (NULL);
259*6ba597c5SAnurag S. Maskey 	}
260*6ba597c5SAnurag S. Maskey 	(void) pthread_mutex_lock(&object->nwamd_object_mutex);
261*6ba597c5SAnurag S. Maskey 
262*6ba597c5SAnurag S. Maskey 	uu_list_node_init(object, &object->nwamd_object_node, object_list_pool);
263*6ba597c5SAnurag S. Maskey 	(void) uu_list_insert_after(object_list->object_list,
264*6ba597c5SAnurag S. Maskey 	    uu_list_last(object_list->object_list), object);
265*6ba597c5SAnurag S. Maskey 
266*6ba597c5SAnurag S. Maskey 	nwamd_object_list_unlock(type);
267*6ba597c5SAnurag S. Maskey 
268*6ba597c5SAnurag S. Maskey 	return (object);
269*6ba597c5SAnurag S. Maskey }
270*6ba597c5SAnurag S. Maskey 
271*6ba597c5SAnurag S. Maskey /*
272*6ba597c5SAnurag S. Maskey  * Find object in object list, returning it holding a lock and with the
273*6ba597c5SAnurag S. Maskey  * reference count incremented.  The opposite function to this is
274*6ba597c5SAnurag S. Maskey  * nwamd_object_release().
275*6ba597c5SAnurag S. Maskey  */
276*6ba597c5SAnurag S. Maskey nwamd_object_t
nwamd_object_find(nwam_object_type_t type,const char * name)277*6ba597c5SAnurag S. Maskey nwamd_object_find(nwam_object_type_t type, const char *name)
278*6ba597c5SAnurag S. Maskey {
279*6ba597c5SAnurag S. Maskey 	nwamd_object_t object;
280*6ba597c5SAnurag S. Maskey 	struct nwamd_object_list *object_list = nwamd_get_object_list(type);
281*6ba597c5SAnurag S. Maskey 
282*6ba597c5SAnurag S. Maskey 	assert(name != NULL);
283*6ba597c5SAnurag S. Maskey 
284*6ba597c5SAnurag S. Maskey 	if (nwamd_object_list_rlock(type) != 0)
285*6ba597c5SAnurag S. Maskey 		return (NULL);
286*6ba597c5SAnurag S. Maskey 
287*6ba597c5SAnurag S. Maskey 	for (object = uu_list_first(object_list->object_list);
288*6ba597c5SAnurag S. Maskey 	    object != NULL;
289*6ba597c5SAnurag S. Maskey 	    object = uu_list_next(object_list->object_list, object)) {
290*6ba597c5SAnurag S. Maskey 		if (strcmp(object->nwamd_object_name, name) == 0)
291*6ba597c5SAnurag S. Maskey 			break;
292*6ba597c5SAnurag S. Maskey 	}
293*6ba597c5SAnurag S. Maskey 	if (object != NULL) {
294*6ba597c5SAnurag S. Maskey 		(void) pthread_mutex_lock(&object->nwamd_object_mutex);
295*6ba597c5SAnurag S. Maskey 		object->nwamd_object_refcount++;
296*6ba597c5SAnurag S. Maskey 	}
297*6ba597c5SAnurag S. Maskey 	nwamd_object_list_unlock(type);
298*6ba597c5SAnurag S. Maskey 
299*6ba597c5SAnurag S. Maskey 	return (object);
300*6ba597c5SAnurag S. Maskey }
301*6ba597c5SAnurag S. Maskey 
302*6ba597c5SAnurag S. Maskey /* Removes object from list, destroy mutex, and free storage. */
303*6ba597c5SAnurag S. Maskey static void
nwamd_object_fini(nwamd_object_t object,nwam_object_type_t objtype)304*6ba597c5SAnurag S. Maskey nwamd_object_fini(nwamd_object_t object, nwam_object_type_t objtype)
305*6ba597c5SAnurag S. Maskey {
306*6ba597c5SAnurag S. Maskey 	nwamd_object_t o;
307*6ba597c5SAnurag S. Maskey 	struct nwamd_object_list *object_list;
308*6ba597c5SAnurag S. Maskey 
309*6ba597c5SAnurag S. Maskey 	assert(object != NULL);
310*6ba597c5SAnurag S. Maskey 
311*6ba597c5SAnurag S. Maskey 	object_list = nwamd_get_object_list(objtype);
312*6ba597c5SAnurag S. Maskey 
313*6ba597c5SAnurag S. Maskey 	for (o = uu_list_first(object_list->object_list);
314*6ba597c5SAnurag S. Maskey 	    o != NULL;
315*6ba597c5SAnurag S. Maskey 	    o = uu_list_next(object_list->object_list, o)) {
316*6ba597c5SAnurag S. Maskey 		if (o == object) {
317*6ba597c5SAnurag S. Maskey 			uu_list_remove(object_list->object_list, object);
318*6ba597c5SAnurag S. Maskey 			(void) pthread_mutex_unlock(
319*6ba597c5SAnurag S. Maskey 			    &object->nwamd_object_mutex);
320*6ba597c5SAnurag S. Maskey 			(void) pthread_mutex_destroy(
321*6ba597c5SAnurag S. Maskey 			    &object->nwamd_object_mutex);
322*6ba597c5SAnurag S. Maskey 			uu_list_node_fini(object, &object->nwamd_object_node,
323*6ba597c5SAnurag S. Maskey 			    object_list_pool);
324*6ba597c5SAnurag S. Maskey 			switch (objtype) {
325*6ba597c5SAnurag S. Maskey 			case NWAM_OBJECT_TYPE_NCU:
326*6ba597c5SAnurag S. Maskey 				nwamd_ncu_free(object->nwamd_object_data);
327*6ba597c5SAnurag S. Maskey 				nwam_ncu_free(object->nwamd_object_handle);
328*6ba597c5SAnurag S. Maskey 				break;
329*6ba597c5SAnurag S. Maskey 			case NWAM_OBJECT_TYPE_LOC:
330*6ba597c5SAnurag S. Maskey 				nwam_loc_free(object->nwamd_object_handle);
331*6ba597c5SAnurag S. Maskey 				break;
332*6ba597c5SAnurag S. Maskey 			case NWAM_OBJECT_TYPE_ENM:
333*6ba597c5SAnurag S. Maskey 				nwam_enm_free(object->nwamd_object_handle);
334*6ba597c5SAnurag S. Maskey 				break;
335*6ba597c5SAnurag S. Maskey 			default:
336*6ba597c5SAnurag S. Maskey 				nlog(LOG_ERR, "nwamd_object_fini: "
337*6ba597c5SAnurag S. Maskey 				    "got unexpected object type %d", objtype);
338*6ba597c5SAnurag S. Maskey 				break;
339*6ba597c5SAnurag S. Maskey 			}
340*6ba597c5SAnurag S. Maskey 			free(object);
341*6ba597c5SAnurag S. Maskey 			break;
342*6ba597c5SAnurag S. Maskey 		}
343*6ba597c5SAnurag S. Maskey 	}
344*6ba597c5SAnurag S. Maskey }
345*6ba597c5SAnurag S. Maskey 
346*6ba597c5SAnurag S. Maskey static void
nwamd_object_decref(nwamd_object_t object,int num)347*6ba597c5SAnurag S. Maskey nwamd_object_decref(nwamd_object_t object, int num)
348*6ba597c5SAnurag S. Maskey {
349*6ba597c5SAnurag S. Maskey 	nwam_object_type_t objtype;
350*6ba597c5SAnurag S. Maskey 
351*6ba597c5SAnurag S. Maskey 	assert(object->nwamd_object_refcount >= num);
352*6ba597c5SAnurag S. Maskey 	object->nwamd_object_refcount -= num;
353*6ba597c5SAnurag S. Maskey 	if (object->nwamd_object_refcount == 0) {
354*6ba597c5SAnurag S. Maskey 		/*
355*6ba597c5SAnurag S. Maskey 		 * We need to maintain the locking hierarchy of owning the
356*6ba597c5SAnurag S. Maskey 		 * list lock before we get the object lock when we are
357*6ba597c5SAnurag S. Maskey 		 * destroying the object.  If we merely release and then
358*6ba597c5SAnurag S. Maskey 		 * reacquire in the right order we might not find the right
359*6ba597c5SAnurag S. Maskey 		 * object.  Instead we bump the ref count so that it can't
360*6ba597c5SAnurag S. Maskey 		 * be destroyed, we drop the object lock, we acquire the
361*6ba597c5SAnurag S. Maskey 		 * list lock, we acquire the object lock, decrement the ref
362*6ba597c5SAnurag S. Maskey 		 * count, check to make sure we are really destroying it and
363*6ba597c5SAnurag S. Maskey 		 * somebody else hasn't gotten it, and then, if its unref'd,
364*6ba597c5SAnurag S. Maskey 		 * destroying it.
365*6ba597c5SAnurag S. Maskey 		 */
366*6ba597c5SAnurag S. Maskey 		object->nwamd_object_refcount++;
367*6ba597c5SAnurag S. Maskey 		objtype = object->nwamd_object_type;
368*6ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&object->nwamd_object_mutex);
369*6ba597c5SAnurag S. Maskey 		(void) nwamd_object_list_lock(objtype);
370*6ba597c5SAnurag S. Maskey 		(void) pthread_mutex_lock(&object->nwamd_object_mutex);
371*6ba597c5SAnurag S. Maskey 		if (--object->nwamd_object_refcount != 0)
372*6ba597c5SAnurag S. Maskey 			(void) pthread_mutex_unlock(
373*6ba597c5SAnurag S. Maskey 			    &object->nwamd_object_mutex);
374*6ba597c5SAnurag S. Maskey 		else
375*6ba597c5SAnurag S. Maskey 			nwamd_object_fini(object, objtype);
376*6ba597c5SAnurag S. Maskey 		nwamd_object_list_unlock(objtype);
377*6ba597c5SAnurag S. Maskey 	} else {
378*6ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&object->nwamd_object_mutex);
379*6ba597c5SAnurag S. Maskey 	}
380*6ba597c5SAnurag S. Maskey }
381*6ba597c5SAnurag S. Maskey 
382*6ba597c5SAnurag S. Maskey /*
383*6ba597c5SAnurag S. Maskey  * Drop mutex without decreasing reference count.  Used where we wish to
384*6ba597c5SAnurag S. Maskey  * let go of an object but ensure it will not go away.
385*6ba597c5SAnurag S. Maskey  */
386*6ba597c5SAnurag S. Maskey void
nwamd_object_release_and_preserve(nwamd_object_t object)387*6ba597c5SAnurag S. Maskey nwamd_object_release_and_preserve(nwamd_object_t object)
388*6ba597c5SAnurag S. Maskey {
389*6ba597c5SAnurag S. Maskey 	(void) pthread_mutex_unlock(&object->nwamd_object_mutex);
390*6ba597c5SAnurag S. Maskey }
391*6ba597c5SAnurag S. Maskey 
392*6ba597c5SAnurag S. Maskey void
nwamd_object_release(nwamd_object_t object)393*6ba597c5SAnurag S. Maskey nwamd_object_release(nwamd_object_t object)
394*6ba597c5SAnurag S. Maskey {
395*6ba597c5SAnurag S. Maskey 	nwamd_object_decref(object, 1);
396*6ba597c5SAnurag S. Maskey }
397*6ba597c5SAnurag S. Maskey 
398*6ba597c5SAnurag S. Maskey void
nwamd_object_release_and_destroy(nwamd_object_t object)399*6ba597c5SAnurag S. Maskey nwamd_object_release_and_destroy(nwamd_object_t object)
400*6ba597c5SAnurag S. Maskey {
401*6ba597c5SAnurag S. Maskey 	nwamd_object_decref(object, 2);
402*6ba597c5SAnurag S. Maskey }
403*6ba597c5SAnurag S. Maskey 
404*6ba597c5SAnurag S. Maskey void
nwamd_object_release_and_destroy_after_preserve(nwamd_object_t object)405*6ba597c5SAnurag S. Maskey nwamd_object_release_and_destroy_after_preserve(nwamd_object_t object)
406*6ba597c5SAnurag S. Maskey {
407*6ba597c5SAnurag S. Maskey 	nwamd_object_decref(object, 3);
408*6ba597c5SAnurag S. Maskey }
409*6ba597c5SAnurag S. Maskey 
410*6ba597c5SAnurag S. Maskey void
nwamd_object_release_after_preserve(nwamd_object_t object)411*6ba597c5SAnurag S. Maskey nwamd_object_release_after_preserve(nwamd_object_t object)
412*6ba597c5SAnurag S. Maskey {
413*6ba597c5SAnurag S. Maskey 	nwamd_object_decref(object, 2);
414*6ba597c5SAnurag S. Maskey }
415*6ba597c5SAnurag S. Maskey 
416*6ba597c5SAnurag S. Maskey void
nwamd_object_set_state_timed(nwam_object_type_t type,const char * name,nwam_state_t state,nwam_aux_state_t aux_state,uint32_t when)417*6ba597c5SAnurag S. Maskey nwamd_object_set_state_timed(nwam_object_type_t type, const char *name,
418*6ba597c5SAnurag S. Maskey     nwam_state_t state, nwam_aux_state_t aux_state, uint32_t when)
419*6ba597c5SAnurag S. Maskey {
420*6ba597c5SAnurag S. Maskey 	nwamd_event_t event = nwamd_event_init_object_state(type, name,
421*6ba597c5SAnurag S. Maskey 	    state, aux_state);
422*6ba597c5SAnurag S. Maskey 
423*6ba597c5SAnurag S. Maskey 	nlog(LOG_INFO, "nwamd_object_set_state: state event (%s, %s) for %s",
424*6ba597c5SAnurag S. Maskey 	    nwam_state_to_string(state),
425*6ba597c5SAnurag S. Maskey 	    nwam_aux_state_to_string(aux_state), name);
426*6ba597c5SAnurag S. Maskey 	if (event != NULL)
427*6ba597c5SAnurag S. Maskey 		nwamd_event_enqueue_timed(event, when);
428*6ba597c5SAnurag S. Maskey }
429*6ba597c5SAnurag S. Maskey 
430*6ba597c5SAnurag S. Maskey void
nwamd_object_set_state(nwam_object_type_t type,const char * name,nwam_state_t state,nwam_aux_state_t aux_state)431*6ba597c5SAnurag S. Maskey nwamd_object_set_state(nwam_object_type_t type, const char *name,
432*6ba597c5SAnurag S. Maskey     nwam_state_t state, nwam_aux_state_t aux_state)
433*6ba597c5SAnurag S. Maskey {
434*6ba597c5SAnurag S. Maskey 	nwamd_object_set_state_timed(type, name, state, aux_state, 0);
435*6ba597c5SAnurag S. Maskey }
436*6ba597c5SAnurag S. Maskey 
437*6ba597c5SAnurag S. Maskey nwamd_event_method_t *
nwamd_object_event_methods(nwam_object_type_t type)438*6ba597c5SAnurag S. Maskey nwamd_object_event_methods(nwam_object_type_t type)
439*6ba597c5SAnurag S. Maskey {
440*6ba597c5SAnurag S. Maskey 	struct nwamd_object_list *object_list = nwamd_get_object_list(type);
441*6ba597c5SAnurag S. Maskey 
442*6ba597c5SAnurag S. Maskey 	return (object_list->object_event_methods);
443*6ba597c5SAnurag S. Maskey }
444*6ba597c5SAnurag S. Maskey 
445*6ba597c5SAnurag S. Maskey /*
446*6ba597c5SAnurag S. Maskey  * Walk all objects of specified type calling callback function cb.
447*6ba597c5SAnurag S. Maskey  * Object is locked for duration of callback.
448*6ba597c5SAnurag S. Maskey  */
449*6ba597c5SAnurag S. Maskey int
nwamd_walk_objects(nwam_object_type_t type,int (* cb)(nwamd_object_t,void *),void * data)450*6ba597c5SAnurag S. Maskey nwamd_walk_objects(nwam_object_type_t type, int (*cb)(nwamd_object_t, void *),
451*6ba597c5SAnurag S. Maskey     void *data)
452*6ba597c5SAnurag S. Maskey {
453*6ba597c5SAnurag S. Maskey 	nwamd_object_t object;
454*6ba597c5SAnurag S. Maskey 	struct nwamd_object_list *object_list = nwamd_get_object_list(type);
455*6ba597c5SAnurag S. Maskey 	int ret = 0;
456*6ba597c5SAnurag S. Maskey 
457*6ba597c5SAnurag S. Maskey 	if (nwamd_object_list_rlock(type) != 0)
458*6ba597c5SAnurag S. Maskey 		return (-1);
459*6ba597c5SAnurag S. Maskey 
460*6ba597c5SAnurag S. Maskey 	for (object = uu_list_first(object_list->object_list);
461*6ba597c5SAnurag S. Maskey 	    object != NULL;
462*6ba597c5SAnurag S. Maskey 	    object = uu_list_next(object_list->object_list, object)) {
463*6ba597c5SAnurag S. Maskey 		(void) pthread_mutex_lock(&object->nwamd_object_mutex);
464*6ba597c5SAnurag S. Maskey 		ret = cb(object, data);
465*6ba597c5SAnurag S. Maskey 		(void) pthread_mutex_unlock(&object->nwamd_object_mutex);
466*6ba597c5SAnurag S. Maskey 		if (ret != 0) {
467*6ba597c5SAnurag S. Maskey 			nwamd_object_list_unlock(type);
468*6ba597c5SAnurag S. Maskey 			return (ret);
469*6ba597c5SAnurag S. Maskey 		}
470*6ba597c5SAnurag S. Maskey 	}
471*6ba597c5SAnurag S. Maskey 	nwamd_object_list_unlock(type);
472*6ba597c5SAnurag S. Maskey 
473*6ba597c5SAnurag S. Maskey 	return (0);
474*6ba597c5SAnurag S. Maskey }
475