File: | cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c |
Warning: | line 2474, column 7 Copies out a struct with uncleared padding (>= 3 bytes) |
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 (the "License"). | |||
6 | * You may not use this file except in compliance with the License. | |||
7 | * | |||
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. | |||
12 | * | |||
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] | |||
18 | * | |||
19 | * CDDL HEADER END | |||
20 | * | |||
21 | * Portions Copyright 2010 The FreeBSD Foundation | |||
22 | * | |||
23 | * $FreeBSD: releng/11.0/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c 296479 2016-03-08 00:43:03Z markj $ | |||
24 | */ | |||
25 | ||||
26 | /* | |||
27 | * Copyright 2008 Sun Microsystems, Inc. All rights reserved. | |||
28 | * Use is subject to license terms. | |||
29 | */ | |||
30 | ||||
31 | /* | |||
32 | * Copyright (c) 2015, Joyent, Inc. All rights reserved. | |||
33 | */ | |||
34 | ||||
35 | #include <sys/atomic.h> | |||
36 | #include <sys/errno.h> | |||
37 | #include <sys/stat.h> | |||
38 | #include <sys/modctl.h> | |||
39 | #include <sys/conf.h> | |||
40 | #include <sys/systm.h> | |||
41 | #ifdef illumos | |||
42 | #include <sys/ddi.h> | |||
43 | #endif | |||
44 | #include <sys/sunddi.h> | |||
45 | #include <sys/cpuvar.h> | |||
46 | #include <sys/kmem.h> | |||
47 | #ifdef illumos | |||
48 | #include <sys/strsubr.h> | |||
49 | #endif | |||
50 | #include <sys/fasttrap.h> | |||
51 | #include <sys/fasttrap_impl.h> | |||
52 | #include <sys/fasttrap_isa.h> | |||
53 | #include <sys/dtrace.h> | |||
54 | #include <sys/dtrace_impl.h> | |||
55 | #include <sys/sysmacros.h> | |||
56 | #include <sys/proc.h> | |||
57 | #include <sys/policy.h> | |||
58 | #ifdef illumos | |||
59 | #include <util/qsort.h> | |||
60 | #endif | |||
61 | #include <sys/mutex.h> | |||
62 | #include <sys/kernel.h> | |||
63 | #ifndef illumos | |||
64 | #include <sys/dtrace_bsd.h> | |||
65 | #include <sys/eventhandler.h> | |||
66 | #include <sys/rmlock.h> | |||
67 | #include <sys/sysctl.h> | |||
68 | #include <sys/u8_textprep.h> | |||
69 | #include <sys/user.h> | |||
70 | ||||
71 | #include <vm/vm.h> | |||
72 | #include <vm/pmap.h> | |||
73 | #include <vm/vm_map.h> | |||
74 | #include <vm/vm_param.h> | |||
75 | ||||
76 | #include <cddl/dev/dtrace/dtrace_cddl.h> | |||
77 | #endif | |||
78 | ||||
79 | /* | |||
80 | * User-Land Trap-Based Tracing | |||
81 | * ---------------------------- | |||
82 | * | |||
83 | * The fasttrap provider allows DTrace consumers to instrument any user-level | |||
84 | * instruction to gather data; this includes probes with semantic | |||
85 | * signifigance like entry and return as well as simple offsets into the | |||
86 | * function. While the specific techniques used are very ISA specific, the | |||
87 | * methodology is generalizable to any architecture. | |||
88 | * | |||
89 | * | |||
90 | * The General Methodology | |||
91 | * ----------------------- | |||
92 | * | |||
93 | * With the primary goal of tracing every user-land instruction and the | |||
94 | * limitation that we can't trust user space so don't want to rely on much | |||
95 | * information there, we begin by replacing the instructions we want to trace | |||
96 | * with trap instructions. Each instruction we overwrite is saved into a hash | |||
97 | * table keyed by process ID and pc address. When we enter the kernel due to | |||
98 | * this trap instruction, we need the effects of the replaced instruction to | |||
99 | * appear to have occurred before we proceed with the user thread's | |||
100 | * execution. | |||
101 | * | |||
102 | * Each user level thread is represented by a ulwp_t structure which is | |||
103 | * always easily accessible through a register. The most basic way to produce | |||
104 | * the effects of the instruction we replaced is to copy that instruction out | |||
105 | * to a bit of scratch space reserved in the user thread's ulwp_t structure | |||
106 | * (a sort of kernel-private thread local storage), set the PC to that | |||
107 | * scratch space and single step. When we reenter the kernel after single | |||
108 | * stepping the instruction we must then adjust the PC to point to what would | |||
109 | * normally be the next instruction. Of course, special care must be taken | |||
110 | * for branches and jumps, but these represent such a small fraction of any | |||
111 | * instruction set that writing the code to emulate these in the kernel is | |||
112 | * not too difficult. | |||
113 | * | |||
114 | * Return probes may require several tracepoints to trace every return site, | |||
115 | * and, conversely, each tracepoint may activate several probes (the entry | |||
116 | * and offset 0 probes, for example). To solve this muliplexing problem, | |||
117 | * tracepoints contain lists of probes to activate and probes contain lists | |||
118 | * of tracepoints to enable. If a probe is activated, it adds its ID to | |||
119 | * existing tracepoints or creates new ones as necessary. | |||
120 | * | |||
121 | * Most probes are activated _before_ the instruction is executed, but return | |||
122 | * probes are activated _after_ the effects of the last instruction of the | |||
123 | * function are visible. Return probes must be fired _after_ we have | |||
124 | * single-stepped the instruction whereas all other probes are fired | |||
125 | * beforehand. | |||
126 | * | |||
127 | * | |||
128 | * Lock Ordering | |||
129 | * ------------- | |||
130 | * | |||
131 | * The lock ordering below -- both internally and with respect to the DTrace | |||
132 | * framework -- is a little tricky and bears some explanation. Each provider | |||
133 | * has a lock (ftp_mtx) that protects its members including reference counts | |||
134 | * for enabled probes (ftp_rcount), consumers actively creating probes | |||
135 | * (ftp_ccount) and USDT consumers (ftp_mcount); all three prevent a provider | |||
136 | * from being freed. A provider is looked up by taking the bucket lock for the | |||
137 | * provider hash table, and is returned with its lock held. The provider lock | |||
138 | * may be taken in functions invoked by the DTrace framework, but may not be | |||
139 | * held while calling functions in the DTrace framework. | |||
140 | * | |||
141 | * To ensure consistency over multiple calls to the DTrace framework, the | |||
142 | * creation lock (ftp_cmtx) should be held. Naturally, the creation lock may | |||
143 | * not be taken when holding the provider lock as that would create a cyclic | |||
144 | * lock ordering. In situations where one would naturally take the provider | |||
145 | * lock and then the creation lock, we instead up a reference count to prevent | |||
146 | * the provider from disappearing, drop the provider lock, and acquire the | |||
147 | * creation lock. | |||
148 | * | |||
149 | * Briefly: | |||
150 | * bucket lock before provider lock | |||
151 | * DTrace before provider lock | |||
152 | * creation lock before DTrace | |||
153 | * never hold the provider lock and creation lock simultaneously | |||
154 | */ | |||
155 | ||||
156 | static d_open_t fasttrap_open; | |||
157 | static d_ioctl_t fasttrap_ioctl; | |||
158 | ||||
159 | static struct cdevsw fasttrap_cdevsw = { | |||
160 | .d_version = D_VERSION0x17122009, | |||
161 | .d_open = fasttrap_open, | |||
162 | .d_ioctl = fasttrap_ioctl, | |||
163 | .d_name = "fasttrap", | |||
164 | }; | |||
165 | static struct cdev *fasttrap_cdev; | |||
166 | static dtrace_meta_provider_id_t fasttrap_meta_id; | |||
167 | ||||
168 | static struct proc *fasttrap_cleanup_proc; | |||
169 | static struct mtx fasttrap_cleanup_mtx; | |||
170 | static uint_t fasttrap_cleanup_work, fasttrap_cleanup_drain, fasttrap_cleanup_cv; | |||
171 | ||||
172 | /* | |||
173 | * Generation count on modifications to the global tracepoint lookup table. | |||
174 | */ | |||
175 | static volatile uint64_t fasttrap_mod_gen; | |||
176 | ||||
177 | /* | |||
178 | * When the fasttrap provider is loaded, fasttrap_max is set to either | |||
179 | * FASTTRAP_MAX_DEFAULT, or the value for fasttrap-max-probes in the | |||
180 | * fasttrap.conf file (Illumos), or the value provied in the loader.conf (FreeBSD). | |||
181 | * Each time a probe is created, fasttrap_total is incremented by the number | |||
182 | * of tracepoints that may be associated with that probe; fasttrap_total is capped | |||
183 | * at fasttrap_max. | |||
184 | */ | |||
185 | #define FASTTRAP_MAX_DEFAULT250000 250000 | |||
186 | static uint32_t fasttrap_max = FASTTRAP_MAX_DEFAULT250000; | |||
187 | static uint32_t fasttrap_total; | |||
188 | ||||
189 | /* | |||
190 | * Copyright (c) 2011, Joyent, Inc. All rights reserved. | |||
191 | */ | |||
192 | ||||
193 | #define FASTTRAP_TPOINTS_DEFAULT_SIZE0x4000 0x4000 | |||
194 | #define FASTTRAP_PROVIDERS_DEFAULT_SIZE0x100 0x100 | |||
195 | #define FASTTRAP_PROCS_DEFAULT_SIZE0x100 0x100 | |||
196 | ||||
197 | #define FASTTRAP_PID_NAME"pid" "pid" | |||
198 | ||||
199 | fasttrap_hash_t fasttrap_tpoints; | |||
200 | static fasttrap_hash_t fasttrap_provs; | |||
201 | static fasttrap_hash_t fasttrap_procs; | |||
202 | ||||
203 | static uint64_t fasttrap_pid_count; /* pid ref count */ | |||
204 | static kmutex_t fasttrap_count_mtx; /* lock on ref count */ | |||
205 | ||||
206 | #define FASTTRAP_ENABLE_FAIL1 1 | |||
207 | #define FASTTRAP_ENABLE_PARTIAL2 2 | |||
208 | ||||
209 | static int fasttrap_tracepoint_enable(proc_t *, fasttrap_probe_t *, uint_t); | |||
210 | static void fasttrap_tracepoint_disable(proc_t *, fasttrap_probe_t *, uint_t); | |||
211 | ||||
212 | static fasttrap_provider_t *fasttrap_provider_lookup(pid_t, const char *, | |||
213 | const dtrace_pattr_t *); | |||
214 | static void fasttrap_provider_retire(pid_t, const char *, int); | |||
215 | static void fasttrap_provider_free(fasttrap_provider_t *); | |||
216 | ||||
217 | static fasttrap_proc_t *fasttrap_proc_lookup(pid_t); | |||
218 | static void fasttrap_proc_release(fasttrap_proc_t *); | |||
219 | ||||
220 | #ifndef illumos | |||
221 | static void fasttrap_thread_dtor(void *, struct thread *); | |||
222 | #endif | |||
223 | ||||
224 | #define FASTTRAP_PROVS_INDEX(pid, name)((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask ) \ | |||
225 | ((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask) | |||
226 | ||||
227 | #define FASTTRAP_PROCS_INDEX(pid)((pid) & fasttrap_procs.fth_mask) ((pid) & fasttrap_procs.fth_mask) | |||
228 | ||||
229 | #ifndef illumos | |||
230 | struct rmlock fasttrap_tp_lock; | |||
231 | static eventhandler_tag fasttrap_thread_dtor_tag; | |||
232 | #endif | |||
233 | ||||
234 | static unsigned long tpoints_hash_size = FASTTRAP_TPOINTS_DEFAULT_SIZE0x4000; | |||
235 | ||||
236 | #ifdef __FreeBSD__11 | |||
237 | SYSCTL_DECL(_kern_dtrace)extern struct sysctl_oid sysctl___kern_dtrace; | |||
238 | SYSCTL_NODE(_kern_dtrace, OID_AUTO, fasttrap, CTLFLAG_RD, 0, "DTrace fasttrap parameters")struct sysctl_oid sysctl___kern_dtrace_fasttrap = { .oid_parent = ((&(&sysctl___kern_dtrace)->oid_children)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind = (1|(0x80000000 )), .oid_arg1 = (((void *)0)), .oid_arg2 = (0), .oid_name = ( "fasttrap"), .oid_handler = (0), .oid_fmt = ("N"), .oid_descr = "DTrace fasttrap parameters" }; __asm__(".globl " "__start_set_sysctl_set" ); __asm__(".globl " "__stop_set_sysctl_set"); static void const * const __set_sysctl_set_sym_sysctl___kern_dtrace_fasttrap __attribute__ ((__section__("set_" "sysctl_set"))) __attribute__((__used__) ) = &(sysctl___kern_dtrace_fasttrap); _Static_assert(((0x80000000 ) & 0xf) == 0 || ((0x80000000) & 0xf) == 1, "compile-time assertion failed" ); | |||
239 | SYSCTL_UINT(_kern_dtrace_fasttrap, OID_AUTO, max_probes, CTLFLAG_RWTUN, &fasttrap_max,static struct sysctl_oid sysctl___kern_dtrace_fasttrap_max_probes = { .oid_parent = ((&(&sysctl___kern_dtrace_fasttrap )->oid_children)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind = (6 | 0x00040000 | (((0x80000000|0x40000000 )|0x00080000))), .oid_arg1 = (&fasttrap_max), .oid_arg2 = (250000), .oid_name = ("max_probes"), .oid_handler = (sysctl_handle_int ), .oid_fmt = ("IU"), .oid_descr = "Maximum number of fasttrap probes" }; __asm__(".globl " "__start_set_sysctl_set"); __asm__(".globl " "__stop_set_sysctl_set"); static void const * const __set_sysctl_set_sym_sysctl___kern_dtrace_fasttrap_max_probes __attribute__((__section__("set_" "sysctl_set"))) __attribute__ ((__used__)) = &(sysctl___kern_dtrace_fasttrap_max_probes ); _Static_assert((((((0x80000000|0x40000000)|0x00080000)) & 0xf) == 0 || ((((0x80000000|0x40000000)|0x00080000)) & 0xf ) == 6) && sizeof(unsigned) == sizeof(*(&fasttrap_max )), "compile-time assertion failed") | |||
240 | FASTTRAP_MAX_DEFAULT, "Maximum number of fasttrap probes")static struct sysctl_oid sysctl___kern_dtrace_fasttrap_max_probes = { .oid_parent = ((&(&sysctl___kern_dtrace_fasttrap )->oid_children)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind = (6 | 0x00040000 | (((0x80000000|0x40000000 )|0x00080000))), .oid_arg1 = (&fasttrap_max), .oid_arg2 = (250000), .oid_name = ("max_probes"), .oid_handler = (sysctl_handle_int ), .oid_fmt = ("IU"), .oid_descr = "Maximum number of fasttrap probes" }; __asm__(".globl " "__start_set_sysctl_set"); __asm__(".globl " "__stop_set_sysctl_set"); static void const * const __set_sysctl_set_sym_sysctl___kern_dtrace_fasttrap_max_probes __attribute__((__section__("set_" "sysctl_set"))) __attribute__ ((__used__)) = &(sysctl___kern_dtrace_fasttrap_max_probes ); _Static_assert((((((0x80000000|0x40000000)|0x00080000)) & 0xf) == 0 || ((((0x80000000|0x40000000)|0x00080000)) & 0xf ) == 6) && sizeof(unsigned) == sizeof(*(&fasttrap_max )), "compile-time assertion failed"); | |||
241 | SYSCTL_ULONG(_kern_dtrace_fasttrap, OID_AUTO, tpoints_hash_size, CTLFLAG_RDTUN, &tpoints_hash_size,static struct sysctl_oid sysctl___kern_dtrace_fasttrap_tpoints_hash_size = { .oid_parent = ((&(&sysctl___kern_dtrace_fasttrap )->oid_children)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind = (8 | 0x00040000 | ((0x80000000|0x00080000 ))), .oid_arg1 = (&tpoints_hash_size), .oid_arg2 = (0x4000 ), .oid_name = ("tpoints_hash_size"), .oid_handler = (sysctl_handle_long ), .oid_fmt = ("LU"), .oid_descr = "Size of the tracepoint hash table" }; __asm__(".globl " "__start_set_sysctl_set"); __asm__(".globl " "__stop_set_sysctl_set"); static void const * const __set_sysctl_set_sym_sysctl___kern_dtrace_fasttrap_tpoints_hash_size __attribute__((__section__("set_" "sysctl_set"))) __attribute__ ((__used__)) = &(sysctl___kern_dtrace_fasttrap_tpoints_hash_size ); _Static_assert(((((0x80000000|0x00080000)) & 0xf) == 0 || (((0x80000000|0x00080000)) & 0xf) == 8) && sizeof (unsigned long) == sizeof(*(&tpoints_hash_size)), "compile-time assertion failed" ) | |||
242 | FASTTRAP_TPOINTS_DEFAULT_SIZE, "Size of the tracepoint hash table")static struct sysctl_oid sysctl___kern_dtrace_fasttrap_tpoints_hash_size = { .oid_parent = ((&(&sysctl___kern_dtrace_fasttrap )->oid_children)), .oid_children = { ((void *)0) }, .oid_number = ((-1)), .oid_kind = (8 | 0x00040000 | ((0x80000000|0x00080000 ))), .oid_arg1 = (&tpoints_hash_size), .oid_arg2 = (0x4000 ), .oid_name = ("tpoints_hash_size"), .oid_handler = (sysctl_handle_long ), .oid_fmt = ("LU"), .oid_descr = "Size of the tracepoint hash table" }; __asm__(".globl " "__start_set_sysctl_set"); __asm__(".globl " "__stop_set_sysctl_set"); static void const * const __set_sysctl_set_sym_sysctl___kern_dtrace_fasttrap_tpoints_hash_size __attribute__((__section__("set_" "sysctl_set"))) __attribute__ ((__used__)) = &(sysctl___kern_dtrace_fasttrap_tpoints_hash_size ); _Static_assert(((((0x80000000|0x00080000)) & 0xf) == 0 || (((0x80000000|0x00080000)) & 0xf) == 8) && sizeof (unsigned long) == sizeof(*(&tpoints_hash_size)), "compile-time assertion failed" ); | |||
243 | #endif | |||
244 | ||||
245 | static int | |||
246 | fasttrap_highbit(ulong_t i) | |||
247 | { | |||
248 | int h = 1; | |||
249 | ||||
250 | if (i == 0) | |||
251 | return (0); | |||
252 | #ifdef _LP641 | |||
253 | if (i & 0xffffffff00000000ul) { | |||
254 | h += 32; i >>= 32; | |||
255 | } | |||
256 | #endif | |||
257 | if (i & 0xffff0000) { | |||
258 | h += 16; i >>= 16; | |||
259 | } | |||
260 | if (i & 0xff00) { | |||
261 | h += 8; i >>= 8; | |||
262 | } | |||
263 | if (i & 0xf0) { | |||
264 | h += 4; i >>= 4; | |||
265 | } | |||
266 | if (i & 0xc) { | |||
267 | h += 2; i >>= 2; | |||
268 | } | |||
269 | if (i & 0x2) { | |||
270 | h += 1; | |||
271 | } | |||
272 | return (h); | |||
273 | } | |||
274 | ||||
275 | static uint_t | |||
276 | fasttrap_hash_str(const char *p) | |||
277 | { | |||
278 | unsigned int g; | |||
279 | uint_t hval = 0; | |||
280 | ||||
281 | while (*p) { | |||
282 | hval = (hval << 4) + *p++; | |||
283 | if ((g = (hval & 0xf0000000)) != 0) | |||
284 | hval ^= g >> 24; | |||
285 | hval &= ~g; | |||
286 | } | |||
287 | return (hval); | |||
288 | } | |||
289 | ||||
290 | void | |||
291 | fasttrap_sigtrap(proc_t *p, kthread_t *t, uintptr_t pc) | |||
292 | { | |||
293 | #ifdef illumos | |||
294 | sigqueue_t *sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP)zfs_kmem_alloc((sizeof (sigqueue_t)), (0x0002) | 0x0100); | |||
295 | ||||
296 | sqp->sq_info.si_signo = SIGTRAP5; | |||
297 | sqp->sq_info.si_code = TRAP_DTRACE3; | |||
298 | sqp->sq_info.si_addr = (caddr_t)pc; | |||
299 | ||||
300 | mutex_enter(&p->p_lock)(void)_sx_xlock(((&p->p_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (300)); | |||
301 | sigaddqa(p, t, sqp); | |||
302 | mutex_exit(&p->p_lock)_sx_xunlock(((&p->p_lock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (302)); | |||
303 | ||||
304 | if (t != NULL((void *)0)) | |||
305 | aston(t); | |||
306 | #else | |||
307 | ksiginfo_t *ksi = kmem_zalloc(sizeof (ksiginfo_t), KM_SLEEP)zfs_kmem_alloc((sizeof (ksiginfo_t)), (0x0002) | 0x0100); | |||
308 | ||||
309 | ksiginfo_init(ksi)do { bzero(ksi, sizeof(ksiginfo_t)); } while(0); | |||
310 | ksi->ksi_signoksi_info.si_signo = SIGTRAP5; | |||
311 | ksi->ksi_codeksi_info.si_code = TRAP_DTRACE3; | |||
312 | ksi->ksi_addrksi_info.si_addr = (caddr_t)pc; | |||
313 | PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (313)); | |||
314 | (void) tdsendsignal(p, t, SIGTRAP5, ksi); | |||
315 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (315)); | |||
316 | #endif | |||
317 | } | |||
318 | ||||
319 | #ifndef illumos | |||
320 | /* | |||
321 | * Obtain a chunk of scratch space in the address space of the target process. | |||
322 | */ | |||
323 | fasttrap_scrspace_t * | |||
324 | fasttrap_scraddr(struct thread *td, fasttrap_proc_t *fprc) | |||
325 | { | |||
326 | fasttrap_scrblock_t *scrblk; | |||
327 | fasttrap_scrspace_t *scrspc; | |||
328 | struct proc *p; | |||
329 | vm_offset_t addr; | |||
330 | int error, i; | |||
331 | ||||
332 | scrspc = NULL((void *)0); | |||
333 | if (td->t_dtrace_sscrtd_dtrace->td_dtrace_sscr != NULL((void *)0)) { | |||
334 | /* If the thread already has scratch space, we're done. */ | |||
335 | scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscrtd_dtrace->td_dtrace_sscr; | |||
336 | return (scrspc); | |||
337 | } | |||
338 | ||||
339 | p = td->td_proc; | |||
340 | ||||
341 | mutex_enter(&fprc->ftpc_mtx)(void)_sx_xlock(((&fprc->ftpc_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (341)); | |||
342 | if (LIST_EMPTY(&fprc->ftpc_fscr)((&fprc->ftpc_fscr)->lh_first == ((void *)0))) { | |||
343 | /* | |||
344 | * No scratch space is available, so we'll map a new scratch | |||
345 | * space block into the traced process' address space. | |||
346 | */ | |||
347 | addr = 0; | |||
348 | error = vm_map_find(&p->p_vmspace->vm_map, NULL((void *)0), 0, &addr, | |||
349 | FASTTRAP_SCRBLOCK_SIZE(1<<12), 0, VMFS_ANY_SPACE1, VM_PROT_ALL(((vm_prot_t) 0x01)|((vm_prot_t) 0x02)|((vm_prot_t) 0x04)), | |||
350 | VM_PROT_ALL(((vm_prot_t) 0x01)|((vm_prot_t) 0x02)|((vm_prot_t) 0x04)), 0); | |||
351 | if (error != KERN_SUCCESS0) | |||
352 | goto done; | |||
353 | ||||
354 | scrblk = malloc(sizeof(*scrblk), M_SOLARIS, M_WAITOK0x0002); | |||
355 | scrblk->ftsb_addr = addr; | |||
356 | LIST_INSERT_HEAD(&fprc->ftpc_scrblks, scrblk, ftsb_next)do { ; if (((((scrblk))->ftsb_next.le_next) = (((&fprc ->ftpc_scrblks))->lh_first)) != ((void *)0)) (((&fprc ->ftpc_scrblks))->lh_first)->ftsb_next.le_prev = & (((scrblk))->ftsb_next.le_next); (((&fprc->ftpc_scrblks ))->lh_first) = (scrblk); (scrblk)->ftsb_next.le_prev = &(((&fprc->ftpc_scrblks))->lh_first); } while ( 0); | |||
357 | ||||
358 | /* | |||
359 | * Carve the block up into chunks and put them on the free list. | |||
360 | */ | |||
361 | for (i = 0; | |||
362 | i < FASTTRAP_SCRBLOCK_SIZE(1<<12) / FASTTRAP_SCRSPACE_SIZE64; i++) { | |||
363 | scrspc = malloc(sizeof(*scrspc), M_SOLARIS, M_WAITOK0x0002); | |||
364 | scrspc->ftss_addr = addr + | |||
365 | i * FASTTRAP_SCRSPACE_SIZE64; | |||
366 | LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc,do { ; if (((((scrspc))->ftss_next.le_next) = (((&fprc ->ftpc_fscr))->lh_first)) != ((void *)0)) (((&fprc-> ftpc_fscr))->lh_first)->ftss_next.le_prev = &(((scrspc ))->ftss_next.le_next); (((&fprc->ftpc_fscr))->lh_first ) = (scrspc); (scrspc)->ftss_next.le_prev = &(((&fprc ->ftpc_fscr))->lh_first); } while (0) | |||
367 | ftss_next)do { ; if (((((scrspc))->ftss_next.le_next) = (((&fprc ->ftpc_fscr))->lh_first)) != ((void *)0)) (((&fprc-> ftpc_fscr))->lh_first)->ftss_next.le_prev = &(((scrspc ))->ftss_next.le_next); (((&fprc->ftpc_fscr))->lh_first ) = (scrspc); (scrspc)->ftss_next.le_prev = &(((&fprc ->ftpc_fscr))->lh_first); } while (0); | |||
368 | } | |||
369 | } | |||
370 | ||||
371 | /* | |||
372 | * Take the first scratch chunk off the free list, put it on the | |||
373 | * allocated list, and return its address. | |||
374 | */ | |||
375 | scrspc = LIST_FIRST(&fprc->ftpc_fscr)((&fprc->ftpc_fscr)->lh_first); | |||
376 | LIST_REMOVE(scrspc, ftss_next)do { ; ; ; ; if ((((scrspc))->ftss_next.le_next) != ((void *)0)) (((scrspc))->ftss_next.le_next)->ftss_next.le_prev = (scrspc)->ftss_next.le_prev; *(scrspc)->ftss_next.le_prev = (((scrspc))->ftss_next.le_next); ; ; } while (0); | |||
377 | LIST_INSERT_HEAD(&fprc->ftpc_ascr, scrspc, ftss_next)do { ; if (((((scrspc))->ftss_next.le_next) = (((&fprc ->ftpc_ascr))->lh_first)) != ((void *)0)) (((&fprc-> ftpc_ascr))->lh_first)->ftss_next.le_prev = &(((scrspc ))->ftss_next.le_next); (((&fprc->ftpc_ascr))->lh_first ) = (scrspc); (scrspc)->ftss_next.le_prev = &(((&fprc ->ftpc_ascr))->lh_first); } while (0); | |||
378 | ||||
379 | /* | |||
380 | * This scratch space is reserved for use by td until the thread exits. | |||
381 | */ | |||
382 | td->t_dtrace_sscrtd_dtrace->td_dtrace_sscr = scrspc; | |||
383 | ||||
384 | done: | |||
385 | mutex_exit(&fprc->ftpc_mtx)_sx_xunlock(((&fprc->ftpc_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (385)); | |||
386 | ||||
387 | return (scrspc); | |||
388 | } | |||
389 | ||||
390 | /* | |||
391 | * Return any allocated per-thread scratch space chunks back to the process' | |||
392 | * free list. | |||
393 | */ | |||
394 | static void | |||
395 | fasttrap_thread_dtor(void *arg __unused__attribute__((__unused__)), struct thread *td) | |||
396 | { | |||
397 | fasttrap_bucket_t *bucket; | |||
398 | fasttrap_proc_t *fprc; | |||
399 | fasttrap_scrspace_t *scrspc; | |||
400 | pid_t pid; | |||
401 | ||||
402 | if (td->t_dtrace_sscrtd_dtrace->td_dtrace_sscr == NULL((void *)0)) | |||
403 | return; | |||
404 | ||||
405 | pid = td->td_proc->p_pid; | |||
406 | bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)((pid) & fasttrap_procs.fth_mask)]; | |||
407 | fprc = NULL((void *)0); | |||
408 | ||||
409 | /* Look up the fasttrap process handle for this process. */ | |||
410 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (410)); | |||
411 | for (fprc = bucket->ftb_data; fprc != NULL((void *)0); fprc = fprc->ftpc_next) { | |||
412 | if (fprc->ftpc_pid == pid) { | |||
413 | mutex_enter(&fprc->ftpc_mtx)(void)_sx_xlock(((&fprc->ftpc_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (413)); | |||
414 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (414)); | |||
415 | break; | |||
416 | } | |||
417 | } | |||
418 | if (fprc == NULL((void *)0)) { | |||
419 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (419)); | |||
420 | return; | |||
421 | } | |||
422 | ||||
423 | scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscrtd_dtrace->td_dtrace_sscr; | |||
424 | LIST_REMOVE(scrspc, ftss_next)do { ; ; ; ; if ((((scrspc))->ftss_next.le_next) != ((void *)0)) (((scrspc))->ftss_next.le_next)->ftss_next.le_prev = (scrspc)->ftss_next.le_prev; *(scrspc)->ftss_next.le_prev = (((scrspc))->ftss_next.le_next); ; ; } while (0); | |||
425 | LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc, ftss_next)do { ; if (((((scrspc))->ftss_next.le_next) = (((&fprc ->ftpc_fscr))->lh_first)) != ((void *)0)) (((&fprc-> ftpc_fscr))->lh_first)->ftss_next.le_prev = &(((scrspc ))->ftss_next.le_next); (((&fprc->ftpc_fscr))->lh_first ) = (scrspc); (scrspc)->ftss_next.le_prev = &(((&fprc ->ftpc_fscr))->lh_first); } while (0); | |||
426 | ||||
427 | mutex_exit(&fprc->ftpc_mtx)_sx_xunlock(((&fprc->ftpc_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (427)); | |||
428 | } | |||
429 | #endif | |||
430 | ||||
431 | /* | |||
432 | * This function ensures that no threads are actively using the memory | |||
433 | * associated with probes that were formerly live. | |||
434 | */ | |||
435 | static void | |||
436 | fasttrap_mod_barrier(uint64_t gen) | |||
437 | { | |||
438 | int i; | |||
439 | ||||
440 | if (gen < fasttrap_mod_gen) | |||
441 | return; | |||
442 | ||||
443 | fasttrap_mod_gen++; | |||
444 | ||||
445 | #ifdef illumos | |||
446 | CPU_FOREACH(i)for ((i) = 0; (i) <= mp_maxid; (i)++) if (!(!((((&all_cpus )->__bits[(((((((256)) + (((sizeof(long) * 8)) - 1)) / ((sizeof (long) * 8)))) == 1) ? 0 : (((i)) / (sizeof(long) * 8)))] & (1L << ((((((((256))) + (((sizeof(long) * 8)) - 1)) / ( (sizeof(long) * 8)))) == 1) ? (__size_t)(((i))) : ((((i))) % ( sizeof(long) * 8))))) != 0)))) { | |||
447 | mutex_enter(&fasttrap_cpuc_pid_lock[i])(void)_sx_xlock(((&fasttrap_cpuc_pid_lock[i])), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (447)); | |||
448 | mutex_exit(&fasttrap_cpuc_pid_lock[i])_sx_xunlock(((&fasttrap_cpuc_pid_lock[i])), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (448)); | |||
449 | } | |||
450 | #else | |||
451 | rm_wlock(&fasttrap_tp_lock)_rm_wlock_debug((&fasttrap_tp_lock), "/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" , 451); | |||
452 | rm_wunlock(&fasttrap_tp_lock)_rm_wunlock_debug((&fasttrap_tp_lock), "/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" , 452); | |||
453 | #endif | |||
454 | } | |||
455 | ||||
456 | /* | |||
457 | * This function performs asynchronous cleanup of fasttrap providers. The | |||
458 | * Solaris implementation of this mechanism use a timeout that's activated in | |||
459 | * fasttrap_pid_cleanup(), but this doesn't work in FreeBSD: one may sleep while | |||
460 | * holding the DTrace mutexes, but it is unsafe to sleep in a callout handler. | |||
461 | * Thus we use a dedicated process to perform the cleanup when requested. | |||
462 | */ | |||
463 | /*ARGSUSED*/ | |||
464 | static void | |||
465 | fasttrap_pid_cleanup_cb(void *data) | |||
466 | { | |||
467 | fasttrap_provider_t **fpp, *fp; | |||
468 | fasttrap_bucket_t *bucket; | |||
469 | dtrace_provider_id_t provid; | |||
470 | int i, later = 0, rval; | |||
471 | ||||
472 | mtx_lock(&fasttrap_cleanup_mtx)__mtx_lock_flags(&((((&fasttrap_cleanup_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (472)); | |||
473 | while (!fasttrap_cleanup_drain || later > 0) { | |||
474 | fasttrap_cleanup_work = 0; | |||
475 | mtx_unlock(&fasttrap_cleanup_mtx)__mtx_unlock_flags(&((((&fasttrap_cleanup_mtx))))-> mtx_lock, ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (475)); | |||
476 | ||||
477 | later = 0; | |||
478 | ||||
479 | /* | |||
480 | * Iterate over all the providers trying to remove the marked | |||
481 | * ones. If a provider is marked but not retired, we just | |||
482 | * have to take a crack at removing it -- it's no big deal if | |||
483 | * we can't. | |||
484 | */ | |||
485 | for (i = 0; i < fasttrap_provs.fth_nent; i++) { | |||
486 | bucket = &fasttrap_provs.fth_table[i]; | |||
487 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (487)); | |||
488 | fpp = (fasttrap_provider_t **)&bucket->ftb_data; | |||
489 | ||||
490 | while ((fp = *fpp) != NULL((void *)0)) { | |||
491 | if (!fp->ftp_marked) { | |||
492 | fpp = &fp->ftp_next; | |||
493 | continue; | |||
494 | } | |||
495 | ||||
496 | mutex_enter(&fp->ftp_mtx)(void)_sx_xlock(((&fp->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (496)); | |||
497 | ||||
498 | /* | |||
499 | * If this provider has consumers actively | |||
500 | * creating probes (ftp_ccount) or is a USDT | |||
501 | * provider (ftp_mcount), we can't unregister | |||
502 | * or even condense. | |||
503 | */ | |||
504 | if (fp->ftp_ccount != 0 || | |||
505 | fp->ftp_mcount != 0) { | |||
506 | mutex_exit(&fp->ftp_mtx)_sx_xunlock(((&fp->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (506)); | |||
507 | fp->ftp_marked = 0; | |||
508 | continue; | |||
509 | } | |||
510 | ||||
511 | if (!fp->ftp_retired || fp->ftp_rcount != 0) | |||
512 | fp->ftp_marked = 0; | |||
513 | ||||
514 | mutex_exit(&fp->ftp_mtx)_sx_xunlock(((&fp->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (514)); | |||
515 | ||||
516 | /* | |||
517 | * If we successfully unregister this | |||
518 | * provider we can remove it from the hash | |||
519 | * chain and free the memory. If our attempt | |||
520 | * to unregister fails and this is a retired | |||
521 | * provider, increment our flag to try again | |||
522 | * pretty soon. If we've consumed more than | |||
523 | * half of our total permitted number of | |||
524 | * probes call dtrace_condense() to try to | |||
525 | * clean out the unenabled probes. | |||
526 | */ | |||
527 | provid = fp->ftp_provid; | |||
528 | if ((rval = dtrace_unregister(provid)) != 0) { | |||
529 | if (fasttrap_total > fasttrap_max / 2) | |||
530 | (void) dtrace_condense(provid); | |||
531 | ||||
532 | if (rval == EAGAIN35) | |||
533 | fp->ftp_marked = 1; | |||
534 | ||||
535 | later += fp->ftp_marked; | |||
536 | fpp = &fp->ftp_next; | |||
537 | } else { | |||
538 | *fpp = fp->ftp_next; | |||
539 | fasttrap_provider_free(fp); | |||
540 | } | |||
541 | } | |||
542 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (542)); | |||
543 | } | |||
544 | mtx_lock(&fasttrap_cleanup_mtx)__mtx_lock_flags(&((((&fasttrap_cleanup_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (544)); | |||
545 | ||||
546 | /* | |||
547 | * If we were unable to retire a provider, try again after a | |||
548 | * second. This situation can occur in certain circumstances | |||
549 | * where providers cannot be unregistered even though they have | |||
550 | * no probes enabled because of an execution of dtrace -l or | |||
551 | * something similar. | |||
552 | */ | |||
553 | if (later > 0 || fasttrap_cleanup_work || | |||
554 | fasttrap_cleanup_drain) { | |||
555 | mtx_unlock(&fasttrap_cleanup_mtx)__mtx_unlock_flags(&((((&fasttrap_cleanup_mtx))))-> mtx_lock, ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (555)); | |||
556 | pause("ftclean", hz)pause_sbt(("ftclean"), tick_sbt * (hz), 0, 0x0100); | |||
557 | mtx_lock(&fasttrap_cleanup_mtx)__mtx_lock_flags(&((((&fasttrap_cleanup_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (557)); | |||
558 | } else | |||
559 | mtx_sleep(&fasttrap_cleanup_cv, &fasttrap_cleanup_mtx,_sleep((&fasttrap_cleanup_cv), &(&fasttrap_cleanup_mtx )->lock_object, (0), ("ftcl"), tick_sbt * (0), 0, 0x0100) | |||
560 | 0, "ftcl", 0)_sleep((&fasttrap_cleanup_cv), &(&fasttrap_cleanup_mtx )->lock_object, (0), ("ftcl"), tick_sbt * (0), 0, 0x0100); | |||
561 | } | |||
562 | ||||
563 | /* | |||
564 | * Wake up the thread in fasttrap_unload() now that we're done. | |||
565 | */ | |||
566 | wakeup(&fasttrap_cleanup_drain); | |||
567 | mtx_unlock(&fasttrap_cleanup_mtx)__mtx_unlock_flags(&((((&fasttrap_cleanup_mtx))))-> mtx_lock, ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (567)); | |||
568 | ||||
569 | kthread_exit(); | |||
570 | } | |||
571 | ||||
572 | /* | |||
573 | * Activates the asynchronous cleanup mechanism. | |||
574 | */ | |||
575 | static void | |||
576 | fasttrap_pid_cleanup(void) | |||
577 | { | |||
578 | ||||
579 | mtx_lock(&fasttrap_cleanup_mtx)__mtx_lock_flags(&((((&fasttrap_cleanup_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (579)); | |||
580 | if (!fasttrap_cleanup_work) { | |||
581 | fasttrap_cleanup_work = 1; | |||
582 | wakeup(&fasttrap_cleanup_cv); | |||
583 | } | |||
584 | mtx_unlock(&fasttrap_cleanup_mtx)__mtx_unlock_flags(&((((&fasttrap_cleanup_mtx))))-> mtx_lock, ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (584)); | |||
585 | } | |||
586 | ||||
587 | /* | |||
588 | * This is called from cfork() via dtrace_fasttrap_fork(). The child | |||
589 | * process's address space is (roughly) a copy of the parent process's so | |||
590 | * we have to remove all the instrumentation we had previously enabled in the | |||
591 | * parent. | |||
592 | */ | |||
593 | static void | |||
594 | fasttrap_fork(proc_t *p, proc_t *cp) | |||
595 | { | |||
596 | #ifndef illumos | |||
597 | fasttrap_scrblock_t *scrblk; | |||
598 | fasttrap_proc_t *fprc = NULL((void *)0); | |||
599 | #endif | |||
600 | pid_t ppid = p->p_pid; | |||
601 | int i; | |||
602 | ||||
603 | #ifdef illumos | |||
604 | ASSERT(curproc == p)((void)0); | |||
605 | ASSERT(p->p_proc_flag & P_PR_LOCK)((void)0); | |||
606 | #else | |||
607 | PROC_LOCK_ASSERT(p, MA_OWNED)(void)0; | |||
608 | #endif | |||
609 | #ifdef illumos | |||
610 | ASSERT(p->p_dtrace_count > 0)((void)0); | |||
611 | #else | |||
612 | if (p->p_dtrace_helpersp_dtrace->p_dtrace_helpers) { | |||
613 | /* | |||
614 | * dtrace_helpers_duplicate() allocates memory. | |||
615 | */ | |||
616 | _PHOLD(cp)do { (void)0; do { } while (0); (cp)->p_lock++; if (((cp)-> p_flag & 0x10000000) == 0) faultin((cp)); } while (0); | |||
617 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (617)); | |||
618 | PROC_UNLOCK(cp)__mtx_unlock_flags(&((((&(cp)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (618)); | |||
619 | dtrace_helpers_duplicate(p, cp); | |||
620 | PROC_LOCK(cp)__mtx_lock_flags(&((((&(cp)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (620)); | |||
621 | PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (621)); | |||
622 | _PRELE(cp)do { (void)0; do { do { } while (0); } while (0); (--(cp)-> p_lock); if (((cp)->p_flag & 0x02000) && (cp)-> p_lock == 0) wakeup(&(cp)->p_lock); } while (0); | |||
623 | } | |||
624 | /* | |||
625 | * This check is purposely here instead of in kern_fork.c because, | |||
626 | * for legal resons, we cannot include the dtrace_cddl.h header | |||
627 | * inside kern_fork.c and insert if-clause there. | |||
628 | */ | |||
629 | if (p->p_dtrace_countp_dtrace->p_dtrace_count == 0) | |||
630 | return; | |||
631 | #endif | |||
632 | ASSERT(cp->p_dtrace_count == 0)((void)0); | |||
633 | ||||
634 | /* | |||
635 | * This would be simpler and faster if we maintained per-process | |||
636 | * hash tables of enabled tracepoints. It could, however, potentially | |||
637 | * slow down execution of a tracepoint since we'd need to go | |||
638 | * through two levels of indirection. In the future, we should | |||
639 | * consider either maintaining per-process ancillary lists of | |||
640 | * enabled tracepoints or hanging a pointer to a per-process hash | |||
641 | * table of enabled tracepoints off the proc structure. | |||
642 | */ | |||
643 | ||||
644 | /* | |||
645 | * We don't have to worry about the child process disappearing | |||
646 | * because we're in fork(). | |||
647 | */ | |||
648 | #ifdef illumos | |||
649 | mtx_lock_spin(&cp->p_slock)__mtx_lock_spin_flags(&((((&cp->p_slock))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (649)); | |||
650 | sprlock_proc(cp); | |||
651 | mtx_unlock_spin(&cp->p_slock)__mtx_unlock_spin_flags(&((((&cp->p_slock))))-> mtx_lock, ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (651)); | |||
652 | #else | |||
653 | /* | |||
654 | * fasttrap_tracepoint_remove() expects the child process to be | |||
655 | * unlocked and the VM then expects curproc to be unlocked. | |||
656 | */ | |||
657 | _PHOLD(cp)do { (void)0; do { } while (0); (cp)->p_lock++; if (((cp)-> p_flag & 0x10000000) == 0) faultin((cp)); } while (0); | |||
658 | PROC_UNLOCK(cp)__mtx_unlock_flags(&((((&(cp)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (658)); | |||
659 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (659)); | |||
660 | #endif | |||
661 | ||||
662 | /* | |||
663 | * Iterate over every tracepoint looking for ones that belong to the | |||
664 | * parent process, and remove each from the child process. | |||
665 | */ | |||
666 | for (i = 0; i < fasttrap_tpoints.fth_nent; i++) { | |||
667 | fasttrap_tracepoint_t *tp; | |||
668 | fasttrap_bucket_t *bucket = &fasttrap_tpoints.fth_table[i]; | |||
669 | ||||
670 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (670)); | |||
671 | for (tp = bucket->ftb_data; tp != NULL((void *)0); tp = tp->ftt_next) { | |||
672 | if (tp->ftt_pid == ppid && | |||
673 | tp->ftt_proc->ftpc_acount != 0) { | |||
674 | int ret = fasttrap_tracepoint_remove(cp, tp); | |||
675 | ASSERT(ret == 0)((void)0); | |||
676 | ||||
677 | /* | |||
678 | * The count of active providers can only be | |||
679 | * decremented (i.e. to zero) during exec, | |||
680 | * exit, and removal of a meta provider so it | |||
681 | * should be impossible to drop the count | |||
682 | * mid-fork. | |||
683 | */ | |||
684 | ASSERT(tp->ftt_proc->ftpc_acount != 0)((void)0); | |||
685 | #ifndef illumos | |||
686 | fprc = tp->ftt_proc; | |||
687 | #endif | |||
688 | } | |||
689 | } | |||
690 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (690)); | |||
691 | ||||
692 | #ifndef illumos | |||
693 | /* | |||
694 | * Unmap any scratch space inherited from the parent's address | |||
695 | * space. | |||
696 | */ | |||
697 | if (fprc != NULL((void *)0)) { | |||
698 | mutex_enter(&fprc->ftpc_mtx)(void)_sx_xlock(((&fprc->ftpc_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (698)); | |||
699 | LIST_FOREACH(scrblk, &fprc->ftpc_scrblks, ftsb_next)for ((scrblk) = (((&fprc->ftpc_scrblks))->lh_first) ; (scrblk); (scrblk) = (((scrblk))->ftsb_next.le_next)) { | |||
700 | vm_map_remove(&cp->p_vmspace->vm_map, | |||
701 | scrblk->ftsb_addr, | |||
702 | scrblk->ftsb_addr + FASTTRAP_SCRBLOCK_SIZE(1<<12)); | |||
703 | } | |||
704 | mutex_exit(&fprc->ftpc_mtx)_sx_xunlock(((&fprc->ftpc_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (704)); | |||
705 | } | |||
706 | #endif | |||
707 | } | |||
708 | ||||
709 | #ifdef illumos | |||
710 | mutex_enter(&cp->p_lock)(void)_sx_xlock(((&cp->p_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (710)); | |||
711 | sprunlock(cp); | |||
712 | #else | |||
713 | PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (713)); | |||
714 | PROC_LOCK(cp)__mtx_lock_flags(&((((&(cp)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (714)); | |||
715 | _PRELE(cp)do { (void)0; do { do { } while (0); } while (0); (--(cp)-> p_lock); if (((cp)->p_flag & 0x02000) && (cp)-> p_lock == 0) wakeup(&(cp)->p_lock); } while (0); | |||
716 | #endif | |||
717 | } | |||
718 | ||||
719 | /* | |||
720 | * This is called from proc_exit() or from exec_common() if p_dtrace_probes | |||
721 | * is set on the proc structure to indicate that there is a pid provider | |||
722 | * associated with this process. | |||
723 | */ | |||
724 | static void | |||
725 | fasttrap_exec_exit(proc_t *p) | |||
726 | { | |||
727 | #ifndef illumos | |||
728 | struct thread *td; | |||
729 | #endif | |||
730 | ||||
731 | #ifdef illumos | |||
732 | ASSERT(p == curproc)((void)0); | |||
733 | #else | |||
734 | PROC_LOCK_ASSERT(p, MA_OWNED)(void)0; | |||
735 | _PHOLD(p)do { (void)0; do { } while (0); (p)->p_lock++; if (((p)-> p_flag & 0x10000000) == 0) faultin((p)); } while (0); | |||
736 | /* | |||
737 | * Since struct threads may be recycled, we cannot rely on t_dtrace_sscr | |||
738 | * fields to be zeroed by kdtrace_thread_ctor. Thus we must zero it | |||
739 | * ourselves when a process exits. | |||
740 | */ | |||
741 | FOREACH_THREAD_IN_PROC(p, td)for (((td)) = (((&(p)->p_threads))->tqh_first); ((td )); ((td)) = ((((td)))->td_plist.tqe_next)) | |||
742 | td->t_dtrace_sscrtd_dtrace->td_dtrace_sscr = NULL((void *)0); | |||
743 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (743)); | |||
744 | #endif | |||
745 | ||||
746 | /* | |||
747 | * We clean up the pid provider for this process here; user-land | |||
748 | * static probes are handled by the meta-provider remove entry point. | |||
749 | */ | |||
750 | fasttrap_provider_retire(p->p_pid, FASTTRAP_PID_NAME"pid", 0); | |||
751 | #ifndef illumos | |||
752 | if (p->p_dtrace_helpersp_dtrace->p_dtrace_helpers) | |||
753 | dtrace_helpers_destroy(p); | |||
754 | PROC_LOCK(p)__mtx_lock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (754)); | |||
755 | _PRELE(p)do { (void)0; do { do { } while (0); } while (0); (--(p)-> p_lock); if (((p)->p_flag & 0x02000) && (p)-> p_lock == 0) wakeup(&(p)->p_lock); } while (0); | |||
756 | #endif | |||
757 | } | |||
758 | ||||
759 | ||||
760 | /*ARGSUSED*/ | |||
761 | static void | |||
762 | fasttrap_pid_provide(void *arg, dtrace_probedesc_t *desc) | |||
763 | { | |||
764 | /* | |||
765 | * There are no "default" pid probes. | |||
766 | */ | |||
767 | } | |||
768 | ||||
769 | static int | |||
770 | fasttrap_tracepoint_enable(proc_t *p, fasttrap_probe_t *probe, uint_t index) | |||
771 | { | |||
772 | fasttrap_tracepoint_t *tp, *new_tp = NULL((void *)0); | |||
773 | fasttrap_bucket_t *bucket; | |||
774 | fasttrap_id_t *id; | |||
775 | pid_t pid; | |||
776 | uintptr_t pc; | |||
777 | ||||
778 | ASSERT(index < probe->ftp_ntps)((void)0); | |||
779 | ||||
780 | pid = probe->ftp_pid; | |||
781 | pc = probe->ftp_tps[index].fit_tp->ftt_pc; | |||
782 | id = &probe->ftp_tps[index].fit_id; | |||
783 | ||||
784 | ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid)((void)0); | |||
785 | ||||
786 | #ifdef illumos | |||
787 | ASSERT(!(p->p_flag & SVFORK))((void)0); | |||
788 | #endif | |||
789 | ||||
790 | /* | |||
791 | * Before we make any modifications, make sure we've imposed a barrier | |||
792 | * on the generation in which this probe was last modified. | |||
793 | */ | |||
794 | fasttrap_mod_barrier(probe->ftp_gen); | |||
795 | ||||
796 | bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)(((pc) / sizeof (fasttrap_instr_t) + (pid)) & fasttrap_tpoints .fth_mask)]; | |||
797 | ||||
798 | /* | |||
799 | * If the tracepoint has already been enabled, just add our id to the | |||
800 | * list of interested probes. This may be our second time through | |||
801 | * this path in which case we'll have constructed the tracepoint we'd | |||
802 | * like to install. If we can't find a match, and have an allocated | |||
803 | * tracepoint ready to go, enable that one now. | |||
804 | * | |||
805 | * A tracepoint whose process is defunct is also considered defunct. | |||
806 | */ | |||
807 | again: | |||
808 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (808)); | |||
809 | for (tp = bucket->ftb_data; tp != NULL((void *)0); tp = tp->ftt_next) { | |||
810 | /* | |||
811 | * Note that it's safe to access the active count on the | |||
812 | * associated proc structure because we know that at least one | |||
813 | * provider (this one) will still be around throughout this | |||
814 | * operation. | |||
815 | */ | |||
816 | if (tp->ftt_pid != pid || tp->ftt_pc != pc || | |||
817 | tp->ftt_proc->ftpc_acount == 0) | |||
818 | continue; | |||
819 | ||||
820 | /* | |||
821 | * Now that we've found a matching tracepoint, it would be | |||
822 | * a decent idea to confirm that the tracepoint is still | |||
823 | * enabled and the trap instruction hasn't been overwritten. | |||
824 | * Since this is a little hairy, we'll punt for now. | |||
825 | */ | |||
826 | ||||
827 | /* | |||
828 | * This can't be the first interested probe. We don't have | |||
829 | * to worry about another thread being in the midst of | |||
830 | * deleting this tracepoint (which would be the only valid | |||
831 | * reason for a tracepoint to have no interested probes) | |||
832 | * since we're holding P_PR_LOCK for this process. | |||
833 | */ | |||
834 | ASSERT(tp->ftt_ids != NULL || tp->ftt_retids != NULL)((void)0); | |||
835 | ||||
836 | switch (id->fti_ptype) { | |||
837 | case DTFTP_ENTRY: | |||
838 | case DTFTP_OFFSETS: | |||
839 | case DTFTP_IS_ENABLED: | |||
840 | id->fti_next = tp->ftt_ids; | |||
841 | membar_producer(); | |||
842 | tp->ftt_ids = id; | |||
843 | membar_producer(); | |||
844 | break; | |||
845 | ||||
846 | case DTFTP_RETURN: | |||
847 | case DTFTP_POST_OFFSETS: | |||
848 | id->fti_next = tp->ftt_retids; | |||
849 | membar_producer(); | |||
850 | tp->ftt_retids = id; | |||
851 | membar_producer(); | |||
852 | break; | |||
853 | ||||
854 | default: | |||
855 | ASSERT(0)((void)0); | |||
856 | } | |||
857 | ||||
858 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (858)); | |||
859 | ||||
860 | if (new_tp != NULL((void *)0)) { | |||
861 | new_tp->ftt_ids = NULL((void *)0); | |||
862 | new_tp->ftt_retids = NULL((void *)0); | |||
863 | } | |||
864 | ||||
865 | return (0); | |||
866 | } | |||
867 | ||||
868 | /* | |||
869 | * If we have a good tracepoint ready to go, install it now while | |||
870 | * we have the lock held and no one can screw with us. | |||
871 | */ | |||
872 | if (new_tp != NULL((void *)0)) { | |||
873 | int rc = 0; | |||
874 | ||||
875 | new_tp->ftt_next = bucket->ftb_data; | |||
876 | membar_producer(); | |||
877 | bucket->ftb_data = new_tp; | |||
878 | membar_producer(); | |||
879 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (879)); | |||
880 | ||||
881 | /* | |||
882 | * Activate the tracepoint in the ISA-specific manner. | |||
883 | * If this fails, we need to report the failure, but | |||
884 | * indicate that this tracepoint must still be disabled | |||
885 | * by calling fasttrap_tracepoint_disable(). | |||
886 | */ | |||
887 | if (fasttrap_tracepoint_install(p, new_tp) != 0) | |||
888 | rc = FASTTRAP_ENABLE_PARTIAL2; | |||
889 | ||||
890 | /* | |||
891 | * Increment the count of the number of tracepoints active in | |||
892 | * the victim process. | |||
893 | */ | |||
894 | #ifdef illumos | |||
895 | ASSERT(p->p_proc_flag & P_PR_LOCK)((void)0); | |||
896 | #endif | |||
897 | p->p_dtrace_countp_dtrace->p_dtrace_count++; | |||
898 | ||||
899 | return (rc); | |||
900 | } | |||
901 | ||||
902 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (902)); | |||
903 | ||||
904 | /* | |||
905 | * Initialize the tracepoint that's been preallocated with the probe. | |||
906 | */ | |||
907 | new_tp = probe->ftp_tps[index].fit_tp; | |||
908 | ||||
909 | ASSERT(new_tp->ftt_pid == pid)((void)0); | |||
910 | ASSERT(new_tp->ftt_pc == pc)((void)0); | |||
911 | ASSERT(new_tp->ftt_proc == probe->ftp_prov->ftp_proc)((void)0); | |||
912 | ASSERT(new_tp->ftt_ids == NULL)((void)0); | |||
913 | ASSERT(new_tp->ftt_retids == NULL)((void)0); | |||
914 | ||||
915 | switch (id->fti_ptype) { | |||
916 | case DTFTP_ENTRY: | |||
917 | case DTFTP_OFFSETS: | |||
918 | case DTFTP_IS_ENABLED: | |||
919 | id->fti_next = NULL((void *)0); | |||
920 | new_tp->ftt_ids = id; | |||
921 | break; | |||
922 | ||||
923 | case DTFTP_RETURN: | |||
924 | case DTFTP_POST_OFFSETS: | |||
925 | id->fti_next = NULL((void *)0); | |||
926 | new_tp->ftt_retids = id; | |||
927 | break; | |||
928 | ||||
929 | default: | |||
930 | ASSERT(0)((void)0); | |||
931 | } | |||
932 | ||||
933 | /* | |||
934 | * If the ISA-dependent initialization goes to plan, go back to the | |||
935 | * beginning and try to install this freshly made tracepoint. | |||
936 | */ | |||
937 | if (fasttrap_tracepoint_init(p, new_tp, pc, id->fti_ptype) == 0) | |||
938 | goto again; | |||
939 | ||||
940 | new_tp->ftt_ids = NULL((void *)0); | |||
941 | new_tp->ftt_retids = NULL((void *)0); | |||
942 | ||||
943 | return (FASTTRAP_ENABLE_FAIL1); | |||
944 | } | |||
945 | ||||
946 | static void | |||
947 | fasttrap_tracepoint_disable(proc_t *p, fasttrap_probe_t *probe, uint_t index) | |||
948 | { | |||
949 | fasttrap_bucket_t *bucket; | |||
950 | fasttrap_provider_t *provider = probe->ftp_prov; | |||
951 | fasttrap_tracepoint_t **pp, *tp; | |||
952 | fasttrap_id_t *id, **idp = NULL((void *)0); | |||
953 | pid_t pid; | |||
954 | uintptr_t pc; | |||
955 | ||||
956 | ASSERT(index < probe->ftp_ntps)((void)0); | |||
957 | ||||
958 | pid = probe->ftp_pid; | |||
959 | pc = probe->ftp_tps[index].fit_tp->ftt_pc; | |||
960 | id = &probe->ftp_tps[index].fit_id; | |||
961 | ||||
962 | ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid)((void)0); | |||
963 | ||||
964 | /* | |||
965 | * Find the tracepoint and make sure that our id is one of the | |||
966 | * ones registered with it. | |||
967 | */ | |||
968 | bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)(((pc) / sizeof (fasttrap_instr_t) + (pid)) & fasttrap_tpoints .fth_mask)]; | |||
969 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (969)); | |||
970 | for (tp = bucket->ftb_data; tp != NULL((void *)0); tp = tp->ftt_next) { | |||
971 | if (tp->ftt_pid == pid && tp->ftt_pc == pc && | |||
972 | tp->ftt_proc == provider->ftp_proc) | |||
973 | break; | |||
974 | } | |||
975 | ||||
976 | /* | |||
977 | * If we somehow lost this tracepoint, we're in a world of hurt. | |||
978 | */ | |||
979 | ASSERT(tp != NULL)((void)0); | |||
980 | ||||
981 | switch (id->fti_ptype) { | |||
982 | case DTFTP_ENTRY: | |||
983 | case DTFTP_OFFSETS: | |||
984 | case DTFTP_IS_ENABLED: | |||
985 | ASSERT(tp->ftt_ids != NULL)((void)0); | |||
986 | idp = &tp->ftt_ids; | |||
987 | break; | |||
988 | ||||
989 | case DTFTP_RETURN: | |||
990 | case DTFTP_POST_OFFSETS: | |||
991 | ASSERT(tp->ftt_retids != NULL)((void)0); | |||
992 | idp = &tp->ftt_retids; | |||
993 | break; | |||
994 | ||||
995 | default: | |||
996 | ASSERT(0)((void)0); | |||
997 | } | |||
998 | ||||
999 | while ((*idp)->fti_probe != probe) { | |||
1000 | idp = &(*idp)->fti_next; | |||
1001 | ASSERT(*idp != NULL)((void)0); | |||
1002 | } | |||
1003 | ||||
1004 | id = *idp; | |||
1005 | *idp = id->fti_next; | |||
1006 | membar_producer(); | |||
1007 | ||||
1008 | ASSERT(id->fti_probe == probe)((void)0); | |||
1009 | ||||
1010 | /* | |||
1011 | * If there are other registered enablings of this tracepoint, we're | |||
1012 | * all done, but if this was the last probe assocated with this | |||
1013 | * this tracepoint, we need to remove and free it. | |||
1014 | */ | |||
1015 | if (tp->ftt_ids != NULL((void *)0) || tp->ftt_retids != NULL((void *)0)) { | |||
1016 | ||||
1017 | /* | |||
1018 | * If the current probe's tracepoint is in use, swap it | |||
1019 | * for an unused tracepoint. | |||
1020 | */ | |||
1021 | if (tp == probe->ftp_tps[index].fit_tp) { | |||
1022 | fasttrap_probe_t *tmp_probe; | |||
1023 | fasttrap_tracepoint_t **tmp_tp; | |||
1024 | uint_t tmp_index; | |||
1025 | ||||
1026 | if (tp->ftt_ids != NULL((void *)0)) { | |||
1027 | tmp_probe = tp->ftt_ids->fti_probe; | |||
1028 | /* LINTED - alignment */ | |||
1029 | tmp_index = FASTTRAP_ID_INDEX(tp->ftt_ids)((fasttrap_id_tp_t *)(((char *)(tp->ftt_ids) - __builtin_offsetof (fasttrap_id_tp_t, fit_id))) - &(tp->ftt_ids)->fti_probe ->ftp_tps[0]); | |||
1030 | tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp; | |||
1031 | } else { | |||
1032 | tmp_probe = tp->ftt_retids->fti_probe; | |||
1033 | /* LINTED - alignment */ | |||
1034 | tmp_index = FASTTRAP_ID_INDEX(tp->ftt_retids)((fasttrap_id_tp_t *)(((char *)(tp->ftt_retids) - __builtin_offsetof (fasttrap_id_tp_t, fit_id))) - &(tp->ftt_retids)->fti_probe ->ftp_tps[0]); | |||
1035 | tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp; | |||
1036 | } | |||
1037 | ||||
1038 | ASSERT(*tmp_tp != NULL)((void)0); | |||
1039 | ASSERT(*tmp_tp != probe->ftp_tps[index].fit_tp)((void)0); | |||
1040 | ASSERT((*tmp_tp)->ftt_ids == NULL)((void)0); | |||
1041 | ASSERT((*tmp_tp)->ftt_retids == NULL)((void)0); | |||
1042 | ||||
1043 | probe->ftp_tps[index].fit_tp = *tmp_tp; | |||
1044 | *tmp_tp = tp; | |||
1045 | } | |||
1046 | ||||
1047 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1047)); | |||
1048 | ||||
1049 | /* | |||
1050 | * Tag the modified probe with the generation in which it was | |||
1051 | * changed. | |||
1052 | */ | |||
1053 | probe->ftp_gen = fasttrap_mod_gen; | |||
1054 | return; | |||
1055 | } | |||
1056 | ||||
1057 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1057)); | |||
1058 | ||||
1059 | /* | |||
1060 | * We can't safely remove the tracepoint from the set of active | |||
1061 | * tracepoints until we've actually removed the fasttrap instruction | |||
1062 | * from the process's text. We can, however, operate on this | |||
1063 | * tracepoint secure in the knowledge that no other thread is going to | |||
1064 | * be looking at it since we hold P_PR_LOCK on the process if it's | |||
1065 | * live or we hold the provider lock on the process if it's dead and | |||
1066 | * gone. | |||
1067 | */ | |||
1068 | ||||
1069 | /* | |||
1070 | * We only need to remove the actual instruction if we're looking | |||
1071 | * at an existing process | |||
1072 | */ | |||
1073 | if (p != NULL((void *)0)) { | |||
1074 | /* | |||
1075 | * If we fail to restore the instruction we need to kill | |||
1076 | * this process since it's in a completely unrecoverable | |||
1077 | * state. | |||
1078 | */ | |||
1079 | if (fasttrap_tracepoint_remove(p, tp) != 0) | |||
1080 | fasttrap_sigtrap(p, NULL((void *)0), pc); | |||
1081 | ||||
1082 | /* | |||
1083 | * Decrement the count of the number of tracepoints active | |||
1084 | * in the victim process. | |||
1085 | */ | |||
1086 | #ifdef illumos | |||
1087 | ASSERT(p->p_proc_flag & P_PR_LOCK)((void)0); | |||
1088 | #endif | |||
1089 | p->p_dtrace_countp_dtrace->p_dtrace_count--; | |||
1090 | } | |||
1091 | ||||
1092 | /* | |||
1093 | * Remove the probe from the hash table of active tracepoints. | |||
1094 | */ | |||
1095 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1095)); | |||
1096 | pp = (fasttrap_tracepoint_t **)&bucket->ftb_data; | |||
1097 | ASSERT(*pp != NULL)((void)0); | |||
1098 | while (*pp != tp) { | |||
1099 | pp = &(*pp)->ftt_next; | |||
1100 | ASSERT(*pp != NULL)((void)0); | |||
1101 | } | |||
1102 | ||||
1103 | *pp = tp->ftt_next; | |||
1104 | membar_producer(); | |||
1105 | ||||
1106 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1106)); | |||
1107 | ||||
1108 | /* | |||
1109 | * Tag the modified probe with the generation in which it was changed. | |||
1110 | */ | |||
1111 | probe->ftp_gen = fasttrap_mod_gen; | |||
1112 | } | |||
1113 | ||||
1114 | static void | |||
1115 | fasttrap_enable_callbacks(void) | |||
1116 | { | |||
1117 | /* | |||
1118 | * We don't have to play the rw lock game here because we're | |||
1119 | * providing something rather than taking something away -- | |||
1120 | * we can be sure that no threads have tried to follow this | |||
1121 | * function pointer yet. | |||
1122 | */ | |||
1123 | mutex_enter(&fasttrap_count_mtx)(void)_sx_xlock(((&fasttrap_count_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1123)); | |||
1124 | if (fasttrap_pid_count == 0) { | |||
1125 | ASSERT(dtrace_pid_probe_ptr == NULL)((void)0); | |||
1126 | ASSERT(dtrace_return_probe_ptr == NULL)((void)0); | |||
1127 | dtrace_pid_probe_ptr = &fasttrap_pid_probe; | |||
1128 | dtrace_return_probe_ptr = &fasttrap_return_probe; | |||
1129 | } | |||
1130 | ASSERT(dtrace_pid_probe_ptr == &fasttrap_pid_probe)((void)0); | |||
1131 | ASSERT(dtrace_return_probe_ptr == &fasttrap_return_probe)((void)0); | |||
1132 | fasttrap_pid_count++; | |||
1133 | mutex_exit(&fasttrap_count_mtx)_sx_xunlock(((&fasttrap_count_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1133)); | |||
1134 | } | |||
1135 | ||||
1136 | static void | |||
1137 | fasttrap_disable_callbacks(void) | |||
1138 | { | |||
1139 | #ifdef illumos | |||
1140 | ASSERT(MUTEX_HELD(&cpu_lock))((void)0); | |||
1141 | #endif | |||
1142 | ||||
1143 | ||||
1144 | mutex_enter(&fasttrap_count_mtx)(void)_sx_xlock(((&fasttrap_count_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1144)); | |||
1145 | ASSERT(fasttrap_pid_count > 0)((void)0); | |||
1146 | fasttrap_pid_count--; | |||
1147 | if (fasttrap_pid_count == 0) { | |||
1148 | #ifdef illumos | |||
1149 | cpu_tsolaris_cpu_t *cur, *cpu = CPU__extension__ ({ __typeof(((struct pcpu *)0)->pc_cpuid) __res ; struct __s { u_char __b[(((sizeof(__typeof(((struct pcpu *) 0)->pc_cpuid)))<(8))?(sizeof(__typeof(((struct pcpu *)0 )->pc_cpuid))):(8))]; } __s; if (sizeof(__res) == 1 || sizeof (__res) == 2 || sizeof(__res) == 4 || sizeof(__res) == 8) { __asm volatile("mov %%gs:%1,%0" : "=r" (__s) : "m" (*(struct __s * )(__builtin_offsetof(struct pcpu, pc_cpuid)))); *(struct __s * )(void *)&__res = __s; } else { __res = *__extension__ ({ __typeof(((struct pcpu *)0)->pc_cpuid) *__p; __asm volatile ("movq %%gs:%1,%0; addq %2,%0" : "=r" (__p) : "m" (*(struct pcpu *)(__builtin_offsetof(struct pcpu, pc_prvspace))), "i" (__builtin_offsetof (struct pcpu, pc_cpuid))); __p; }); } __res; }); | |||
1150 | ||||
1151 | for (cur = cpu->cpu_next_onln; cur != cpu; | |||
1152 | cur = cur->cpu_next_onln) { | |||
1153 | rw_enter(&cur->cpu_ft_lock, RW_WRITER); | |||
1154 | } | |||
1155 | #endif | |||
1156 | dtrace_pid_probe_ptr = NULL((void *)0); | |||
1157 | dtrace_return_probe_ptr = NULL((void *)0); | |||
1158 | #ifdef illumos | |||
1159 | for (cur = cpu->cpu_next_onln; cur != cpu; | |||
1160 | cur = cur->cpu_next_onln) { | |||
1161 | rw_exit(&cur->cpu_ft_lock); | |||
1162 | } | |||
1163 | #endif | |||
1164 | } | |||
1165 | mutex_exit(&fasttrap_count_mtx)_sx_xunlock(((&fasttrap_count_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1165)); | |||
1166 | } | |||
1167 | ||||
1168 | /*ARGSUSED*/ | |||
1169 | static void | |||
1170 | fasttrap_pid_enable(void *arg, dtrace_id_t id, void *parg) | |||
1171 | { | |||
1172 | fasttrap_probe_t *probe = parg; | |||
1173 | proc_t *p = NULL((void *)0); | |||
1174 | int i, rc; | |||
1175 | ||||
1176 | ASSERT(probe != NULL)((void)0); | |||
1177 | ASSERT(!probe->ftp_enabled)((void)0); | |||
1178 | ASSERT(id == probe->ftp_id)((void)0); | |||
1179 | #ifdef illumos | |||
1180 | ASSERT(MUTEX_HELD(&cpu_lock))((void)0); | |||
1181 | #endif | |||
1182 | ||||
1183 | /* | |||
1184 | * Increment the count of enabled probes on this probe's provider; | |||
1185 | * the provider can't go away while the probe still exists. We | |||
1186 | * must increment this even if we aren't able to properly enable | |||
1187 | * this probe. | |||
1188 | */ | |||
1189 | mutex_enter(&probe->ftp_prov->ftp_mtx)(void)_sx_xlock(((&probe->ftp_prov->ftp_mtx)), 0, ( "/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1189)); | |||
1190 | probe->ftp_prov->ftp_rcount++; | |||
1191 | mutex_exit(&probe->ftp_prov->ftp_mtx)_sx_xunlock(((&probe->ftp_prov->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1191)); | |||
1192 | ||||
1193 | /* | |||
1194 | * If this probe's provider is retired (meaning it was valid in a | |||
1195 | * previously exec'ed incarnation of this address space), bail out. The | |||
1196 | * provider can't go away while we're in this code path. | |||
1197 | */ | |||
1198 | if (probe->ftp_prov->ftp_retired) | |||
1199 | return; | |||
1200 | ||||
1201 | /* | |||
1202 | * If we can't find the process, it may be that we're in the context of | |||
1203 | * a fork in which the traced process is being born and we're copying | |||
1204 | * USDT probes. Otherwise, the process is gone so bail. | |||
1205 | */ | |||
1206 | #ifdef illumos | |||
1207 | if ((p = sprlock(probe->ftp_pid)) == NULL((void *)0)) { | |||
1208 | if ((curproc((__curthread())->td_proc)->p_flag & SFORKING) == 0) | |||
1209 | return; | |||
1210 | ||||
1211 | mutex_enter(&pidlock)(void)_sx_xlock(((&pidlock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1211)); | |||
1212 | p = prfind(probe->ftp_pid); | |||
1213 | ||||
1214 | if (p == NULL((void *)0)) { | |||
1215 | /* | |||
1216 | * So it's not that the target process is being born, | |||
1217 | * it's that it isn't there at all (and we simply | |||
1218 | * happen to be forking). Anyway, we know that the | |||
1219 | * target is definitely gone, so bail out. | |||
1220 | */ | |||
1221 | mutex_exit(&pidlock)_sx_xunlock(((&pidlock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1221)); | |||
1222 | return (0); | |||
1223 | } | |||
1224 | ||||
1225 | /* | |||
1226 | * Confirm that curproc is indeed forking the process in which | |||
1227 | * we're trying to enable probes. | |||
1228 | */ | |||
1229 | ASSERT(p->p_parent == curproc)((void)0); | |||
1230 | ASSERT(p->p_stat == SIDL)((void)0); | |||
1231 | ||||
1232 | mutex_enter(&p->p_lock)(void)_sx_xlock(((&p->p_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1232)); | |||
1233 | mutex_exit(&pidlock)_sx_xunlock(((&pidlock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1233)); | |||
1234 | ||||
1235 | sprlock_proc(p); | |||
1236 | } | |||
1237 | ||||
1238 | ASSERT(!(p->p_flag & SVFORK))((void)0); | |||
1239 | mutex_exit(&p->p_lock)_sx_xunlock(((&p->p_lock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1239)); | |||
1240 | #else | |||
1241 | if ((p = pfind(probe->ftp_pid)) == NULL((void *)0)) | |||
1242 | return; | |||
1243 | #endif | |||
1244 | ||||
1245 | /* | |||
1246 | * We have to enable the trap entry point before any user threads have | |||
1247 | * the chance to execute the trap instruction we're about to place | |||
1248 | * in their process's text. | |||
1249 | */ | |||
1250 | #ifdef __FreeBSD__11 | |||
1251 | /* | |||
1252 | * pfind() returns a locked process. | |||
1253 | */ | |||
1254 | _PHOLD(p)do { (void)0; do { } while (0); (p)->p_lock++; if (((p)-> p_flag & 0x10000000) == 0) faultin((p)); } while (0); | |||
1255 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1255)); | |||
1256 | #endif | |||
1257 | fasttrap_enable_callbacks(); | |||
1258 | ||||
1259 | /* | |||
1260 | * Enable all the tracepoints and add this probe's id to each | |||
1261 | * tracepoint's list of active probes. | |||
1262 | */ | |||
1263 | for (i = 0; i < probe->ftp_ntps; i++) { | |||
1264 | if ((rc = fasttrap_tracepoint_enable(p, probe, i)) != 0) { | |||
1265 | /* | |||
1266 | * If enabling the tracepoint failed completely, | |||
1267 | * we don't have to disable it; if the failure | |||
1268 | * was only partial we must disable it. | |||
1269 | */ | |||
1270 | if (rc == FASTTRAP_ENABLE_FAIL1) | |||
1271 | i--; | |||
1272 | else | |||
1273 | ASSERT(rc == FASTTRAP_ENABLE_PARTIAL)((void)0); | |||
1274 | ||||
1275 | /* | |||
1276 | * Back up and pull out all the tracepoints we've | |||
1277 | * created so far for this probe. | |||
1278 | */ | |||
1279 | while (i >= 0) { | |||
1280 | fasttrap_tracepoint_disable(p, probe, i); | |||
1281 | i--; | |||
1282 | } | |||
1283 | ||||
1284 | #ifdef illumos | |||
1285 | mutex_enter(&p->p_lock)(void)_sx_xlock(((&p->p_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1285)); | |||
1286 | sprunlock(p); | |||
1287 | #else | |||
1288 | PRELE(p)do { __mtx_lock_flags(&((((&((p))->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1288)); do { (void)0; do { do { } while (0); } while (0); (--((p))->p_lock); if ((((p))->p_flag & 0x02000) && ((p))->p_lock == 0) wakeup(&((p))->p_lock); } while (0); __mtx_unlock_flags(&((((&((p))->p_mtx))))-> mtx_lock, ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1288)); } while (0); | |||
1289 | #endif | |||
1290 | ||||
1291 | /* | |||
1292 | * Since we're not actually enabling this probe, | |||
1293 | * drop our reference on the trap table entry. | |||
1294 | */ | |||
1295 | fasttrap_disable_callbacks(); | |||
1296 | return; | |||
1297 | } | |||
1298 | } | |||
1299 | #ifdef illumos | |||
1300 | mutex_enter(&p->p_lock)(void)_sx_xlock(((&p->p_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1300)); | |||
1301 | sprunlock(p); | |||
1302 | #else | |||
1303 | PRELE(p)do { __mtx_lock_flags(&((((&((p))->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1303)); do { (void)0; do { do { } while (0); } while (0); (--((p))->p_lock); if ((((p))->p_flag & 0x02000) && ((p))->p_lock == 0) wakeup(&((p))->p_lock); } while (0); __mtx_unlock_flags(&((((&((p))->p_mtx))))-> mtx_lock, ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1303)); } while (0); | |||
1304 | #endif | |||
1305 | ||||
1306 | probe->ftp_enabled = 1; | |||
1307 | } | |||
1308 | ||||
1309 | /*ARGSUSED*/ | |||
1310 | static void | |||
1311 | fasttrap_pid_disable(void *arg, dtrace_id_t id, void *parg) | |||
1312 | { | |||
1313 | fasttrap_probe_t *probe = parg; | |||
1314 | fasttrap_provider_t *provider = probe->ftp_prov; | |||
1315 | proc_t *p; | |||
1316 | int i, whack = 0; | |||
1317 | ||||
1318 | ASSERT(id == probe->ftp_id)((void)0); | |||
1319 | ||||
1320 | mutex_enter(&provider->ftp_mtx)(void)_sx_xlock(((&provider->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1320)); | |||
1321 | ||||
1322 | /* | |||
1323 | * We won't be able to acquire a /proc-esque lock on the process | |||
1324 | * iff the process is dead and gone. In this case, we rely on the | |||
1325 | * provider lock as a point of mutual exclusion to prevent other | |||
1326 | * DTrace consumers from disabling this probe. | |||
1327 | */ | |||
1328 | if ((p = pfind(probe->ftp_pid)) != NULL((void *)0)) { | |||
1329 | #ifdef __FreeBSD__11 | |||
1330 | if (p->p_flag & P_WEXIT0x02000) { | |||
1331 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1331)); | |||
1332 | p = NULL((void *)0); | |||
1333 | } else { | |||
1334 | _PHOLD(p)do { (void)0; do { } while (0); (p)->p_lock++; if (((p)-> p_flag & 0x10000000) == 0) faultin((p)); } while (0); | |||
1335 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1335)); | |||
1336 | } | |||
1337 | #endif | |||
1338 | } | |||
1339 | ||||
1340 | /* | |||
1341 | * Disable all the associated tracepoints (for fully enabled probes). | |||
1342 | */ | |||
1343 | if (probe->ftp_enabled) { | |||
1344 | for (i = 0; i < probe->ftp_ntps; i++) { | |||
1345 | fasttrap_tracepoint_disable(p, probe, i); | |||
1346 | } | |||
1347 | } | |||
1348 | ||||
1349 | ASSERT(provider->ftp_rcount > 0)((void)0); | |||
1350 | provider->ftp_rcount--; | |||
1351 | ||||
1352 | if (p != NULL((void *)0)) { | |||
1353 | /* | |||
1354 | * Even though we may not be able to remove it entirely, we | |||
1355 | * mark this retired provider to get a chance to remove some | |||
1356 | * of the associated probes. | |||
1357 | */ | |||
1358 | if (provider->ftp_retired && !provider->ftp_marked) | |||
1359 | whack = provider->ftp_marked = 1; | |||
1360 | mutex_exit(&provider->ftp_mtx)_sx_xunlock(((&provider->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1360)); | |||
1361 | } else { | |||
1362 | /* | |||
1363 | * If the process is dead, we're just waiting for the | |||
1364 | * last probe to be disabled to be able to free it. | |||
1365 | */ | |||
1366 | if (provider->ftp_rcount == 0 && !provider->ftp_marked) | |||
1367 | whack = provider->ftp_marked = 1; | |||
1368 | mutex_exit(&provider->ftp_mtx)_sx_xunlock(((&provider->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1368)); | |||
1369 | } | |||
1370 | ||||
1371 | if (whack) | |||
1372 | fasttrap_pid_cleanup(); | |||
1373 | ||||
1374 | #ifdef __FreeBSD__11 | |||
1375 | if (p != NULL((void *)0)) | |||
1376 | PRELE(p)do { __mtx_lock_flags(&((((&((p))->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1376)); do { (void)0; do { do { } while (0); } while (0); (--((p))->p_lock); if ((((p))->p_flag & 0x02000) && ((p))->p_lock == 0) wakeup(&((p))->p_lock); } while (0); __mtx_unlock_flags(&((((&((p))->p_mtx))))-> mtx_lock, ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1376)); } while (0); | |||
1377 | #endif | |||
1378 | if (!probe->ftp_enabled) | |||
1379 | return; | |||
1380 | ||||
1381 | probe->ftp_enabled = 0; | |||
1382 | ||||
1383 | #ifdef illumos | |||
1384 | ASSERT(MUTEX_HELD(&cpu_lock))((void)0); | |||
1385 | #endif | |||
1386 | fasttrap_disable_callbacks(); | |||
1387 | } | |||
1388 | ||||
1389 | /*ARGSUSED*/ | |||
1390 | static void | |||
1391 | fasttrap_pid_getargdesc(void *arg, dtrace_id_t id, void *parg, | |||
1392 | dtrace_argdesc_t *desc) | |||
1393 | { | |||
1394 | fasttrap_probe_t *probe = parg; | |||
1395 | char *str; | |||
1396 | int i, ndx; | |||
1397 | ||||
1398 | desc->dtargd_native[0] = '\0'; | |||
1399 | desc->dtargd_xlate[0] = '\0'; | |||
1400 | ||||
1401 | if (probe->ftp_prov->ftp_retired != 0 || | |||
1402 | desc->dtargd_ndx >= probe->ftp_nargs) { | |||
1403 | desc->dtargd_ndx = DTRACE_ARGNONE-1; | |||
1404 | return; | |||
1405 | } | |||
1406 | ||||
1407 | ndx = (probe->ftp_argmap != NULL((void *)0)) ? | |||
1408 | probe->ftp_argmap[desc->dtargd_ndx] : desc->dtargd_ndx; | |||
1409 | ||||
1410 | str = probe->ftp_ntypes; | |||
1411 | for (i = 0; i < ndx; i++) { | |||
1412 | str += strlen(str) + 1; | |||
1413 | } | |||
1414 | ||||
1415 | ASSERT(strlen(str + 1) < sizeof (desc->dtargd_native))((void)0); | |||
1416 | (void) strcpy(desc->dtargd_native, str); | |||
1417 | ||||
1418 | if (probe->ftp_xtypes == NULL((void *)0)) | |||
1419 | return; | |||
1420 | ||||
1421 | str = probe->ftp_xtypes; | |||
1422 | for (i = 0; i < desc->dtargd_ndx; i++) { | |||
1423 | str += strlen(str) + 1; | |||
1424 | } | |||
1425 | ||||
1426 | ASSERT(strlen(str + 1) < sizeof (desc->dtargd_xlate))((void)0); | |||
1427 | (void) strcpy(desc->dtargd_xlate, str); | |||
1428 | } | |||
1429 | ||||
1430 | /*ARGSUSED*/ | |||
1431 | static void | |||
1432 | fasttrap_pid_destroy(void *arg, dtrace_id_t id, void *parg) | |||
1433 | { | |||
1434 | fasttrap_probe_t *probe = parg; | |||
1435 | int i; | |||
1436 | size_t size; | |||
1437 | ||||
1438 | ASSERT(probe != NULL)((void)0); | |||
1439 | ASSERT(!probe->ftp_enabled)((void)0); | |||
1440 | ASSERT(fasttrap_total >= probe->ftp_ntps)((void)0); | |||
1441 | ||||
1442 | atomic_add_32atomic_add_int(&fasttrap_total, -probe->ftp_ntps); | |||
1443 | size = offsetof(fasttrap_probe_t, ftp_tps[probe->ftp_ntps])__builtin_offsetof(fasttrap_probe_t, ftp_tps[probe->ftp_ntps ]); | |||
1444 | ||||
1445 | if (probe->ftp_gen + 1 >= fasttrap_mod_gen) | |||
1446 | fasttrap_mod_barrier(probe->ftp_gen); | |||
1447 | ||||
1448 | for (i = 0; i < probe->ftp_ntps; i++) { | |||
1449 | kmem_free(probe->ftp_tps[i].fit_tp,zfs_kmem_free((probe->ftp_tps[i].fit_tp), (sizeof (fasttrap_tracepoint_t ))) | |||
1450 | sizeof (fasttrap_tracepoint_t))zfs_kmem_free((probe->ftp_tps[i].fit_tp), (sizeof (fasttrap_tracepoint_t ))); | |||
1451 | } | |||
1452 | ||||
1453 | kmem_free(probe, size)zfs_kmem_free((probe), (size)); | |||
1454 | } | |||
1455 | ||||
1456 | ||||
1457 | static const dtrace_pattr_t pid_attr = { | |||
1458 | { DTRACE_STABILITY_EVOLVING5, DTRACE_STABILITY_EVOLVING5, DTRACE_CLASS_ISA4 }, | |||
1459 | { DTRACE_STABILITY_PRIVATE1, DTRACE_STABILITY_PRIVATE1, DTRACE_CLASS_UNKNOWN0 }, | |||
1460 | { DTRACE_STABILITY_PRIVATE1, DTRACE_STABILITY_PRIVATE1, DTRACE_CLASS_UNKNOWN0 }, | |||
1461 | { DTRACE_STABILITY_EVOLVING5, DTRACE_STABILITY_EVOLVING5, DTRACE_CLASS_ISA4 }, | |||
1462 | { DTRACE_STABILITY_PRIVATE1, DTRACE_STABILITY_PRIVATE1, DTRACE_CLASS_UNKNOWN0 }, | |||
1463 | }; | |||
1464 | ||||
1465 | static dtrace_pops_t pid_pops = { | |||
1466 | fasttrap_pid_provide, | |||
1467 | NULL((void *)0), | |||
1468 | fasttrap_pid_enable, | |||
1469 | fasttrap_pid_disable, | |||
1470 | NULL((void *)0), | |||
1471 | NULL((void *)0), | |||
1472 | fasttrap_pid_getargdesc, | |||
1473 | fasttrap_pid_getarg, | |||
1474 | NULL((void *)0), | |||
1475 | fasttrap_pid_destroy | |||
1476 | }; | |||
1477 | ||||
1478 | static dtrace_pops_t usdt_pops = { | |||
1479 | fasttrap_pid_provide, | |||
1480 | NULL((void *)0), | |||
1481 | fasttrap_pid_enable, | |||
1482 | fasttrap_pid_disable, | |||
1483 | NULL((void *)0), | |||
1484 | NULL((void *)0), | |||
1485 | fasttrap_pid_getargdesc, | |||
1486 | fasttrap_usdt_getarg, | |||
1487 | NULL((void *)0), | |||
1488 | fasttrap_pid_destroy | |||
1489 | }; | |||
1490 | ||||
1491 | static fasttrap_proc_t * | |||
1492 | fasttrap_proc_lookup(pid_t pid) | |||
1493 | { | |||
1494 | fasttrap_bucket_t *bucket; | |||
1495 | fasttrap_proc_t *fprc, *new_fprc; | |||
1496 | ||||
1497 | ||||
1498 | bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)((pid) & fasttrap_procs.fth_mask)]; | |||
1499 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1499)); | |||
1500 | ||||
1501 | for (fprc = bucket->ftb_data; fprc != NULL((void *)0); fprc = fprc->ftpc_next) { | |||
1502 | if (fprc->ftpc_pid == pid && fprc->ftpc_acount != 0) { | |||
1503 | mutex_enter(&fprc->ftpc_mtx)(void)_sx_xlock(((&fprc->ftpc_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1503)); | |||
1504 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1504)); | |||
1505 | fprc->ftpc_rcount++; | |||
1506 | atomic_inc_64(&fprc->ftpc_acount); | |||
1507 | ASSERT(fprc->ftpc_acount <= fprc->ftpc_rcount)((void)0); | |||
1508 | mutex_exit(&fprc->ftpc_mtx)_sx_xunlock(((&fprc->ftpc_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1508)); | |||
1509 | ||||
1510 | return (fprc); | |||
1511 | } | |||
1512 | } | |||
1513 | ||||
1514 | /* | |||
1515 | * Drop the bucket lock so we don't try to perform a sleeping | |||
1516 | * allocation under it. | |||
1517 | */ | |||
1518 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1518)); | |||
1519 | ||||
1520 | new_fprc = kmem_zalloc(sizeof (fasttrap_proc_t), KM_SLEEP)zfs_kmem_alloc((sizeof (fasttrap_proc_t)), (0x0002) | 0x0100); | |||
1521 | new_fprc->ftpc_pid = pid; | |||
1522 | new_fprc->ftpc_rcount = 1; | |||
1523 | new_fprc->ftpc_acount = 1; | |||
1524 | #ifndef illumos | |||
1525 | mutex_init(&new_fprc->ftpc_mtx, "fasttrap proc mtx", MUTEX_DEFAULT,do { const char *_name; ((void)0); do { } while (0); bzero((& new_fprc->ftpc_mtx), sizeof(struct sx)); for (_name = "&new_fprc->ftpc_mtx" ; *_name != '\0'; _name++) { if (*_name >= 'a' && * _name <= 'z') break; } if (*_name == '\0') _name = "&new_fprc->ftpc_mtx" ; sx_init_flags((&new_fprc->ftpc_mtx), _name, (0x01 | 0x04 )); } while (0) | |||
1526 | NULL)do { const char *_name; ((void)0); do { } while (0); bzero((& new_fprc->ftpc_mtx), sizeof(struct sx)); for (_name = "&new_fprc->ftpc_mtx" ; *_name != '\0'; _name++) { if (*_name >= 'a' && * _name <= 'z') break; } if (*_name == '\0') _name = "&new_fprc->ftpc_mtx" ; sx_init_flags((&new_fprc->ftpc_mtx), _name, (0x01 | 0x04 )); } while (0); | |||
1527 | #endif | |||
1528 | ||||
1529 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1529)); | |||
1530 | ||||
1531 | /* | |||
1532 | * Take another lap through the list to make sure a proc hasn't | |||
1533 | * been created for this pid while we weren't under the bucket lock. | |||
1534 | */ | |||
1535 | for (fprc = bucket->ftb_data; fprc != NULL((void *)0); fprc = fprc->ftpc_next) { | |||
1536 | if (fprc->ftpc_pid == pid && fprc->ftpc_acount != 0) { | |||
1537 | mutex_enter(&fprc->ftpc_mtx)(void)_sx_xlock(((&fprc->ftpc_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1537)); | |||
1538 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1538)); | |||
1539 | fprc->ftpc_rcount++; | |||
1540 | atomic_inc_64(&fprc->ftpc_acount); | |||
1541 | ASSERT(fprc->ftpc_acount <= fprc->ftpc_rcount)((void)0); | |||
1542 | mutex_exit(&fprc->ftpc_mtx)_sx_xunlock(((&fprc->ftpc_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1542)); | |||
1543 | ||||
1544 | kmem_free(new_fprc, sizeof (fasttrap_proc_t))zfs_kmem_free((new_fprc), (sizeof (fasttrap_proc_t))); | |||
1545 | ||||
1546 | return (fprc); | |||
1547 | } | |||
1548 | } | |||
1549 | ||||
1550 | new_fprc->ftpc_next = bucket->ftb_data; | |||
1551 | bucket->ftb_data = new_fprc; | |||
1552 | ||||
1553 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1553)); | |||
1554 | ||||
1555 | return (new_fprc); | |||
1556 | } | |||
1557 | ||||
1558 | static void | |||
1559 | fasttrap_proc_release(fasttrap_proc_t *proc) | |||
1560 | { | |||
1561 | fasttrap_bucket_t *bucket; | |||
1562 | fasttrap_proc_t *fprc, **fprcp; | |||
1563 | pid_t pid = proc->ftpc_pid; | |||
1564 | #ifndef illumos | |||
1565 | fasttrap_scrblock_t *scrblk, *scrblktmp; | |||
1566 | fasttrap_scrspace_t *scrspc, *scrspctmp; | |||
1567 | struct proc *p; | |||
1568 | struct thread *td; | |||
1569 | #endif | |||
1570 | ||||
1571 | mutex_enter(&proc->ftpc_mtx)(void)_sx_xlock(((&proc->ftpc_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1571)); | |||
1572 | ||||
1573 | ASSERT(proc->ftpc_rcount != 0)((void)0); | |||
1574 | ASSERT(proc->ftpc_acount <= proc->ftpc_rcount)((void)0); | |||
1575 | ||||
1576 | if (--proc->ftpc_rcount != 0) { | |||
1577 | mutex_exit(&proc->ftpc_mtx)_sx_xunlock(((&proc->ftpc_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1577)); | |||
1578 | return; | |||
1579 | } | |||
1580 | ||||
1581 | #ifndef illumos | |||
1582 | /* | |||
1583 | * Free all structures used to manage per-thread scratch space. | |||
1584 | */ | |||
1585 | LIST_FOREACH_SAFE(scrblk, &proc->ftpc_scrblks, ftsb_next,for ((scrblk) = (((&proc->ftpc_scrblks))->lh_first) ; (scrblk) && ((scrblktmp) = (((scrblk))->ftsb_next .le_next), 1); (scrblk) = (scrblktmp)) | |||
1586 | scrblktmp)for ((scrblk) = (((&proc->ftpc_scrblks))->lh_first) ; (scrblk) && ((scrblktmp) = (((scrblk))->ftsb_next .le_next), 1); (scrblk) = (scrblktmp)) { | |||
1587 | LIST_REMOVE(scrblk, ftsb_next)do { ; ; ; ; if ((((scrblk))->ftsb_next.le_next) != ((void *)0)) (((scrblk))->ftsb_next.le_next)->ftsb_next.le_prev = (scrblk)->ftsb_next.le_prev; *(scrblk)->ftsb_next.le_prev = (((scrblk))->ftsb_next.le_next); ; ; } while (0); | |||
1588 | free(scrblk, M_SOLARIS); | |||
1589 | } | |||
1590 | LIST_FOREACH_SAFE(scrspc, &proc->ftpc_fscr, ftss_next, scrspctmp)for ((scrspc) = (((&proc->ftpc_fscr))->lh_first); ( scrspc) && ((scrspctmp) = (((scrspc))->ftss_next.le_next ), 1); (scrspc) = (scrspctmp)) { | |||
1591 | LIST_REMOVE(scrspc, ftss_next)do { ; ; ; ; if ((((scrspc))->ftss_next.le_next) != ((void *)0)) (((scrspc))->ftss_next.le_next)->ftss_next.le_prev = (scrspc)->ftss_next.le_prev; *(scrspc)->ftss_next.le_prev = (((scrspc))->ftss_next.le_next); ; ; } while (0); | |||
1592 | free(scrspc, M_SOLARIS); | |||
1593 | } | |||
1594 | LIST_FOREACH_SAFE(scrspc, &proc->ftpc_ascr, ftss_next, scrspctmp)for ((scrspc) = (((&proc->ftpc_ascr))->lh_first); ( scrspc) && ((scrspctmp) = (((scrspc))->ftss_next.le_next ), 1); (scrspc) = (scrspctmp)) { | |||
1595 | LIST_REMOVE(scrspc, ftss_next)do { ; ; ; ; if ((((scrspc))->ftss_next.le_next) != ((void *)0)) (((scrspc))->ftss_next.le_next)->ftss_next.le_prev = (scrspc)->ftss_next.le_prev; *(scrspc)->ftss_next.le_prev = (((scrspc))->ftss_next.le_next); ; ; } while (0); | |||
1596 | free(scrspc, M_SOLARIS); | |||
1597 | } | |||
1598 | ||||
1599 | if ((p = pfind(pid)) != NULL((void *)0)) { | |||
1600 | FOREACH_THREAD_IN_PROC(p, td)for (((td)) = (((&(p)->p_threads))->tqh_first); ((td )); ((td)) = ((((td)))->td_plist.tqe_next)) | |||
1601 | td->t_dtrace_sscrtd_dtrace->td_dtrace_sscr = NULL((void *)0); | |||
1602 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1602)); | |||
1603 | } | |||
1604 | #endif | |||
1605 | ||||
1606 | mutex_exit(&proc->ftpc_mtx)_sx_xunlock(((&proc->ftpc_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1606)); | |||
1607 | ||||
1608 | /* | |||
1609 | * There should definitely be no live providers associated with this | |||
1610 | * process at this point. | |||
1611 | */ | |||
1612 | ASSERT(proc->ftpc_acount == 0)((void)0); | |||
1613 | ||||
1614 | bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)((pid) & fasttrap_procs.fth_mask)]; | |||
1615 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1615)); | |||
1616 | ||||
1617 | fprcp = (fasttrap_proc_t **)&bucket->ftb_data; | |||
1618 | while ((fprc = *fprcp) != NULL((void *)0)) { | |||
1619 | if (fprc == proc) | |||
1620 | break; | |||
1621 | ||||
1622 | fprcp = &fprc->ftpc_next; | |||
1623 | } | |||
1624 | ||||
1625 | /* | |||
1626 | * Something strange has happened if we can't find the proc. | |||
1627 | */ | |||
1628 | ASSERT(fprc != NULL)((void)0); | |||
1629 | ||||
1630 | *fprcp = fprc->ftpc_next; | |||
1631 | ||||
1632 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1632)); | |||
1633 | ||||
1634 | kmem_free(fprc, sizeof (fasttrap_proc_t))zfs_kmem_free((fprc), (sizeof (fasttrap_proc_t))); | |||
1635 | } | |||
1636 | ||||
1637 | /* | |||
1638 | * Lookup a fasttrap-managed provider based on its name and associated pid. | |||
1639 | * If the pattr argument is non-NULL, this function instantiates the provider | |||
1640 | * if it doesn't exist otherwise it returns NULL. The provider is returned | |||
1641 | * with its lock held. | |||
1642 | */ | |||
1643 | static fasttrap_provider_t * | |||
1644 | fasttrap_provider_lookup(pid_t pid, const char *name, | |||
1645 | const dtrace_pattr_t *pattr) | |||
1646 | { | |||
1647 | fasttrap_provider_t *fp, *new_fp = NULL((void *)0); | |||
1648 | fasttrap_bucket_t *bucket; | |||
1649 | char provname[DTRACE_PROVNAMELEN64]; | |||
1650 | proc_t *p; | |||
1651 | cred_t *cred; | |||
1652 | ||||
1653 | ASSERT(strlen(name) < sizeof (fp->ftp_name))((void)0); | |||
1654 | ASSERT(pattr != NULL)((void)0); | |||
1655 | ||||
1656 | bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask )]; | |||
1657 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1657)); | |||
1658 | ||||
1659 | /* | |||
1660 | * Take a lap through the list and return the match if we find it. | |||
1661 | */ | |||
1662 | for (fp = bucket->ftb_data; fp != NULL((void *)0); fp = fp->ftp_next) { | |||
1663 | if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 && | |||
1664 | !fp->ftp_retired) { | |||
1665 | mutex_enter(&fp->ftp_mtx)(void)_sx_xlock(((&fp->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1665)); | |||
1666 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1666)); | |||
1667 | return (fp); | |||
1668 | } | |||
1669 | } | |||
1670 | ||||
1671 | /* | |||
1672 | * Drop the bucket lock so we don't try to perform a sleeping | |||
1673 | * allocation under it. | |||
1674 | */ | |||
1675 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1675)); | |||
1676 | ||||
1677 | /* | |||
1678 | * Make sure the process exists, isn't a child created as the result | |||
1679 | * of a vfork(2), and isn't a zombie (but may be in fork). | |||
1680 | */ | |||
1681 | if ((p = pfind(pid)) == NULL((void *)0)) | |||
1682 | return (NULL((void *)0)); | |||
1683 | ||||
1684 | /* | |||
1685 | * Increment p_dtrace_probes so that the process knows to inform us | |||
1686 | * when it exits or execs. fasttrap_provider_free() decrements this | |||
1687 | * when we're done with this provider. | |||
1688 | */ | |||
1689 | p->p_dtrace_probesp_dtrace->p_dtrace_probes++; | |||
1690 | ||||
1691 | /* | |||
1692 | * Grab the credentials for this process so we have | |||
1693 | * something to pass to dtrace_register(). | |||
1694 | */ | |||
1695 | PROC_LOCK_ASSERT(p, MA_OWNED)(void)0; | |||
1696 | crhold(p->p_ucred); | |||
1697 | cred = p->p_ucred; | |||
1698 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1698)); | |||
1699 | ||||
1700 | new_fp = kmem_zalloc(sizeof (fasttrap_provider_t), KM_SLEEP)zfs_kmem_alloc((sizeof (fasttrap_provider_t)), (0x0002) | 0x0100 ); | |||
1701 | new_fp->ftp_pid = pid; | |||
1702 | new_fp->ftp_proc = fasttrap_proc_lookup(pid); | |||
1703 | #ifndef illumos | |||
1704 | mutex_init(&new_fp->ftp_mtx, "provider mtx", MUTEX_DEFAULT, NULL)do { const char *_name; ((void)0); do { } while (0); bzero((& new_fp->ftp_mtx), sizeof(struct sx)); for (_name = "&new_fp->ftp_mtx" ; *_name != '\0'; _name++) { if (*_name >= 'a' && * _name <= 'z') break; } if (*_name == '\0') _name = "&new_fp->ftp_mtx" ; sx_init_flags((&new_fp->ftp_mtx), _name, (0x01 | 0x04 )); } while (0); | |||
1705 | mutex_init(&new_fp->ftp_cmtx, "lock on creating", MUTEX_DEFAULT, NULL)do { const char *_name; ((void)0); do { } while (0); bzero((& new_fp->ftp_cmtx), sizeof(struct sx)); for (_name = "&new_fp->ftp_cmtx" ; *_name != '\0'; _name++) { if (*_name >= 'a' && * _name <= 'z') break; } if (*_name == '\0') _name = "&new_fp->ftp_cmtx" ; sx_init_flags((&new_fp->ftp_cmtx), _name, (0x01 | 0x04 )); } while (0); | |||
1706 | #endif | |||
1707 | ||||
1708 | ASSERT(new_fp->ftp_proc != NULL)((void)0); | |||
1709 | ||||
1710 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1710)); | |||
1711 | ||||
1712 | /* | |||
1713 | * Take another lap through the list to make sure a provider hasn't | |||
1714 | * been created for this pid while we weren't under the bucket lock. | |||
1715 | */ | |||
1716 | for (fp = bucket->ftb_data; fp != NULL((void *)0); fp = fp->ftp_next) { | |||
1717 | if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 && | |||
1718 | !fp->ftp_retired) { | |||
1719 | mutex_enter(&fp->ftp_mtx)(void)_sx_xlock(((&fp->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1719)); | |||
1720 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1720)); | |||
1721 | fasttrap_provider_free(new_fp); | |||
1722 | crfree(cred); | |||
1723 | return (fp); | |||
1724 | } | |||
1725 | } | |||
1726 | ||||
1727 | (void) strcpy(new_fp->ftp_name, name); | |||
1728 | ||||
1729 | /* | |||
1730 | * Fail and return NULL if either the provider name is too long | |||
1731 | * or we fail to register this new provider with the DTrace | |||
1732 | * framework. Note that this is the only place we ever construct | |||
1733 | * the full provider name -- we keep it in pieces in the provider | |||
1734 | * structure. | |||
1735 | */ | |||
1736 | if (snprintf(provname, sizeof (provname), "%s%u", name, (uint_t)pid) >= | |||
1737 | sizeof (provname) || | |||
1738 | dtrace_register(provname, pattr, | |||
1739 | DTRACE_PRIV_PROC0x0004 | DTRACE_PRIV_OWNER0x0008 | DTRACE_PRIV_ZONEOWNER0x0010, cred, | |||
1740 | pattr == &pid_attr ? &pid_pops : &usdt_pops, new_fp, | |||
1741 | &new_fp->ftp_provid) != 0) { | |||
1742 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1742)); | |||
1743 | fasttrap_provider_free(new_fp); | |||
1744 | crfree(cred); | |||
1745 | return (NULL((void *)0)); | |||
1746 | } | |||
1747 | ||||
1748 | new_fp->ftp_next = bucket->ftb_data; | |||
1749 | bucket->ftb_data = new_fp; | |||
1750 | ||||
1751 | mutex_enter(&new_fp->ftp_mtx)(void)_sx_xlock(((&new_fp->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1751)); | |||
1752 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1752)); | |||
1753 | ||||
1754 | crfree(cred); | |||
1755 | return (new_fp); | |||
1756 | } | |||
1757 | ||||
1758 | static void | |||
1759 | fasttrap_provider_free(fasttrap_provider_t *provider) | |||
1760 | { | |||
1761 | pid_t pid = provider->ftp_pid; | |||
1762 | proc_t *p; | |||
1763 | ||||
1764 | /* | |||
1765 | * There need to be no associated enabled probes, no consumers | |||
1766 | * creating probes, and no meta providers referencing this provider. | |||
1767 | */ | |||
1768 | ASSERT(provider->ftp_rcount == 0)((void)0); | |||
1769 | ASSERT(provider->ftp_ccount == 0)((void)0); | |||
1770 | ASSERT(provider->ftp_mcount == 0)((void)0); | |||
1771 | ||||
1772 | /* | |||
1773 | * If this provider hasn't been retired, we need to explicitly drop the | |||
1774 | * count of active providers on the associated process structure. | |||
1775 | */ | |||
1776 | if (!provider->ftp_retired) { | |||
1777 | atomic_dec_64(&provider->ftp_proc->ftpc_acount); | |||
1778 | ASSERT(provider->ftp_proc->ftpc_acount <((void)0) | |||
1779 | provider->ftp_proc->ftpc_rcount)((void)0); | |||
1780 | } | |||
1781 | ||||
1782 | fasttrap_proc_release(provider->ftp_proc); | |||
1783 | ||||
1784 | #ifndef illumos | |||
1785 | mutex_destroy(&provider->ftp_mtx)sx_destroy(&provider->ftp_mtx); | |||
1786 | mutex_destroy(&provider->ftp_cmtx)sx_destroy(&provider->ftp_cmtx); | |||
1787 | #endif | |||
1788 | kmem_free(provider, sizeof (fasttrap_provider_t))zfs_kmem_free((provider), (sizeof (fasttrap_provider_t))); | |||
1789 | ||||
1790 | /* | |||
1791 | * Decrement p_dtrace_probes on the process whose provider we're | |||
1792 | * freeing. We don't have to worry about clobbering somone else's | |||
1793 | * modifications to it because we have locked the bucket that | |||
1794 | * corresponds to this process's hash chain in the provider hash | |||
1795 | * table. Don't sweat it if we can't find the process. | |||
1796 | */ | |||
1797 | if ((p = pfind(pid)) == NULL((void *)0)) { | |||
1798 | return; | |||
1799 | } | |||
1800 | ||||
1801 | p->p_dtrace_probesp_dtrace->p_dtrace_probes--; | |||
1802 | #ifndef illumos | |||
1803 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1803)); | |||
1804 | #endif | |||
1805 | } | |||
1806 | ||||
1807 | static void | |||
1808 | fasttrap_provider_retire(pid_t pid, const char *name, int mprov) | |||
1809 | { | |||
1810 | fasttrap_provider_t *fp; | |||
1811 | fasttrap_bucket_t *bucket; | |||
1812 | dtrace_provider_id_t provid; | |||
1813 | ||||
1814 | ASSERT(strlen(name) < sizeof (fp->ftp_name))((void)0); | |||
1815 | ||||
1816 | bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask )]; | |||
1817 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1817)); | |||
1818 | ||||
1819 | for (fp = bucket->ftb_data; fp != NULL((void *)0); fp = fp->ftp_next) { | |||
1820 | if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 && | |||
1821 | !fp->ftp_retired) | |||
1822 | break; | |||
1823 | } | |||
1824 | ||||
1825 | if (fp == NULL((void *)0)) { | |||
1826 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1826)); | |||
1827 | return; | |||
1828 | } | |||
1829 | ||||
1830 | mutex_enter(&fp->ftp_mtx)(void)_sx_xlock(((&fp->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1830)); | |||
1831 | ASSERT(!mprov || fp->ftp_mcount > 0)((void)0); | |||
1832 | if (mprov && --fp->ftp_mcount != 0) { | |||
1833 | mutex_exit(&fp->ftp_mtx)_sx_xunlock(((&fp->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1833)); | |||
1834 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1834)); | |||
1835 | return; | |||
1836 | } | |||
1837 | ||||
1838 | /* | |||
1839 | * Mark the provider to be removed in our post-processing step, mark it | |||
1840 | * retired, and drop the active count on its proc. Marking it indicates | |||
1841 | * that we should try to remove it; setting the retired flag indicates | |||
1842 | * that we're done with this provider; dropping the active the proc | |||
1843 | * releases our hold, and when this reaches zero (as it will during | |||
1844 | * exit or exec) the proc and associated providers become defunct. | |||
1845 | * | |||
1846 | * We obviously need to take the bucket lock before the provider lock | |||
1847 | * to perform the lookup, but we need to drop the provider lock | |||
1848 | * before calling into the DTrace framework since we acquire the | |||
1849 | * provider lock in callbacks invoked from the DTrace framework. The | |||
1850 | * bucket lock therefore protects the integrity of the provider hash | |||
1851 | * table. | |||
1852 | */ | |||
1853 | atomic_dec_64(&fp->ftp_proc->ftpc_acount); | |||
1854 | ASSERT(fp->ftp_proc->ftpc_acount < fp->ftp_proc->ftpc_rcount)((void)0); | |||
1855 | ||||
1856 | fp->ftp_retired = 1; | |||
1857 | fp->ftp_marked = 1; | |||
1858 | provid = fp->ftp_provid; | |||
1859 | mutex_exit(&fp->ftp_mtx)_sx_xunlock(((&fp->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1859)); | |||
1860 | ||||
1861 | /* | |||
1862 | * We don't have to worry about invalidating the same provider twice | |||
1863 | * since fasttrap_provider_lookup() will ignore provider that have | |||
1864 | * been marked as retired. | |||
1865 | */ | |||
1866 | dtrace_invalidate(provid); | |||
1867 | ||||
1868 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1868)); | |||
1869 | ||||
1870 | fasttrap_pid_cleanup(); | |||
1871 | } | |||
1872 | ||||
1873 | static int | |||
1874 | fasttrap_uint32_cmp(const void *ap, const void *bp) | |||
1875 | { | |||
1876 | return (*(const uint32_t *)ap - *(const uint32_t *)bp); | |||
1877 | } | |||
1878 | ||||
1879 | static int | |||
1880 | fasttrap_uint64_cmp(const void *ap, const void *bp) | |||
1881 | { | |||
1882 | return (*(const uint64_t *)ap - *(const uint64_t *)bp); | |||
1883 | } | |||
1884 | ||||
1885 | static int | |||
1886 | fasttrap_add_probe(fasttrap_probe_spec_t *pdata) | |||
1887 | { | |||
1888 | fasttrap_provider_t *provider; | |||
1889 | fasttrap_probe_t *pp; | |||
1890 | fasttrap_tracepoint_t *tp; | |||
1891 | char *name; | |||
1892 | int i, aframes = 0, whack; | |||
1893 | ||||
1894 | /* | |||
1895 | * There needs to be at least one desired trace point. | |||
1896 | */ | |||
1897 | if (pdata->ftps_noffs == 0) | |||
1898 | return (EINVAL22); | |||
1899 | ||||
1900 | switch (pdata->ftps_type) { | |||
1901 | case DTFTP_ENTRY: | |||
1902 | name = "entry"; | |||
1903 | aframes = FASTTRAP_ENTRY_AFRAMES3; | |||
1904 | break; | |||
1905 | case DTFTP_RETURN: | |||
1906 | name = "return"; | |||
1907 | aframes = FASTTRAP_RETURN_AFRAMES4; | |||
1908 | break; | |||
1909 | case DTFTP_OFFSETS: | |||
1910 | name = NULL((void *)0); | |||
1911 | break; | |||
1912 | default: | |||
1913 | return (EINVAL22); | |||
1914 | } | |||
1915 | ||||
1916 | if ((provider = fasttrap_provider_lookup(pdata->ftps_pid, | |||
1917 | FASTTRAP_PID_NAME"pid", &pid_attr)) == NULL((void *)0)) | |||
1918 | return (ESRCH3); | |||
1919 | ||||
1920 | /* | |||
1921 | * Increment this reference count to indicate that a consumer is | |||
1922 | * actively adding a new probe associated with this provider. This | |||
1923 | * prevents the provider from being deleted -- we'll need to check | |||
1924 | * for pending deletions when we drop this reference count. | |||
1925 | */ | |||
1926 | provider->ftp_ccount++; | |||
1927 | mutex_exit(&provider->ftp_mtx)_sx_xunlock(((&provider->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1927)); | |||
1928 | ||||
1929 | /* | |||
1930 | * Grab the creation lock to ensure consistency between calls to | |||
1931 | * dtrace_probe_lookup() and dtrace_probe_create() in the face of | |||
1932 | * other threads creating probes. We must drop the provider lock | |||
1933 | * before taking this lock to avoid a three-way deadlock with the | |||
1934 | * DTrace framework. | |||
1935 | */ | |||
1936 | mutex_enter(&provider->ftp_cmtx)(void)_sx_xlock(((&provider->ftp_cmtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (1936)); | |||
1937 | ||||
1938 | if (name == NULL((void *)0)) { | |||
1939 | for (i = 0; i < pdata->ftps_noffs; i++) { | |||
1940 | char name_str[17]; | |||
1941 | ||||
1942 | (void) sprintf(name_str, "%llx", | |||
1943 | (unsigned long long)pdata->ftps_offs[i]); | |||
1944 | ||||
1945 | if (dtrace_probe_lookup(provider->ftp_provid, | |||
1946 | pdata->ftps_mod, pdata->ftps_func, name_str) != 0) | |||
1947 | continue; | |||
1948 | ||||
1949 | atomic_inc_32(&fasttrap_total); | |||
1950 | ||||
1951 | if (fasttrap_total > fasttrap_max) { | |||
1952 | atomic_dec_32(&fasttrap_total); | |||
1953 | goto no_mem; | |||
1954 | } | |||
1955 | ||||
1956 | pp = kmem_zalloc(sizeof (fasttrap_probe_t), KM_SLEEP)zfs_kmem_alloc((sizeof (fasttrap_probe_t)), (0x0002) | 0x0100 ); | |||
1957 | ||||
1958 | pp->ftp_prov = provider; | |||
1959 | pp->ftp_faddr = pdata->ftps_pc; | |||
1960 | pp->ftp_fsize = pdata->ftps_size; | |||
1961 | pp->ftp_pid = pdata->ftps_pid; | |||
1962 | pp->ftp_ntps = 1; | |||
1963 | ||||
1964 | tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t),zfs_kmem_alloc((sizeof (fasttrap_tracepoint_t)), (0x0002) | 0x0100 ) | |||
1965 | KM_SLEEP)zfs_kmem_alloc((sizeof (fasttrap_tracepoint_t)), (0x0002) | 0x0100 ); | |||
1966 | ||||
1967 | tp->ftt_proc = provider->ftp_proc; | |||
1968 | tp->ftt_pc = pdata->ftps_offs[i] + pdata->ftps_pc; | |||
1969 | tp->ftt_pid = pdata->ftps_pid; | |||
1970 | ||||
1971 | pp->ftp_tps[0].fit_tp = tp; | |||
1972 | pp->ftp_tps[0].fit_id.fti_probe = pp; | |||
1973 | pp->ftp_tps[0].fit_id.fti_ptype = pdata->ftps_type; | |||
1974 | ||||
1975 | pp->ftp_id = dtrace_probe_create(provider->ftp_provid, | |||
1976 | pdata->ftps_mod, pdata->ftps_func, name_str, | |||
1977 | FASTTRAP_OFFSET_AFRAMES3, pp); | |||
1978 | } | |||
1979 | ||||
1980 | } else if (dtrace_probe_lookup(provider->ftp_provid, pdata->ftps_mod, | |||
1981 | pdata->ftps_func, name) == 0) { | |||
1982 | atomic_add_32atomic_add_int(&fasttrap_total, pdata->ftps_noffs); | |||
1983 | ||||
1984 | if (fasttrap_total > fasttrap_max) { | |||
1985 | atomic_add_32atomic_add_int(&fasttrap_total, -pdata->ftps_noffs); | |||
1986 | goto no_mem; | |||
1987 | } | |||
1988 | ||||
1989 | /* | |||
1990 | * Make sure all tracepoint program counter values are unique. | |||
1991 | * We later assume that each probe has exactly one tracepoint | |||
1992 | * for a given pc. | |||
1993 | */ | |||
1994 | qsort(pdata->ftps_offs, pdata->ftps_noffs, | |||
1995 | sizeof (uint64_t), fasttrap_uint64_cmp); | |||
1996 | for (i = 1; i < pdata->ftps_noffs; i++) { | |||
1997 | if (pdata->ftps_offs[i] > pdata->ftps_offs[i - 1]) | |||
1998 | continue; | |||
1999 | ||||
2000 | atomic_add_32atomic_add_int(&fasttrap_total, -pdata->ftps_noffs); | |||
2001 | goto no_mem; | |||
2002 | } | |||
2003 | ||||
2004 | ASSERT(pdata->ftps_noffs > 0)((void)0); | |||
2005 | pp = kmem_zalloc(offsetof(fasttrap_probe_t,zfs_kmem_alloc((__builtin_offsetof(fasttrap_probe_t, ftp_tps[ pdata->ftps_noffs])), (0x0002) | 0x0100) | |||
2006 | ftp_tps[pdata->ftps_noffs]), KM_SLEEP)zfs_kmem_alloc((__builtin_offsetof(fasttrap_probe_t, ftp_tps[ pdata->ftps_noffs])), (0x0002) | 0x0100); | |||
2007 | ||||
2008 | pp->ftp_prov = provider; | |||
2009 | pp->ftp_faddr = pdata->ftps_pc; | |||
2010 | pp->ftp_fsize = pdata->ftps_size; | |||
2011 | pp->ftp_pid = pdata->ftps_pid; | |||
2012 | pp->ftp_ntps = pdata->ftps_noffs; | |||
2013 | ||||
2014 | for (i = 0; i < pdata->ftps_noffs; i++) { | |||
2015 | tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t),zfs_kmem_alloc((sizeof (fasttrap_tracepoint_t)), (0x0002) | 0x0100 ) | |||
2016 | KM_SLEEP)zfs_kmem_alloc((sizeof (fasttrap_tracepoint_t)), (0x0002) | 0x0100 ); | |||
2017 | ||||
2018 | tp->ftt_proc = provider->ftp_proc; | |||
2019 | tp->ftt_pc = pdata->ftps_offs[i] + pdata->ftps_pc; | |||
2020 | tp->ftt_pid = pdata->ftps_pid; | |||
2021 | ||||
2022 | pp->ftp_tps[i].fit_tp = tp; | |||
2023 | pp->ftp_tps[i].fit_id.fti_probe = pp; | |||
2024 | pp->ftp_tps[i].fit_id.fti_ptype = pdata->ftps_type; | |||
2025 | } | |||
2026 | ||||
2027 | pp->ftp_id = dtrace_probe_create(provider->ftp_provid, | |||
2028 | pdata->ftps_mod, pdata->ftps_func, name, aframes, pp); | |||
2029 | } | |||
2030 | ||||
2031 | mutex_exit(&provider->ftp_cmtx)_sx_xunlock(((&provider->ftp_cmtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2031)); | |||
2032 | ||||
2033 | /* | |||
2034 | * We know that the provider is still valid since we incremented the | |||
2035 | * creation reference count. If someone tried to clean up this provider | |||
2036 | * while we were using it (e.g. because the process called exec(2) or | |||
2037 | * exit(2)), take note of that and try to clean it up now. | |||
2038 | */ | |||
2039 | mutex_enter(&provider->ftp_mtx)(void)_sx_xlock(((&provider->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2039)); | |||
2040 | provider->ftp_ccount--; | |||
2041 | whack = provider->ftp_retired; | |||
2042 | mutex_exit(&provider->ftp_mtx)_sx_xunlock(((&provider->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2042)); | |||
2043 | ||||
2044 | if (whack) | |||
2045 | fasttrap_pid_cleanup(); | |||
2046 | ||||
2047 | return (0); | |||
2048 | ||||
2049 | no_mem: | |||
2050 | /* | |||
2051 | * If we've exhausted the allowable resources, we'll try to remove | |||
2052 | * this provider to free some up. This is to cover the case where | |||
2053 | * the user has accidentally created many more probes than was | |||
2054 | * intended (e.g. pid123:::). | |||
2055 | */ | |||
2056 | mutex_exit(&provider->ftp_cmtx)_sx_xunlock(((&provider->ftp_cmtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2056)); | |||
2057 | mutex_enter(&provider->ftp_mtx)(void)_sx_xlock(((&provider->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2057)); | |||
2058 | provider->ftp_ccount--; | |||
2059 | provider->ftp_marked = 1; | |||
2060 | mutex_exit(&provider->ftp_mtx)_sx_xunlock(((&provider->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2060)); | |||
2061 | ||||
2062 | fasttrap_pid_cleanup(); | |||
2063 | ||||
2064 | return (ENOMEM12); | |||
2065 | } | |||
2066 | ||||
2067 | /*ARGSUSED*/ | |||
2068 | static void * | |||
2069 | fasttrap_meta_provide(void *arg, dtrace_helper_provdesc_t *dhpv, pid_t pid) | |||
2070 | { | |||
2071 | fasttrap_provider_t *provider; | |||
2072 | ||||
2073 | /* | |||
2074 | * A 32-bit unsigned integer (like a pid for example) can be | |||
2075 | * expressed in 10 or fewer decimal digits. Make sure that we'll | |||
2076 | * have enough space for the provider name. | |||
2077 | */ | |||
2078 | if (strlen(dhpv->dthpv_provname) + 10 >= | |||
2079 | sizeof (provider->ftp_name)) { | |||
2080 | printf("failed to instantiate provider %s: " | |||
2081 | "name too long to accomodate pid", dhpv->dthpv_provname); | |||
2082 | return (NULL((void *)0)); | |||
2083 | } | |||
2084 | ||||
2085 | /* | |||
2086 | * Don't let folks spoof the true pid provider. | |||
2087 | */ | |||
2088 | if (strcmp(dhpv->dthpv_provname, FASTTRAP_PID_NAME"pid") == 0) { | |||
2089 | printf("failed to instantiate provider %s: " | |||
2090 | "%s is an invalid name", dhpv->dthpv_provname, | |||
2091 | FASTTRAP_PID_NAME"pid"); | |||
2092 | return (NULL((void *)0)); | |||
2093 | } | |||
2094 | ||||
2095 | /* | |||
2096 | * The highest stability class that fasttrap supports is ISA; cap | |||
2097 | * the stability of the new provider accordingly. | |||
2098 | */ | |||
2099 | if (dhpv->dthpv_pattr.dtpa_provider.dtat_class > DTRACE_CLASS_ISA4) | |||
2100 | dhpv->dthpv_pattr.dtpa_provider.dtat_class = DTRACE_CLASS_ISA4; | |||
2101 | if (dhpv->dthpv_pattr.dtpa_mod.dtat_class > DTRACE_CLASS_ISA4) | |||
2102 | dhpv->dthpv_pattr.dtpa_mod.dtat_class = DTRACE_CLASS_ISA4; | |||
2103 | if (dhpv->dthpv_pattr.dtpa_func.dtat_class > DTRACE_CLASS_ISA4) | |||
2104 | dhpv->dthpv_pattr.dtpa_func.dtat_class = DTRACE_CLASS_ISA4; | |||
2105 | if (dhpv->dthpv_pattr.dtpa_name.dtat_class > DTRACE_CLASS_ISA4) | |||
2106 | dhpv->dthpv_pattr.dtpa_name.dtat_class = DTRACE_CLASS_ISA4; | |||
2107 | if (dhpv->dthpv_pattr.dtpa_args.dtat_class > DTRACE_CLASS_ISA4) | |||
2108 | dhpv->dthpv_pattr.dtpa_args.dtat_class = DTRACE_CLASS_ISA4; | |||
2109 | ||||
2110 | if ((provider = fasttrap_provider_lookup(pid, dhpv->dthpv_provname, | |||
2111 | &dhpv->dthpv_pattr)) == NULL((void *)0)) { | |||
2112 | printf("failed to instantiate provider %s for " | |||
2113 | "process %u", dhpv->dthpv_provname, (uint_t)pid); | |||
2114 | return (NULL((void *)0)); | |||
2115 | } | |||
2116 | ||||
2117 | /* | |||
2118 | * Up the meta provider count so this provider isn't removed until | |||
2119 | * the meta provider has been told to remove it. | |||
2120 | */ | |||
2121 | provider->ftp_mcount++; | |||
2122 | ||||
2123 | mutex_exit(&provider->ftp_mtx)_sx_xunlock(((&provider->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2123)); | |||
2124 | ||||
2125 | return (provider); | |||
2126 | } | |||
2127 | ||||
2128 | /* | |||
2129 | * We know a few things about our context here: we know that the probe being | |||
2130 | * created doesn't already exist (DTrace won't load DOF at the same address | |||
2131 | * twice, even if explicitly told to do so) and we know that we are | |||
2132 | * single-threaded with respect to the meta provider machinery. Knowing that | |||
2133 | * this is a new probe and that there is no way for us to race with another | |||
2134 | * operation on this provider allows us an important optimization: we need not | |||
2135 | * lookup a probe before adding it. Saving this lookup is important because | |||
2136 | * this code is in the fork path for processes with USDT probes, and lookups | |||
2137 | * here are potentially very expensive because of long hash conflicts on | |||
2138 | * module, function and name (DTrace doesn't hash on provider name). | |||
2139 | */ | |||
2140 | /*ARGSUSED*/ | |||
2141 | static void | |||
2142 | fasttrap_meta_create_probe(void *arg, void *parg, | |||
2143 | dtrace_helper_probedesc_t *dhpb) | |||
2144 | { | |||
2145 | fasttrap_provider_t *provider = parg; | |||
2146 | fasttrap_probe_t *pp; | |||
2147 | fasttrap_tracepoint_t *tp; | |||
2148 | int i, j; | |||
2149 | uint32_t ntps; | |||
2150 | ||||
2151 | /* | |||
2152 | * Since the meta provider count is non-zero we don't have to worry | |||
2153 | * about this provider disappearing. | |||
2154 | */ | |||
2155 | ASSERT(provider->ftp_mcount > 0)((void)0); | |||
2156 | ||||
2157 | /* | |||
2158 | * The offsets must be unique. | |||
2159 | */ | |||
2160 | qsort(dhpb->dthpb_offs, dhpb->dthpb_noffs, sizeof (uint32_t), | |||
2161 | fasttrap_uint32_cmp); | |||
2162 | for (i = 1; i < dhpb->dthpb_noffs; i++) { | |||
2163 | if (dhpb->dthpb_base + dhpb->dthpb_offs[i] <= | |||
2164 | dhpb->dthpb_base + dhpb->dthpb_offs[i - 1]) | |||
2165 | return; | |||
2166 | } | |||
2167 | ||||
2168 | qsort(dhpb->dthpb_enoffs, dhpb->dthpb_nenoffs, sizeof (uint32_t), | |||
2169 | fasttrap_uint32_cmp); | |||
2170 | for (i = 1; i < dhpb->dthpb_nenoffs; i++) { | |||
2171 | if (dhpb->dthpb_base + dhpb->dthpb_enoffs[i] <= | |||
2172 | dhpb->dthpb_base + dhpb->dthpb_enoffs[i - 1]) | |||
2173 | return; | |||
2174 | } | |||
2175 | ||||
2176 | ntps = dhpb->dthpb_noffs + dhpb->dthpb_nenoffs; | |||
2177 | ASSERT(ntps > 0)((void)0); | |||
2178 | ||||
2179 | atomic_add_32atomic_add_int(&fasttrap_total, ntps); | |||
2180 | ||||
2181 | if (fasttrap_total > fasttrap_max) { | |||
2182 | atomic_add_32atomic_add_int(&fasttrap_total, -ntps); | |||
2183 | return; | |||
2184 | } | |||
2185 | ||||
2186 | pp = kmem_zalloc(offsetof(fasttrap_probe_t, ftp_tps[ntps]), KM_SLEEP)zfs_kmem_alloc((__builtin_offsetof(fasttrap_probe_t, ftp_tps[ ntps])), (0x0002) | 0x0100); | |||
2187 | ||||
2188 | pp->ftp_prov = provider; | |||
2189 | pp->ftp_pid = provider->ftp_pid; | |||
2190 | pp->ftp_ntps = ntps; | |||
2191 | pp->ftp_nargs = dhpb->dthpb_xargc; | |||
2192 | pp->ftp_xtypes = dhpb->dthpb_xtypes; | |||
2193 | pp->ftp_ntypes = dhpb->dthpb_ntypes; | |||
2194 | ||||
2195 | /* | |||
2196 | * First create a tracepoint for each actual point of interest. | |||
2197 | */ | |||
2198 | for (i = 0; i < dhpb->dthpb_noffs; i++) { | |||
2199 | tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP)zfs_kmem_alloc((sizeof (fasttrap_tracepoint_t)), (0x0002) | 0x0100 ); | |||
2200 | ||||
2201 | tp->ftt_proc = provider->ftp_proc; | |||
2202 | tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_offs[i]; | |||
2203 | tp->ftt_pid = provider->ftp_pid; | |||
2204 | ||||
2205 | pp->ftp_tps[i].fit_tp = tp; | |||
2206 | pp->ftp_tps[i].fit_id.fti_probe = pp; | |||
2207 | #ifdef __sparc | |||
2208 | pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_POST_OFFSETS; | |||
2209 | #else | |||
2210 | pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_OFFSETS; | |||
2211 | #endif | |||
2212 | } | |||
2213 | ||||
2214 | /* | |||
2215 | * Then create a tracepoint for each is-enabled point. | |||
2216 | */ | |||
2217 | for (j = 0; i < ntps; i++, j++) { | |||
2218 | tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP)zfs_kmem_alloc((sizeof (fasttrap_tracepoint_t)), (0x0002) | 0x0100 ); | |||
2219 | ||||
2220 | tp->ftt_proc = provider->ftp_proc; | |||
2221 | tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_enoffs[j]; | |||
2222 | tp->ftt_pid = provider->ftp_pid; | |||
2223 | ||||
2224 | pp->ftp_tps[i].fit_tp = tp; | |||
2225 | pp->ftp_tps[i].fit_id.fti_probe = pp; | |||
2226 | pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_IS_ENABLED; | |||
2227 | } | |||
2228 | ||||
2229 | /* | |||
2230 | * If the arguments are shuffled around we set the argument remapping | |||
2231 | * table. Later, when the probe fires, we only remap the arguments | |||
2232 | * if the table is non-NULL. | |||
2233 | */ | |||
2234 | for (i = 0; i < dhpb->dthpb_xargc; i++) { | |||
2235 | if (dhpb->dthpb_args[i] != i) { | |||
2236 | pp->ftp_argmap = dhpb->dthpb_args; | |||
2237 | break; | |||
2238 | } | |||
2239 | } | |||
2240 | ||||
2241 | /* | |||
2242 | * The probe is fully constructed -- register it with DTrace. | |||
2243 | */ | |||
2244 | pp->ftp_id = dtrace_probe_create(provider->ftp_provid, dhpb->dthpb_mod, | |||
2245 | dhpb->dthpb_func, dhpb->dthpb_name, FASTTRAP_OFFSET_AFRAMES3, pp); | |||
2246 | } | |||
2247 | ||||
2248 | /*ARGSUSED*/ | |||
2249 | static void | |||
2250 | fasttrap_meta_remove(void *arg, dtrace_helper_provdesc_t *dhpv, pid_t pid) | |||
2251 | { | |||
2252 | /* | |||
2253 | * Clean up the USDT provider. There may be active consumers of the | |||
2254 | * provider busy adding probes, no damage will actually befall the | |||
2255 | * provider until that count has dropped to zero. This just puts | |||
2256 | * the provider on death row. | |||
2257 | */ | |||
2258 | fasttrap_provider_retire(pid, dhpv->dthpv_provname, 1); | |||
2259 | } | |||
2260 | ||||
2261 | static dtrace_mops_t fasttrap_mops = { | |||
2262 | fasttrap_meta_create_probe, | |||
2263 | fasttrap_meta_provide, | |||
2264 | fasttrap_meta_remove | |||
2265 | }; | |||
2266 | ||||
2267 | /*ARGSUSED*/ | |||
2268 | static int | |||
2269 | fasttrap_open(struct cdev *dev __unused__attribute__((__unused__)), int oflags __unused__attribute__((__unused__)), | |||
2270 | int devtype __unused__attribute__((__unused__)), struct thread *td __unused__attribute__((__unused__))) | |||
2271 | { | |||
2272 | return (0); | |||
2273 | } | |||
2274 | ||||
2275 | /*ARGSUSED*/ | |||
2276 | static int | |||
2277 | fasttrap_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int fflag, | |||
2278 | struct thread *td) | |||
2279 | { | |||
2280 | #ifdef notyet | |||
2281 | struct kinfo_proc kp; | |||
2282 | const cred_t *cr = td->td_ucred; | |||
2283 | #endif | |||
2284 | if (!dtrace_attached()) | |||
| ||||
2285 | return (EAGAIN35); | |||
2286 | ||||
2287 | if (cmd == FASTTRAPIOC_MAKEPROBE((unsigned long) ((0x20000000) | (((0) & ((1 << 13) - 1)) << 16) | ((('f')) << 8) | ((3))))) { | |||
2288 | fasttrap_probe_spec_t *uprobe = *(fasttrap_probe_spec_t **)arg; | |||
2289 | fasttrap_probe_spec_t *probe; | |||
2290 | uint64_t noffs; | |||
2291 | size_t size; | |||
2292 | int ret, err; | |||
2293 | ||||
2294 | if (copyin(&uprobe->ftps_noffs, &noffs, | |||
2295 | sizeof (uprobe->ftps_noffs))) | |||
2296 | return (EFAULT14); | |||
2297 | ||||
2298 | /* | |||
2299 | * Probes must have at least one tracepoint. | |||
2300 | */ | |||
2301 | if (noffs == 0) | |||
2302 | return (EINVAL22); | |||
2303 | ||||
2304 | size = sizeof (fasttrap_probe_spec_t) + | |||
2305 | sizeof (probe->ftps_offs[0]) * (noffs - 1); | |||
2306 | ||||
2307 | if (size > 1024 * 1024) | |||
2308 | return (ENOMEM12); | |||
2309 | ||||
2310 | probe = kmem_alloc(size, KM_SLEEP)zfs_kmem_alloc((size), (0x0002)); | |||
2311 | ||||
2312 | if (copyin(uprobe, probe, size) != 0 || | |||
2313 | probe->ftps_noffs != noffs) { | |||
2314 | kmem_free(probe, size)zfs_kmem_free((probe), (size)); | |||
2315 | return (EFAULT14); | |||
2316 | } | |||
2317 | ||||
2318 | /* | |||
2319 | * Verify that the function and module strings contain no | |||
2320 | * funny characters. | |||
2321 | */ | |||
2322 | if (u8_validate(probe->ftps_func, strlen(probe->ftps_func), | |||
2323 | NULL((void *)0), U8_VALIDATE_ENTIRE(0x00100000), &err) < 0) { | |||
2324 | ret = EINVAL22; | |||
2325 | goto err; | |||
2326 | } | |||
2327 | ||||
2328 | if (u8_validate(probe->ftps_mod, strlen(probe->ftps_mod), | |||
2329 | NULL((void *)0), U8_VALIDATE_ENTIRE(0x00100000), &err) < 0) { | |||
2330 | ret = EINVAL22; | |||
2331 | goto err; | |||
2332 | } | |||
2333 | ||||
2334 | #ifdef notyet | |||
2335 | if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)priv_policy_choice((cr), (PRIV_ALL), (0))) { | |||
2336 | proc_t *p; | |||
2337 | pid_t pid = probe->ftps_pid; | |||
2338 | ||||
2339 | #ifdef illumos | |||
2340 | mutex_enter(&pidlock)(void)_sx_xlock(((&pidlock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2340)); | |||
2341 | #endif | |||
2342 | /* | |||
2343 | * Report an error if the process doesn't exist | |||
2344 | * or is actively being birthed. | |||
2345 | */ | |||
2346 | sx_slock(&proctree_lock)(void)_sx_slock(((&proctree_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2346)); | |||
2347 | p = pfind(pid); | |||
2348 | if (p) | |||
2349 | fill_kinfo_proc(p, &kp); | |||
2350 | sx_sunlock(&proctree_lock)_sx_sunlock(((&proctree_lock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2350)); | |||
2351 | if (p == NULL((void *)0) || kp.ki_stat == SIDL1) { | |||
2352 | #ifdef illumos | |||
2353 | mutex_exit(&pidlock)_sx_xunlock(((&pidlock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2353)); | |||
2354 | #endif | |||
2355 | return (ESRCH3); | |||
2356 | } | |||
2357 | #ifdef illumos | |||
2358 | mutex_enter(&p->p_lock)(void)_sx_xlock(((&p->p_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2358)); | |||
2359 | mutex_exit(&pidlock)_sx_xunlock(((&pidlock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2359)); | |||
2360 | #else | |||
2361 | PROC_LOCK_ASSERT(p, MA_OWNED)(void)0; | |||
2362 | #endif | |||
2363 | ||||
2364 | #ifdef notyet | |||
2365 | if ((ret = priv_proc_cred_perm(cr, p, NULL((void *)0), | |||
2366 | VREAD000000000400 | VWRITE000000000200)) != 0) { | |||
2367 | #ifdef illumos | |||
2368 | mutex_exit(&p->p_lock)_sx_xunlock(((&p->p_lock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2368)); | |||
2369 | #else | |||
2370 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2370)); | |||
2371 | #endif | |||
2372 | return (ret); | |||
2373 | } | |||
2374 | #endif /* notyet */ | |||
2375 | #ifdef illumos | |||
2376 | mutex_exit(&p->p_lock)_sx_xunlock(((&p->p_lock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2376)); | |||
2377 | #else | |||
2378 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2378)); | |||
2379 | #endif | |||
2380 | } | |||
2381 | #endif /* notyet */ | |||
2382 | ||||
2383 | ret = fasttrap_add_probe(probe); | |||
2384 | err: | |||
2385 | kmem_free(probe, size)zfs_kmem_free((probe), (size)); | |||
2386 | ||||
2387 | return (ret); | |||
2388 | ||||
2389 | } else if (cmd == FASTTRAPIOC_GETINSTR((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(uint8_t )) & ((1 << 13) - 1)) << 16) | ((('f')) << 8) | ((2))))) { | |||
2390 | fasttrap_instr_query_t instr; | |||
2391 | fasttrap_tracepoint_t *tp; | |||
2392 | uint_t index; | |||
2393 | #ifdef illumos | |||
2394 | int ret; | |||
2395 | #endif | |||
2396 | ||||
2397 | #ifdef illumos | |||
2398 | if (copyin((void *)arg, &instr, sizeof (instr)) != 0) | |||
2399 | return (EFAULT14); | |||
2400 | #endif | |||
2401 | ||||
2402 | #ifdef notyet | |||
2403 | if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)priv_policy_choice((cr), (PRIV_ALL), (0))) { | |||
2404 | proc_t *p; | |||
2405 | pid_t pid = instr.ftiq_pid; | |||
2406 | ||||
2407 | #ifdef illumos | |||
2408 | mutex_enter(&pidlock)(void)_sx_xlock(((&pidlock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2408)); | |||
2409 | #endif | |||
2410 | /* | |||
2411 | * Report an error if the process doesn't exist | |||
2412 | * or is actively being birthed. | |||
2413 | */ | |||
2414 | sx_slock(&proctree_lock)(void)_sx_slock(((&proctree_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2414)); | |||
2415 | p = pfind(pid); | |||
2416 | if (p) | |||
2417 | fill_kinfo_proc(p, &kp); | |||
2418 | sx_sunlock(&proctree_lock)_sx_sunlock(((&proctree_lock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2418)); | |||
2419 | if (p == NULL((void *)0) || kp.ki_stat == SIDL1) { | |||
2420 | #ifdef illumos | |||
2421 | mutex_exit(&pidlock)_sx_xunlock(((&pidlock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2421)); | |||
2422 | #endif | |||
2423 | return (ESRCH3); | |||
2424 | } | |||
2425 | #ifdef illumos | |||
2426 | mutex_enter(&p->p_lock)(void)_sx_xlock(((&p->p_lock)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2426)); | |||
2427 | mutex_exit(&pidlock)_sx_xunlock(((&pidlock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2427)); | |||
2428 | #else | |||
2429 | PROC_LOCK_ASSERT(p, MA_OWNED)(void)0; | |||
2430 | #endif | |||
2431 | ||||
2432 | #ifdef notyet | |||
2433 | if ((ret = priv_proc_cred_perm(cr, p, NULL((void *)0), | |||
2434 | VREAD000000000400)) != 0) { | |||
2435 | #ifdef illumos | |||
2436 | mutex_exit(&p->p_lock)_sx_xunlock(((&p->p_lock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2436)); | |||
2437 | #else | |||
2438 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2438)); | |||
2439 | #endif | |||
2440 | return (ret); | |||
2441 | } | |||
2442 | #endif /* notyet */ | |||
2443 | ||||
2444 | #ifdef illumos | |||
2445 | mutex_exit(&p->p_lock)_sx_xunlock(((&p->p_lock)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2445)); | |||
2446 | #else | |||
2447 | PROC_UNLOCK(p)__mtx_unlock_flags(&((((&(p)->p_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2447)); | |||
2448 | #endif | |||
2449 | } | |||
2450 | #endif /* notyet */ | |||
2451 | ||||
2452 | index = FASTTRAP_TPOINTS_INDEX(instr.ftiq_pid, instr.ftiq_pc)(((instr.ftiq_pc) / sizeof (fasttrap_instr_t) + (instr.ftiq_pid )) & fasttrap_tpoints.fth_mask); | |||
2453 | ||||
2454 | mutex_enter(&fasttrap_tpoints.fth_table[index].ftb_mtx)(void)_sx_xlock(((&fasttrap_tpoints.fth_table[index].ftb_mtx )), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2454)); | |||
2455 | tp = fasttrap_tpoints.fth_table[index].ftb_data; | |||
2456 | while (tp != NULL((void *)0)) { | |||
2457 | if (instr.ftiq_pid == tp->ftt_pid && | |||
2458 | instr.ftiq_pc == tp->ftt_pc && | |||
2459 | tp->ftt_proc->ftpc_acount != 0) | |||
2460 | break; | |||
2461 | ||||
2462 | tp = tp->ftt_next; | |||
2463 | } | |||
2464 | ||||
2465 | if (tp == NULL((void *)0)) { | |||
2466 | mutex_exit(&fasttrap_tpoints.fth_table[index].ftb_mtx)_sx_xunlock(((&fasttrap_tpoints.fth_table[index].ftb_mtx) ), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2466)); | |||
2467 | return (ENOENT2); | |||
2468 | } | |||
2469 | ||||
2470 | bcopy(&tp->ftt_instrftt_mtp.ftmt_instr, &instr.ftiq_instr, | |||
2471 | sizeof (instr.ftiq_instr)); | |||
2472 | mutex_exit(&fasttrap_tpoints.fth_table[index].ftb_mtx)_sx_xunlock(((&fasttrap_tpoints.fth_table[index].ftb_mtx) ), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2472)); | |||
2473 | ||||
2474 | if (copyout(&instr, (void *)arg, sizeof (instr)) != 0) | |||
| ||||
2475 | return (EFAULT14); | |||
2476 | ||||
2477 | return (0); | |||
2478 | } | |||
2479 | ||||
2480 | return (EINVAL22); | |||
2481 | } | |||
2482 | ||||
2483 | static int | |||
2484 | fasttrap_load(void) | |||
2485 | { | |||
2486 | ulong_t nent; | |||
2487 | int i, ret; | |||
2488 | ||||
2489 | /* Create the /dev/dtrace/fasttrap entry. */ | |||
2490 | fasttrap_cdev = make_dev(&fasttrap_cdevsw, 0, UID_ROOT0, GID_WHEEL0, 0600, | |||
2491 | "dtrace/fasttrap"); | |||
2492 | ||||
2493 | mtx_init(&fasttrap_cleanup_mtx, "fasttrap clean", "dtrace", MTX_DEF)_mtx_init(&(&fasttrap_cleanup_mtx)->mtx_lock, "fasttrap clean" , "dtrace", 0x00000000); | |||
2494 | mutex_init(&fasttrap_count_mtx, "fasttrap count mtx", MUTEX_DEFAULT,do { const char *_name; ((void)0); do { } while (0); bzero((& fasttrap_count_mtx), sizeof(struct sx)); for (_name = "&fasttrap_count_mtx" ; *_name != '\0'; _name++) { if (*_name >= 'a' && * _name <= 'z') break; } if (*_name == '\0') _name = "&fasttrap_count_mtx" ; sx_init_flags((&fasttrap_count_mtx), _name, (0x01 | 0x04 )); } while (0) | |||
2495 | NULL)do { const char *_name; ((void)0); do { } while (0); bzero((& fasttrap_count_mtx), sizeof(struct sx)); for (_name = "&fasttrap_count_mtx" ; *_name != '\0'; _name++) { if (*_name >= 'a' && * _name <= 'z') break; } if (*_name == '\0') _name = "&fasttrap_count_mtx" ; sx_init_flags((&fasttrap_count_mtx), _name, (0x01 | 0x04 )); } while (0); | |||
2496 | ||||
2497 | #ifdef illumos | |||
2498 | fasttrap_max = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, | |||
2499 | "fasttrap-max-probes", FASTTRAP_MAX_DEFAULT250000); | |||
2500 | #endif | |||
2501 | fasttrap_total = 0; | |||
2502 | ||||
2503 | /* | |||
2504 | * Conjure up the tracepoints hashtable... | |||
2505 | */ | |||
2506 | #ifdef illumos | |||
2507 | nent = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, | |||
2508 | "fasttrap-hash-size", FASTTRAP_TPOINTS_DEFAULT_SIZE0x4000); | |||
2509 | #else | |||
2510 | nent = tpoints_hash_size; | |||
2511 | #endif | |||
2512 | ||||
2513 | if (nent == 0 || nent > 0x1000000) | |||
2514 | nent = FASTTRAP_TPOINTS_DEFAULT_SIZE0x4000; | |||
2515 | ||||
2516 | tpoints_hash_size = nent; | |||
2517 | ||||
2518 | if (ISP2(nent)(((nent) & ((nent) - 1)) == 0)) | |||
2519 | fasttrap_tpoints.fth_nent = nent; | |||
2520 | else | |||
2521 | fasttrap_tpoints.fth_nent = 1 << fasttrap_highbit(nent); | |||
2522 | ASSERT(fasttrap_tpoints.fth_nent > 0)((void)0); | |||
2523 | fasttrap_tpoints.fth_mask = fasttrap_tpoints.fth_nent - 1; | |||
2524 | fasttrap_tpoints.fth_table = kmem_zalloc(fasttrap_tpoints.fth_nent *zfs_kmem_alloc((fasttrap_tpoints.fth_nent * sizeof (fasttrap_bucket_t )), (0x0002) | 0x0100) | |||
2525 | sizeof (fasttrap_bucket_t), KM_SLEEP)zfs_kmem_alloc((fasttrap_tpoints.fth_nent * sizeof (fasttrap_bucket_t )), (0x0002) | 0x0100); | |||
2526 | #ifndef illumos | |||
2527 | for (i = 0; i < fasttrap_tpoints.fth_nent; i++) | |||
2528 | mutex_init(&fasttrap_tpoints.fth_table[i].ftb_mtx,do { const char *_name; ((void)0); do { } while (0); bzero((& fasttrap_tpoints.fth_table[i].ftb_mtx), sizeof(struct sx)); for (_name = "&fasttrap_tpoints.fth_table[i].ftb_mtx"; *_name != '\0'; _name++) { if (*_name >= 'a' && *_name <= 'z') break; } if (*_name == '\0') _name = "&fasttrap_tpoints.fth_table[i].ftb_mtx" ; sx_init_flags((&fasttrap_tpoints.fth_table[i].ftb_mtx), _name, (0x01 | 0x04)); } while (0) | |||
2529 | "tracepoints bucket mtx", MUTEX_DEFAULT, NULL)do { const char *_name; ((void)0); do { } while (0); bzero((& fasttrap_tpoints.fth_table[i].ftb_mtx), sizeof(struct sx)); for (_name = "&fasttrap_tpoints.fth_table[i].ftb_mtx"; *_name != '\0'; _name++) { if (*_name >= 'a' && *_name <= 'z') break; } if (*_name == '\0') _name = "&fasttrap_tpoints.fth_table[i].ftb_mtx" ; sx_init_flags((&fasttrap_tpoints.fth_table[i].ftb_mtx), _name, (0x01 | 0x04)); } while (0); | |||
2530 | #endif | |||
2531 | ||||
2532 | /* | |||
2533 | * ... and the providers hash table... | |||
2534 | */ | |||
2535 | nent = FASTTRAP_PROVIDERS_DEFAULT_SIZE0x100; | |||
2536 | if (ISP2(nent)(((nent) & ((nent) - 1)) == 0)) | |||
2537 | fasttrap_provs.fth_nent = nent; | |||
2538 | else | |||
2539 | fasttrap_provs.fth_nent = 1 << fasttrap_highbit(nent); | |||
2540 | ASSERT(fasttrap_provs.fth_nent > 0)((void)0); | |||
2541 | fasttrap_provs.fth_mask = fasttrap_provs.fth_nent - 1; | |||
2542 | fasttrap_provs.fth_table = kmem_zalloc(fasttrap_provs.fth_nent *zfs_kmem_alloc((fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t )), (0x0002) | 0x0100) | |||
2543 | sizeof (fasttrap_bucket_t), KM_SLEEP)zfs_kmem_alloc((fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t )), (0x0002) | 0x0100); | |||
2544 | #ifndef illumos | |||
2545 | for (i = 0; i < fasttrap_provs.fth_nent; i++) | |||
2546 | mutex_init(&fasttrap_provs.fth_table[i].ftb_mtx,do { const char *_name; ((void)0); do { } while (0); bzero((& fasttrap_provs.fth_table[i].ftb_mtx), sizeof(struct sx)); for (_name = "&fasttrap_provs.fth_table[i].ftb_mtx"; *_name != '\0'; _name++) { if (*_name >= 'a' && *_name <= 'z') break; } if (*_name == '\0') _name = "&fasttrap_provs.fth_table[i].ftb_mtx" ; sx_init_flags((&fasttrap_provs.fth_table[i].ftb_mtx), _name , (0x01 | 0x04)); } while (0) | |||
2547 | "providers bucket mtx", MUTEX_DEFAULT, NULL)do { const char *_name; ((void)0); do { } while (0); bzero((& fasttrap_provs.fth_table[i].ftb_mtx), sizeof(struct sx)); for (_name = "&fasttrap_provs.fth_table[i].ftb_mtx"; *_name != '\0'; _name++) { if (*_name >= 'a' && *_name <= 'z') break; } if (*_name == '\0') _name = "&fasttrap_provs.fth_table[i].ftb_mtx" ; sx_init_flags((&fasttrap_provs.fth_table[i].ftb_mtx), _name , (0x01 | 0x04)); } while (0); | |||
2548 | #endif | |||
2549 | ||||
2550 | ret = kproc_create(fasttrap_pid_cleanup_cb, NULL((void *)0), | |||
2551 | &fasttrap_cleanup_proc, 0, 0, "ftcleanup"); | |||
2552 | if (ret != 0) { | |||
2553 | destroy_dev(fasttrap_cdev); | |||
2554 | #ifndef illumos | |||
2555 | for (i = 0; i < fasttrap_provs.fth_nent; i++) | |||
2556 | mutex_destroy(&fasttrap_provs.fth_table[i].ftb_mtx)sx_destroy(&fasttrap_provs.fth_table[i].ftb_mtx); | |||
2557 | for (i = 0; i < fasttrap_tpoints.fth_nent; i++) | |||
2558 | mutex_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx)sx_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx); | |||
2559 | #endif | |||
2560 | kmem_free(fasttrap_provs.fth_table, fasttrap_provs.fth_nent *zfs_kmem_free((fasttrap_provs.fth_table), (fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t))) | |||
2561 | sizeof (fasttrap_bucket_t))zfs_kmem_free((fasttrap_provs.fth_table), (fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t))); | |||
2562 | mtx_destroy(&fasttrap_cleanup_mtx)_mtx_destroy(&(&fasttrap_cleanup_mtx)->mtx_lock); | |||
2563 | mutex_destroy(&fasttrap_count_mtx)sx_destroy(&fasttrap_count_mtx); | |||
2564 | return (ret); | |||
2565 | } | |||
2566 | ||||
2567 | ||||
2568 | /* | |||
2569 | * ... and the procs hash table. | |||
2570 | */ | |||
2571 | nent = FASTTRAP_PROCS_DEFAULT_SIZE0x100; | |||
2572 | if (ISP2(nent)(((nent) & ((nent) - 1)) == 0)) | |||
2573 | fasttrap_procs.fth_nent = nent; | |||
2574 | else | |||
2575 | fasttrap_procs.fth_nent = 1 << fasttrap_highbit(nent); | |||
2576 | ASSERT(fasttrap_procs.fth_nent > 0)((void)0); | |||
2577 | fasttrap_procs.fth_mask = fasttrap_procs.fth_nent - 1; | |||
2578 | fasttrap_procs.fth_table = kmem_zalloc(fasttrap_procs.fth_nent *zfs_kmem_alloc((fasttrap_procs.fth_nent * sizeof (fasttrap_bucket_t )), (0x0002) | 0x0100) | |||
2579 | sizeof (fasttrap_bucket_t), KM_SLEEP)zfs_kmem_alloc((fasttrap_procs.fth_nent * sizeof (fasttrap_bucket_t )), (0x0002) | 0x0100); | |||
2580 | #ifndef illumos | |||
2581 | for (i = 0; i < fasttrap_procs.fth_nent; i++) | |||
2582 | mutex_init(&fasttrap_procs.fth_table[i].ftb_mtx,do { const char *_name; ((void)0); do { } while (0); bzero((& fasttrap_procs.fth_table[i].ftb_mtx), sizeof(struct sx)); for (_name = "&fasttrap_procs.fth_table[i].ftb_mtx"; *_name != '\0'; _name++) { if (*_name >= 'a' && *_name <= 'z') break; } if (*_name == '\0') _name = "&fasttrap_procs.fth_table[i].ftb_mtx" ; sx_init_flags((&fasttrap_procs.fth_table[i].ftb_mtx), _name , (0x01 | 0x04)); } while (0) | |||
2583 | "processes bucket mtx", MUTEX_DEFAULT, NULL)do { const char *_name; ((void)0); do { } while (0); bzero((& fasttrap_procs.fth_table[i].ftb_mtx), sizeof(struct sx)); for (_name = "&fasttrap_procs.fth_table[i].ftb_mtx"; *_name != '\0'; _name++) { if (*_name >= 'a' && *_name <= 'z') break; } if (*_name == '\0') _name = "&fasttrap_procs.fth_table[i].ftb_mtx" ; sx_init_flags((&fasttrap_procs.fth_table[i].ftb_mtx), _name , (0x01 | 0x04)); } while (0); | |||
2584 | ||||
2585 | rm_init(&fasttrap_tp_lock, "fasttrap tracepoint"); | |||
2586 | ||||
2587 | /* | |||
2588 | * This event handler must run before kdtrace_thread_dtor() since it | |||
2589 | * accesses the thread's struct kdtrace_thread. | |||
2590 | */ | |||
2591 | fasttrap_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor,eventhandler_register(((void *)0), "thread_dtor", fasttrap_thread_dtor , ((void *)0), 0) | |||
2592 | fasttrap_thread_dtor, NULL, EVENTHANDLER_PRI_FIRST)eventhandler_register(((void *)0), "thread_dtor", fasttrap_thread_dtor , ((void *)0), 0); | |||
2593 | #endif | |||
2594 | ||||
2595 | /* | |||
2596 | * Install our hooks into fork(2), exec(2), and exit(2). | |||
2597 | */ | |||
2598 | dtrace_fasttrap_fork = &fasttrap_fork; | |||
2599 | dtrace_fasttrap_exit = &fasttrap_exec_exit; | |||
2600 | dtrace_fasttrap_exec = &fasttrap_exec_exit; | |||
2601 | ||||
2602 | (void) dtrace_meta_register("fasttrap", &fasttrap_mops, NULL((void *)0), | |||
2603 | &fasttrap_meta_id); | |||
2604 | ||||
2605 | return (0); | |||
2606 | } | |||
2607 | ||||
2608 | static int | |||
2609 | fasttrap_unload(void) | |||
2610 | { | |||
2611 | int i, fail = 0; | |||
2612 | ||||
2613 | /* | |||
2614 | * Unregister the meta-provider to make sure no new fasttrap- | |||
2615 | * managed providers come along while we're trying to close up | |||
2616 | * shop. If we fail to detach, we'll need to re-register as a | |||
2617 | * meta-provider. We can fail to unregister as a meta-provider | |||
2618 | * if providers we manage still exist. | |||
2619 | */ | |||
2620 | if (fasttrap_meta_id != DTRACE_METAPROVNONE0 && | |||
2621 | dtrace_meta_unregister(fasttrap_meta_id) != 0) | |||
2622 | return (-1); | |||
2623 | ||||
2624 | /* | |||
2625 | * Iterate over all of our providers. If there's still a process | |||
2626 | * that corresponds to that pid, fail to detach. | |||
2627 | */ | |||
2628 | for (i = 0; i < fasttrap_provs.fth_nent; i++) { | |||
2629 | fasttrap_provider_t **fpp, *fp; | |||
2630 | fasttrap_bucket_t *bucket = &fasttrap_provs.fth_table[i]; | |||
2631 | ||||
2632 | mutex_enter(&bucket->ftb_mtx)(void)_sx_xlock(((&bucket->ftb_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2632)); | |||
2633 | fpp = (fasttrap_provider_t **)&bucket->ftb_data; | |||
2634 | while ((fp = *fpp) != NULL((void *)0)) { | |||
2635 | /* | |||
2636 | * Acquire and release the lock as a simple way of | |||
2637 | * waiting for any other consumer to finish with | |||
2638 | * this provider. A thread must first acquire the | |||
2639 | * bucket lock so there's no chance of another thread | |||
2640 | * blocking on the provider's lock. | |||
2641 | */ | |||
2642 | mutex_enter(&fp->ftp_mtx)(void)_sx_xlock(((&fp->ftp_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2642)); | |||
2643 | mutex_exit(&fp->ftp_mtx)_sx_xunlock(((&fp->ftp_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2643)); | |||
2644 | ||||
2645 | if (dtrace_unregister(fp->ftp_provid) != 0) { | |||
2646 | fail = 1; | |||
2647 | fpp = &fp->ftp_next; | |||
2648 | } else { | |||
2649 | *fpp = fp->ftp_next; | |||
2650 | fasttrap_provider_free(fp); | |||
2651 | } | |||
2652 | } | |||
2653 | ||||
2654 | mutex_exit(&bucket->ftb_mtx)_sx_xunlock(((&bucket->ftb_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2654)); | |||
2655 | } | |||
2656 | ||||
2657 | if (fail) { | |||
2658 | (void) dtrace_meta_register("fasttrap", &fasttrap_mops, NULL((void *)0), | |||
2659 | &fasttrap_meta_id); | |||
2660 | ||||
2661 | return (-1); | |||
2662 | } | |||
2663 | ||||
2664 | /* | |||
2665 | * Stop new processes from entering these hooks now, before the | |||
2666 | * fasttrap_cleanup thread runs. That way all processes will hopefully | |||
2667 | * be out of these hooks before we free fasttrap_provs.fth_table | |||
2668 | */ | |||
2669 | ASSERT(dtrace_fasttrap_fork == &fasttrap_fork)((void)0); | |||
2670 | dtrace_fasttrap_fork = NULL((void *)0); | |||
2671 | ||||
2672 | ASSERT(dtrace_fasttrap_exec == &fasttrap_exec_exit)((void)0); | |||
2673 | dtrace_fasttrap_exec = NULL((void *)0); | |||
2674 | ||||
2675 | ASSERT(dtrace_fasttrap_exit == &fasttrap_exec_exit)((void)0); | |||
2676 | dtrace_fasttrap_exit = NULL((void *)0); | |||
2677 | ||||
2678 | mtx_lock(&fasttrap_cleanup_mtx)__mtx_lock_flags(&((((&fasttrap_cleanup_mtx))))->mtx_lock , ((0)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2678)); | |||
2679 | fasttrap_cleanup_drain = 1; | |||
2680 | /* Wait for the cleanup thread to finish up and signal us. */ | |||
2681 | wakeup(&fasttrap_cleanup_cv); | |||
2682 | mtx_sleep(&fasttrap_cleanup_drain, &fasttrap_cleanup_mtx, 0, "ftcld",_sleep((&fasttrap_cleanup_drain), &(&fasttrap_cleanup_mtx )->lock_object, (0), ("ftcld"), tick_sbt * (0), 0, 0x0100) | |||
2683 | 0)_sleep((&fasttrap_cleanup_drain), &(&fasttrap_cleanup_mtx )->lock_object, (0), ("ftcld"), tick_sbt * (0), 0, 0x0100); | |||
2684 | fasttrap_cleanup_proc = NULL((void *)0); | |||
2685 | mtx_destroy(&fasttrap_cleanup_mtx)_mtx_destroy(&(&fasttrap_cleanup_mtx)->mtx_lock); | |||
2686 | ||||
2687 | #ifdef DEBUG | |||
2688 | mutex_enter(&fasttrap_count_mtx)(void)_sx_xlock(((&fasttrap_count_mtx)), 0, ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2688)); | |||
2689 | ASSERT(fasttrap_pid_count == 0)((void)0); | |||
2690 | mutex_exit(&fasttrap_count_mtx)_sx_xunlock(((&fasttrap_count_mtx)), ("/usr/src/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c" ), (2690)); | |||
2691 | #endif | |||
2692 | ||||
2693 | #ifndef illumos | |||
2694 | EVENTHANDLER_DEREGISTER(thread_dtor, fasttrap_thread_dtor_tag)do { struct eventhandler_list *_el; if ((_el = eventhandler_find_list ("thread_dtor")) != ((void *)0)) eventhandler_deregister(_el, fasttrap_thread_dtor_tag); } while(0); | |||
2695 | ||||
2696 | for (i = 0; i < fasttrap_tpoints.fth_nent; i++) | |||
2697 | mutex_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx)sx_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx); | |||
2698 | for (i = 0; i < fasttrap_provs.fth_nent; i++) | |||
2699 | mutex_destroy(&fasttrap_provs.fth_table[i].ftb_mtx)sx_destroy(&fasttrap_provs.fth_table[i].ftb_mtx); | |||
2700 | for (i = 0; i < fasttrap_procs.fth_nent; i++) | |||
2701 | mutex_destroy(&fasttrap_procs.fth_table[i].ftb_mtx)sx_destroy(&fasttrap_procs.fth_table[i].ftb_mtx); | |||
2702 | #endif | |||
2703 | kmem_free(fasttrap_tpoints.fth_table,zfs_kmem_free((fasttrap_tpoints.fth_table), (fasttrap_tpoints .fth_nent * sizeof (fasttrap_bucket_t))) | |||
2704 | fasttrap_tpoints.fth_nent * sizeof (fasttrap_bucket_t))zfs_kmem_free((fasttrap_tpoints.fth_table), (fasttrap_tpoints .fth_nent * sizeof (fasttrap_bucket_t))); | |||
2705 | fasttrap_tpoints.fth_nent = 0; | |||
2706 | ||||
2707 | kmem_free(fasttrap_provs.fth_table,zfs_kmem_free((fasttrap_provs.fth_table), (fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t))) | |||
2708 | fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t))zfs_kmem_free((fasttrap_provs.fth_table), (fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t))); | |||
2709 | fasttrap_provs.fth_nent = 0; | |||
2710 | ||||
2711 | kmem_free(fasttrap_procs.fth_table,zfs_kmem_free((fasttrap_procs.fth_table), (fasttrap_procs.fth_nent * sizeof (fasttrap_bucket_t))) | |||
2712 | fasttrap_procs.fth_nent * sizeof (fasttrap_bucket_t))zfs_kmem_free((fasttrap_procs.fth_table), (fasttrap_procs.fth_nent * sizeof (fasttrap_bucket_t))); | |||
2713 | fasttrap_procs.fth_nent = 0; | |||
2714 | ||||
2715 | #ifndef illumos | |||
2716 | destroy_dev(fasttrap_cdev); | |||
2717 | mutex_destroy(&fasttrap_count_mtx)sx_destroy(&fasttrap_count_mtx); | |||
2718 | rm_destroy(&fasttrap_tp_lock); | |||
2719 | #endif | |||
2720 | ||||
2721 | return (0); | |||
2722 | } | |||
2723 | ||||
2724 | /* ARGSUSED */ | |||
2725 | static int | |||
2726 | fasttrap_modevent(module_t mod __unused__attribute__((__unused__)), int type, void *data __unused__attribute__((__unused__))) | |||
2727 | { | |||
2728 | int error = 0; | |||
2729 | ||||
2730 | switch (type) { | |||
2731 | case MOD_LOAD: | |||
2732 | break; | |||
2733 | ||||
2734 | case MOD_UNLOAD: | |||
2735 | break; | |||
2736 | ||||
2737 | case MOD_SHUTDOWN: | |||
2738 | break; | |||
2739 | ||||
2740 | default: | |||
2741 | error = EOPNOTSUPP45; | |||
2742 | break; | |||
2743 | } | |||
2744 | return (error); | |||
2745 | } | |||
2746 | ||||
2747 | SYSINIT(fasttrap_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fasttrap_load,static struct sysinit fasttrap_load_sys_init = { SI_SUB_DTRACE_PROVIDER , SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)fasttrap_load , ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysinit_set" ); __asm__(".globl " "__stop_set_sysinit_set"); static void const * const __set_sysinit_set_sym_fasttrap_load_sys_init __attribute__ ((__section__("set_" "sysinit_set"))) __attribute__((__used__ )) = &(fasttrap_load_sys_init) | |||
2748 | NULL)static struct sysinit fasttrap_load_sys_init = { SI_SUB_DTRACE_PROVIDER , SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)fasttrap_load , ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysinit_set" ); __asm__(".globl " "__stop_set_sysinit_set"); static void const * const __set_sysinit_set_sym_fasttrap_load_sys_init __attribute__ ((__section__("set_" "sysinit_set"))) __attribute__((__used__ )) = &(fasttrap_load_sys_init); | |||
2749 | SYSUNINIT(fasttrap_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,static struct sysinit fasttrap_unload_sys_uninit = { SI_SUB_DTRACE_PROVIDER , SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)fasttrap_unload , ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysuninit_set" ); __asm__(".globl " "__stop_set_sysuninit_set"); static void const * const __set_sysuninit_set_sym_fasttrap_unload_sys_uninit __attribute__((__section__("set_" "sysuninit_set"))) __attribute__ ((__used__)) = &(fasttrap_unload_sys_uninit) | |||
2750 | fasttrap_unload, NULL)static struct sysinit fasttrap_unload_sys_uninit = { SI_SUB_DTRACE_PROVIDER , SI_ORDER_ANY, (sysinit_cfunc_t)(sysinit_nfunc_t)fasttrap_unload , ((void *)(((void *)0))) }; __asm__(".globl " "__start_set_sysuninit_set" ); __asm__(".globl " "__stop_set_sysuninit_set"); static void const * const __set_sysuninit_set_sym_fasttrap_unload_sys_uninit __attribute__((__section__("set_" "sysuninit_set"))) __attribute__ ((__used__)) = &(fasttrap_unload_sys_uninit); | |||
2751 | ||||
2752 | DEV_MODULE(fasttrap, fasttrap_modevent, NULL)static moduledata_t fasttrap_mod = { "fasttrap", fasttrap_modevent , ((void *)0) }; static struct mod_depend _fasttrap_depend_on_kernel __attribute__((__section__(".data"))) = { 1100122, 1100122, ( ((((1100122)+((100000)-1))/(100000))*(100000)) - 1) }; static struct mod_metadata _mod_metadata_md_fasttrap_on_kernel = { 1 , 1, &_fasttrap_depend_on_kernel, "kernel" }; __asm__(".globl " "__start_set_modmetadata_set"); __asm__(".globl " "__stop_set_modmetadata_set" ); static void const * const __set_modmetadata_set_sym__mod_metadata_md_fasttrap_on_kernel __attribute__((__section__("set_" "modmetadata_set"))) __attribute__ ((__used__)) = &(_mod_metadata_md_fasttrap_on_kernel); static struct mod_metadata _mod_metadata_md_fasttrap = { 1, 2, & fasttrap_mod, "fasttrap" }; __asm__(".globl " "__start_set_modmetadata_set" ); __asm__(".globl " "__stop_set_modmetadata_set"); static void const * const __set_modmetadata_set_sym__mod_metadata_md_fasttrap __attribute__((__section__("set_" "modmetadata_set"))) __attribute__ ((__used__)) = &(_mod_metadata_md_fasttrap); static struct sysinit fasttrapmodule_sys_init = { SI_SUB_DRIVERS, SI_ORDER_MIDDLE , (sysinit_cfunc_t)(sysinit_nfunc_t)module_register_init, ((void *)(&fasttrap_mod)) }; __asm__(".globl " "__start_set_sysinit_set" ); __asm__(".globl " "__stop_set_sysinit_set"); static void const * const __set_sysinit_set_sym_fasttrapmodule_sys_init __attribute__ ((__section__("set_" "sysinit_set"))) __attribute__((__used__ )) = &(fasttrapmodule_sys_init); struct __hack; | |||
2753 | MODULE_VERSION(fasttrap, 1)static struct mod_version _fasttrap_version __attribute__((__section__ (".data"))) = { 1 }; static struct mod_metadata _mod_metadata_fasttrap_version = { 1, 3, &_fasttrap_version, "fasttrap" }; __asm__(".globl " "__start_set_modmetadata_set"); __asm__(".globl " "__stop_set_modmetadata_set" ); static void const * const __set_modmetadata_set_sym__mod_metadata_fasttrap_version __attribute__((__section__("set_" "modmetadata_set"))) __attribute__ ((__used__)) = &(_mod_metadata_fasttrap_version); | |||
2754 | MODULE_DEPEND(fasttrap, dtrace, 1, 1, 1)static struct mod_depend _fasttrap_depend_on_dtrace __attribute__ ((__section__(".data"))) = { 1, 1, 1 }; static struct mod_metadata _mod_metadata_md_fasttrap_on_dtrace = { 1, 1, &_fasttrap_depend_on_dtrace , "dtrace" }; __asm__(".globl " "__start_set_modmetadata_set" ); __asm__(".globl " "__stop_set_modmetadata_set"); static void const * const __set_modmetadata_set_sym__mod_metadata_md_fasttrap_on_dtrace __attribute__((__section__("set_" "modmetadata_set"))) __attribute__ ((__used__)) = &(_mod_metadata_md_fasttrap_on_dtrace); | |||
2755 | MODULE_DEPEND(fasttrap, opensolaris, 1, 1, 1)static struct mod_depend _fasttrap_depend_on_opensolaris __attribute__ ((__section__(".data"))) = { 1, 1, 1 }; static struct mod_metadata _mod_metadata_md_fasttrap_on_opensolaris = { 1, 1, &_fasttrap_depend_on_opensolaris , "opensolaris" }; __asm__(".globl " "__start_set_modmetadata_set" ); __asm__(".globl " "__stop_set_modmetadata_set"); static void const * const __set_modmetadata_set_sym__mod_metadata_md_fasttrap_on_opensolaris __attribute__((__section__("set_" "modmetadata_set"))) __attribute__ ((__used__)) = &(_mod_metadata_md_fasttrap_on_opensolaris ); |