4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
42 * objects.c - contains routines which manipulate object lists of NCUs,
43 * locations, ENMs and known WLANs.
46 typedef struct nwamd_object_list
{
47 nwam_object_type_t object_type
;
48 uu_list_t
*object_list
;
49 nwamd_event_method_t
*object_event_methods
;
50 pthread_rwlock_t object_list_lock
;
51 } nwamd_object_list_t
;
53 nwamd_event_method_t enm_event_methods
[] =
55 { NWAM_EVENT_TYPE_OBJECT_INIT
, nwamd_enm_handle_init_event
},
56 { NWAM_EVENT_TYPE_OBJECT_FINI
, nwamd_enm_handle_fini_event
},
57 { NWAM_EVENT_TYPE_OBJECT_ACTION
, nwamd_enm_handle_action_event
},
58 { NWAM_EVENT_TYPE_OBJECT_STATE
, nwamd_enm_handle_state_event
},
59 { NWAM_EVENT_TYPE_NOOP
, NULL
}
62 nwamd_event_method_t loc_event_methods
[] =
64 { NWAM_EVENT_TYPE_OBJECT_INIT
, nwamd_loc_handle_init_event
},
65 { NWAM_EVENT_TYPE_OBJECT_FINI
, nwamd_loc_handle_fini_event
},
66 { NWAM_EVENT_TYPE_OBJECT_ACTION
, nwamd_loc_handle_action_event
},
67 { NWAM_EVENT_TYPE_OBJECT_STATE
, nwamd_loc_handle_state_event
},
68 { NWAM_EVENT_TYPE_NOOP
, NULL
}
71 nwamd_event_method_t ncu_event_methods
[] =
73 { NWAM_EVENT_TYPE_IF_STATE
, nwamd_ncu_handle_if_state_event
},
74 { NWAM_EVENT_TYPE_IF_ACTION
, nwamd_ncu_handle_if_action_event
},
75 { NWAM_EVENT_TYPE_LINK_STATE
, nwamd_ncu_handle_link_state_event
},
76 { NWAM_EVENT_TYPE_LINK_ACTION
, nwamd_ncu_handle_link_action_event
},
77 { NWAM_EVENT_TYPE_OBJECT_INIT
, nwamd_ncu_handle_init_event
},
78 { NWAM_EVENT_TYPE_OBJECT_FINI
, nwamd_ncu_handle_fini_event
},
79 { NWAM_EVENT_TYPE_OBJECT_ACTION
, nwamd_ncu_handle_action_event
},
80 { NWAM_EVENT_TYPE_OBJECT_STATE
, nwamd_ncu_handle_state_event
},
81 { NWAM_EVENT_TYPE_PERIODIC_SCAN
, nwamd_ncu_handle_periodic_scan_event
},
82 { NWAM_EVENT_TYPE_NOOP
, NULL
}
85 nwamd_event_method_t ncp_event_methods
[] =
87 { NWAM_EVENT_TYPE_OBJECT_ACTION
, nwamd_ncp_handle_action_event
},
88 { NWAM_EVENT_TYPE_OBJECT_STATE
, nwamd_ncp_handle_state_event
},
89 { NWAM_EVENT_TYPE_UPGRADE
, nwamd_handle_upgrade
},
90 { NWAM_EVENT_TYPE_NOOP
, NULL
}
93 nwamd_event_method_t known_wlan_event_methods
[] =
95 { NWAM_EVENT_TYPE_OBJECT_INIT
, nwamd_known_wlan_handle_init_event
},
96 { NWAM_EVENT_TYPE_OBJECT_FINI
, NULL
},
97 { NWAM_EVENT_TYPE_OBJECT_ACTION
, nwamd_known_wlan_handle_action_event
},
98 { NWAM_EVENT_TYPE_NOOP
, NULL
}
101 /* Should be kept in same order as object types */
102 nwamd_object_list_t object_lists
[] = {
103 { NWAM_OBJECT_TYPE_NCP
, NULL
, ncp_event_methods
,
104 PTHREAD_RWLOCK_INITIALIZER
},
105 { NWAM_OBJECT_TYPE_NCU
, NULL
, ncu_event_methods
,
106 PTHREAD_RWLOCK_INITIALIZER
},
107 { NWAM_OBJECT_TYPE_LOC
, NULL
, loc_event_methods
,
108 PTHREAD_RWLOCK_INITIALIZER
},
109 { NWAM_OBJECT_TYPE_ENM
, NULL
, enm_event_methods
,
110 PTHREAD_RWLOCK_INITIALIZER
},
111 { NWAM_OBJECT_TYPE_KNOWN_WLAN
, NULL
, known_wlan_event_methods
,
112 PTHREAD_RWLOCK_INITIALIZER
}
115 uu_list_pool_t
*object_list_pool
= NULL
;
118 * Comparison function for objects, passed in as callback to
119 * uu_list_pool_create().
123 nwamd_object_compare(const void *l_arg
, const void *r_arg
, void *private)
125 nwamd_object_t l
= (nwamd_object_t
)l_arg
;
126 nwamd_object_t r
= (nwamd_object_t
)r_arg
;
129 (void) pthread_mutex_lock(&l
->nwamd_object_mutex
);
131 (void) pthread_mutex_lock(&r
->nwamd_object_mutex
);
133 rv
= strcmp(l
->nwamd_object_name
, r
->nwamd_object_name
);
135 (void) pthread_mutex_unlock(&r
->nwamd_object_mutex
);
136 (void) pthread_mutex_unlock(&l
->nwamd_object_mutex
);
142 nwamd_object_lists_init(void)
146 object_list_pool
= uu_list_pool_create("object_list_pool",
147 sizeof (struct nwamd_object
),
148 offsetof(struct nwamd_object
, nwamd_object_node
),
149 nwamd_object_compare
, UU_LIST_POOL_DEBUG
);
150 if (object_list_pool
== NULL
)
151 pfail("uu_list_pool_create failed with error %d", uu_error());
154 i
< sizeof (object_lists
) / sizeof (struct nwamd_object_list
);
156 object_lists
[i
].object_list
= uu_list_create(object_list_pool
,
158 if (object_lists
[i
].object_list
== NULL
)
159 pfail("uu_list_create failed with error %d",
165 nwamd_object_lists_fini(void)
168 nwamd_object_t object
;
172 i
< sizeof (object_lists
) / sizeof (struct nwamd_object_list
);
174 while ((object
= uu_list_teardown(object_lists
[i
].object_list
,
178 uu_list_destroy(object_lists
[i
].object_list
);
180 if (object_list_pool
!= NULL
)
181 uu_list_pool_destroy(object_list_pool
);
184 static nwamd_object_list_t
*
185 nwamd_get_object_list(nwam_object_type_t type
)
187 assert(type
< sizeof (object_lists
) / sizeof (object_lists
[0]));
188 return (&object_lists
[type
]);
192 nwamd_object_list_lock(nwam_object_type_t type
)
194 nwamd_object_list_t
*object_list
= nwamd_get_object_list(type
);
196 (void) pthread_rwlock_wrlock(&object_list
->object_list_lock
);
201 nwamd_object_list_rlock(nwam_object_type_t type
)
203 nwamd_object_list_t
*object_list
= nwamd_get_object_list(type
);
205 if (pthread_rwlock_rdlock(&object_list
->object_list_lock
) == -1) {
206 nlog(LOG_ERR
, "cannot get lock for object list: %s",
214 nwamd_object_list_unlock(nwam_object_type_t type
)
216 nwamd_object_list_t
*object_list
= nwamd_get_object_list(type
);
218 (void) pthread_rwlock_unlock(&object_list
->object_list_lock
);
222 * Initialize object and return it in locked state.
225 nwamd_object_init(nwam_object_type_t type
, const char *name
, void *handle
,
228 nwamd_object_t object
;
229 struct nwamd_object_list
*object_list
= nwamd_get_object_list(type
);
231 object
= calloc(1, sizeof (struct nwamd_object
));
235 (void) strlcpy(object
->nwamd_object_name
, name
, NWAM_MAX_NAME_LEN
);
237 /* 1 for the list and 1 for the returned object */
238 object
->nwamd_object_refcount
= 2;
239 object
->nwamd_object_handle
= handle
;
240 object
->nwamd_object_data
= data
;
241 object
->nwamd_object_type
= type
;
242 object
->nwamd_object_state
= NWAM_STATE_INITIALIZED
;
243 object
->nwamd_object_aux_state
= NWAM_AUX_STATE_INITIALIZED
;
245 /* Add object to appropriate object list */
246 if (nwamd_object_list_lock(type
) != 0) {
247 nlog(LOG_ERR
, "nwamd_object_init: could not lock list to init "
253 if (pthread_mutex_init(&object
->nwamd_object_mutex
, NULL
) == -1) {
254 nlog(LOG_ERR
, "pthread_mutex_init failed: %s",
257 nwamd_object_list_unlock(type
);
260 (void) pthread_mutex_lock(&object
->nwamd_object_mutex
);
262 uu_list_node_init(object
, &object
->nwamd_object_node
, object_list_pool
);
263 (void) uu_list_insert_after(object_list
->object_list
,
264 uu_list_last(object_list
->object_list
), object
);
266 nwamd_object_list_unlock(type
);
272 * Find object in object list, returning it holding a lock and with the
273 * reference count incremented. The opposite function to this is
274 * nwamd_object_release().
277 nwamd_object_find(nwam_object_type_t type
, const char *name
)
279 nwamd_object_t object
;
280 struct nwamd_object_list
*object_list
= nwamd_get_object_list(type
);
282 assert(name
!= NULL
);
284 if (nwamd_object_list_rlock(type
) != 0)
287 for (object
= uu_list_first(object_list
->object_list
);
289 object
= uu_list_next(object_list
->object_list
, object
)) {
290 if (strcmp(object
->nwamd_object_name
, name
) == 0)
293 if (object
!= NULL
) {
294 (void) pthread_mutex_lock(&object
->nwamd_object_mutex
);
295 object
->nwamd_object_refcount
++;
297 nwamd_object_list_unlock(type
);
302 /* Removes object from list, destroy mutex, and free storage. */
304 nwamd_object_fini(nwamd_object_t object
, nwam_object_type_t objtype
)
307 struct nwamd_object_list
*object_list
;
309 assert(object
!= NULL
);
311 object_list
= nwamd_get_object_list(objtype
);
313 for (o
= uu_list_first(object_list
->object_list
);
315 o
= uu_list_next(object_list
->object_list
, o
)) {
317 uu_list_remove(object_list
->object_list
, object
);
318 (void) pthread_mutex_unlock(
319 &object
->nwamd_object_mutex
);
320 (void) pthread_mutex_destroy(
321 &object
->nwamd_object_mutex
);
322 uu_list_node_fini(object
, &object
->nwamd_object_node
,
325 case NWAM_OBJECT_TYPE_NCU
:
326 nwamd_ncu_free(object
->nwamd_object_data
);
327 nwam_ncu_free(object
->nwamd_object_handle
);
329 case NWAM_OBJECT_TYPE_LOC
:
330 nwam_loc_free(object
->nwamd_object_handle
);
332 case NWAM_OBJECT_TYPE_ENM
:
333 nwam_enm_free(object
->nwamd_object_handle
);
336 nlog(LOG_ERR
, "nwamd_object_fini: "
337 "got unexpected object type %d", objtype
);
347 nwamd_object_decref(nwamd_object_t object
, int num
)
349 nwam_object_type_t objtype
;
351 assert(object
->nwamd_object_refcount
>= num
);
352 object
->nwamd_object_refcount
-= num
;
353 if (object
->nwamd_object_refcount
== 0) {
355 * We need to maintain the locking hierarchy of owning the
356 * list lock before we get the object lock when we are
357 * destroying the object. If we merely release and then
358 * reacquire in the right order we might not find the right
359 * object. Instead we bump the ref count so that it can't
360 * be destroyed, we drop the object lock, we acquire the
361 * list lock, we acquire the object lock, decrement the ref
362 * count, check to make sure we are really destroying it and
363 * somebody else hasn't gotten it, and then, if its unref'd,
366 object
->nwamd_object_refcount
++;
367 objtype
= object
->nwamd_object_type
;
368 (void) pthread_mutex_unlock(&object
->nwamd_object_mutex
);
369 (void) nwamd_object_list_lock(objtype
);
370 (void) pthread_mutex_lock(&object
->nwamd_object_mutex
);
371 if (--object
->nwamd_object_refcount
!= 0)
372 (void) pthread_mutex_unlock(
373 &object
->nwamd_object_mutex
);
375 nwamd_object_fini(object
, objtype
);
376 nwamd_object_list_unlock(objtype
);
378 (void) pthread_mutex_unlock(&object
->nwamd_object_mutex
);
383 * Drop mutex without decreasing reference count. Used where we wish to
384 * let go of an object but ensure it will not go away.
387 nwamd_object_release_and_preserve(nwamd_object_t object
)
389 (void) pthread_mutex_unlock(&object
->nwamd_object_mutex
);
393 nwamd_object_release(nwamd_object_t object
)
395 nwamd_object_decref(object
, 1);
399 nwamd_object_release_and_destroy(nwamd_object_t object
)
401 nwamd_object_decref(object
, 2);
405 nwamd_object_release_and_destroy_after_preserve(nwamd_object_t object
)
407 nwamd_object_decref(object
, 3);
411 nwamd_object_release_after_preserve(nwamd_object_t object
)
413 nwamd_object_decref(object
, 2);
417 nwamd_object_set_state_timed(nwam_object_type_t type
, const char *name
,
418 nwam_state_t state
, nwam_aux_state_t aux_state
, uint32_t when
)
420 nwamd_event_t event
= nwamd_event_init_object_state(type
, name
,
423 nlog(LOG_INFO
, "nwamd_object_set_state: state event (%s, %s) for %s",
424 nwam_state_to_string(state
),
425 nwam_aux_state_to_string(aux_state
), name
);
427 nwamd_event_enqueue_timed(event
, when
);
431 nwamd_object_set_state(nwam_object_type_t type
, const char *name
,
432 nwam_state_t state
, nwam_aux_state_t aux_state
)
434 nwamd_object_set_state_timed(type
, name
, state
, aux_state
, 0);
437 nwamd_event_method_t
*
438 nwamd_object_event_methods(nwam_object_type_t type
)
440 struct nwamd_object_list
*object_list
= nwamd_get_object_list(type
);
442 return (object_list
->object_event_methods
);
446 * Walk all objects of specified type calling callback function cb.
447 * Object is locked for duration of callback.
450 nwamd_walk_objects(nwam_object_type_t type
, int (*cb
)(nwamd_object_t
, void *),
453 nwamd_object_t object
;
454 struct nwamd_object_list
*object_list
= nwamd_get_object_list(type
);
457 if (nwamd_object_list_rlock(type
) != 0)
460 for (object
= uu_list_first(object_list
->object_list
);
462 object
= uu_list_next(object_list
->object_list
, object
)) {
463 (void) pthread_mutex_lock(&object
->nwamd_object_mutex
);
464 ret
= cb(object
, data
);
465 (void) pthread_mutex_unlock(&object
->nwamd_object_mutex
);
467 nwamd_object_list_unlock(type
);
471 nwamd_object_list_unlock(type
);