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 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * Functions to sync up library list with that of the run time linker
30 */
31
32 #ifndef DEBUG
33 #define NDEBUG 1
34 #endif
35
36 #include <assert.h>
37
38 #include "tnfctl_int.h"
39 #include "kernel_int.h"
40 #include "dbg.h"
41
42 tnfctl_errcode_t
tnfctl_check_libs(tnfctl_handle_t * hndl)43 tnfctl_check_libs(tnfctl_handle_t *hndl)
44 {
45 tnfctl_errcode_t prexstat;
46 enum event_op_t dl_evt;
47 boolean_t lmap_ok;
48
49 if (hndl->mode == KERNEL_MODE) {
50 prexstat = _tnfctl_refresh_kernel(hndl);
51 return (prexstat);
52 }
53
54 /* hndl refers to a process */
55
56 /* return value of lmap_ok, dl_evt ignored */
57 prexstat = _tnfctl_refresh_process(hndl, &lmap_ok, &dl_evt);
58 assert(lmap_ok == B_TRUE);
59 return (prexstat);
60 }
61
62 /*
63 * _tnfctl_lock_libs() locks the library list maintained in the prex
64 * handle against it changing by a dlopen or dlclose.
65 *
66 * This locking code is between the thread that owns the handle and
67 * another thread that may be doing a dlopen/dlclose. We do not support
68 * the situation of having multiple threads operating on the same
69 * handle - in effect the code per tnfctl_handle can be thought of as
70 * being single-threaded - that is why we can check "hndl->in_objlist"
71 * without first obtaining a lock. "in_objlist" is the re-entrancy
72 * protector on the lock i.e. we can call _tnfctl_lock_libs() safely even if
73 * this thread has the lock held. The return value "release_lock" indicates
74 * whether the lock should be released or not. It can be passed into
75 * _tnfctl_unlock_libs() which will do the right thing.
76 *
77 * All of this is a bit too complex for warlock. Here we give warlock a
78 * simpler view, that these routines have the side effect of acquiring and
79 * releasing the lock, period.
80 */
81
82 tnfctl_errcode_t
_tnfctl_lock_libs(tnfctl_handle_t * hndl,boolean_t * release_lock)83 _tnfctl_lock_libs(tnfctl_handle_t *hndl, boolean_t *release_lock)
84 {
85 #if defined(__lock_lint)
86
87 NOTE(MUTEX_ACQUIRED_AS_SIDE_EFFECT(&warlock_kludge->lmap_lock))
88 mutex_lock(&warlock_kludge->lmap_lock);
89
90 #else
91
92 /* this interface is only for INTERNAL_MODE clients */
93 assert(hndl->mode == INTERNAL_MODE);
94
95 if (hndl->in_objlist == B_TRUE) {
96 /*
97 * already have _tnfctl_lmap_lock held which implies that
98 * the library list has been sync'ed up
99 */
100 *release_lock = B_FALSE;
101 return (TNFCTL_ERR_NONE);
102 }
103
104 /* lock is not currently held, so lock it */
105 mutex_lock(&_tnfctl_lmap_lock);
106 hndl->in_objlist = B_TRUE;
107
108 *release_lock = B_TRUE;
109 return (TNFCTL_ERR_NONE);
110
111 #endif
112 }
113
114 void
_tnfctl_unlock_libs(tnfctl_handle_t * hndl,boolean_t release_lock)115 _tnfctl_unlock_libs(tnfctl_handle_t *hndl, boolean_t release_lock)
116 {
117 #if defined(__lock_lint)
118
119 NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&warlock_kludge->lmap_lock))
120 mutex_unlock(&warlock_kludge->lmap_lock);
121
122 #else
123
124 /* this interface is only for INTERNAL_MODE clients */
125 assert(hndl->mode == INTERNAL_MODE);
126
127 if (release_lock) {
128 hndl->in_objlist = B_FALSE;
129 mutex_unlock(&_tnfctl_lmap_lock);
130 }
131
132 #endif
133 }
134
135 /*
136 * _tnfctl_syn_lib_list() syncs up the library list maintained
137 * in the prex handle with the libraries in the process (if needed)
138 * NOTE: Assumes _tnfctl_lmap_lock is held.
139 *
140 */
141 tnfctl_errcode_t
_tnfctl_sync_lib_list(tnfctl_handle_t * hndl)142 _tnfctl_sync_lib_list(tnfctl_handle_t *hndl)
143 {
144 tnfctl_errcode_t prexstat = TNFCTL_ERR_NONE;
145 enum event_op_t dl_evt;
146 boolean_t lmap_ok;
147
148 /* this interface is only for INTERNAL_MODE clients */
149 assert(hndl->mode == INTERNAL_MODE);
150
151 /* lmap_lock held and in_objlist marked as B_TRUE */
152 if (_tnfctl_libs_changed == B_TRUE) {
153 prexstat = _tnfctl_refresh_process(hndl, &lmap_ok, &dl_evt);
154 if (prexstat) {
155 return (prexstat);
156 }
157 }
158 return (TNFCTL_ERR_NONE);
159 }
160