xref: /illumos-gate/usr/src/lib/libtnfctl/checklib.c (revision e2f4f3da)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1994, by Sun Microsytems, Inc.
24  */
25 
26 /*
27  * Functions to sync up library list with that of the run time linker
28  */
29 
30 #ifndef DEBUG
31 #define	NDEBUG	1
32 #endif
33 
34 #include <assert.h>
35 
36 #include "tnfctl_int.h"
37 #include "kernel_int.h"
38 #include "dbg.h"
39 
40 tnfctl_errcode_t
tnfctl_check_libs(tnfctl_handle_t * hndl)41 tnfctl_check_libs(tnfctl_handle_t *hndl)
42 {
43 	tnfctl_errcode_t	prexstat;
44 	enum event_op_t		dl_evt;
45 	boolean_t		lmap_ok;
46 
47 	if (hndl->mode == KERNEL_MODE) {
48 		prexstat = _tnfctl_refresh_kernel(hndl);
49 		return (prexstat);
50 	}
51 
52 	/* hndl refers to a process */
53 
54 	/* return value of lmap_ok, dl_evt ignored */
55 	prexstat = _tnfctl_refresh_process(hndl, &lmap_ok, &dl_evt);
56 	assert(lmap_ok == B_TRUE);
57 	return (prexstat);
58 }
59 
60 /*
61  * _tnfctl_lock_libs() locks the library list maintained in the prex
62  * handle against it changing by a dlopen or dlclose.
63  *
64  * This locking code is between the thread that owns the handle and
65  * another thread that may be doing a dlopen/dlclose.  We do not support
66  * the situation of having multiple threads operating on the same
67  * handle - in effect the code per tnfctl_handle can be thought of as
68  * being single-threaded - that is why we can check "hndl->in_objlist"
69  * without first obtaining a lock.  "in_objlist" is the re-entrancy
70  * protector on the lock i.e. we can call _tnfctl_lock_libs() safely even if
71  * this thread has the lock held.  The return value "release_lock" indicates
72  * whether the lock should be released or not.  It can be passed into
73  * _tnfctl_unlock_libs() which will do the right thing.
74  */
75 
76 tnfctl_errcode_t
_tnfctl_lock_libs(tnfctl_handle_t * hndl,boolean_t * release_lock)77 _tnfctl_lock_libs(tnfctl_handle_t *hndl, boolean_t *release_lock)
78 {
79 	/* this interface is only for INTERNAL_MODE clients */
80 	assert(hndl->mode == INTERNAL_MODE);
81 
82 	if (hndl->in_objlist == B_TRUE) {
83 		/*
84 		 * already have _tnfctl_lmap_lock held which implies that
85 		 * the library list has been sync'ed up
86 		 */
87 		*release_lock = B_FALSE;
88 		return (TNFCTL_ERR_NONE);
89 	}
90 
91 	/* lock is not currently held, so lock it */
92 	mutex_lock(&_tnfctl_lmap_lock);
93 	hndl->in_objlist = B_TRUE;
94 
95 	*release_lock = B_TRUE;
96 	return (TNFCTL_ERR_NONE);
97 }
98 
99 void
_tnfctl_unlock_libs(tnfctl_handle_t * hndl,boolean_t release_lock)100 _tnfctl_unlock_libs(tnfctl_handle_t *hndl, boolean_t release_lock)
101 {
102 	/* this interface is only for INTERNAL_MODE clients */
103 	assert(hndl->mode == INTERNAL_MODE);
104 
105 	if (release_lock) {
106 		hndl->in_objlist = B_FALSE;
107 		mutex_unlock(&_tnfctl_lmap_lock);
108 	}
109 }
110 
111 /*
112  * _tnfctl_syn_lib_list() syncs up the library list maintained
113  * in the prex handle with the libraries in the process (if needed)
114  * NOTE: Assumes _tnfctl_lmap_lock is held.
115  *
116  */
117 tnfctl_errcode_t
_tnfctl_sync_lib_list(tnfctl_handle_t * hndl)118 _tnfctl_sync_lib_list(tnfctl_handle_t *hndl)
119 {
120 	tnfctl_errcode_t	prexstat = TNFCTL_ERR_NONE;
121 	enum event_op_t		dl_evt;
122 	boolean_t		lmap_ok;
123 
124 	/* this interface is only for INTERNAL_MODE clients */
125 	assert(hndl->mode == INTERNAL_MODE);
126 
127 	/* lmap_lock held and in_objlist marked as B_TRUE */
128 	if (_tnfctl_libs_changed == B_TRUE) {
129 		prexstat = _tnfctl_refresh_process(hndl, &lmap_ok, &dl_evt);
130 		if (prexstat) {
131 			return (prexstat);
132 		}
133 	}
134 	return (TNFCTL_ERR_NONE);
135 }
136