4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Published interfaces for probe control.
43 #include "tnfctl_int.h"
44 #include "kernel_int.h"
48 tnfctl_probe_op_t func_p
;
52 tnfctl_errcode_t
_tnfctl_destructor_wrapper(tnfctl_handle_t
*,
53 prbctlref_t
*, void *);
54 tnfctl_errcode_t
_tnfctl_creator_wrapper(tnfctl_handle_t
*,
55 prbctlref_t
*, void *);
56 static tnfctl_errcode_t
apply_func(tnfctl_handle_t
*, prbctlref_t
*, void *);
57 static tnfctl_errcode_t
check_operation(tnfctl_handle_t
*, tnfctl_probe_t
*);
60 tnfctl_register_funcs(tnfctl_handle_t
*hndl
,
61 void *(*create_func
)(tnfctl_handle_t
*, tnfctl_probe_t
*),
62 void (*destroy_func
)(void *))
64 tnfctl_errcode_t prexstat
;
66 if (hndl
->destroy_func
) {
68 * not the first time the register_funcs() is being called
69 * First call currently registered destroy_func on all
72 prexstat
= _tnfctl_probes_traverse(hndl
,
73 _tnfctl_destructor_wrapper
, NULL
);
78 /* set up new creator and destructor functions */
79 hndl
->create_func
= create_func
;
80 hndl
->destroy_func
= destroy_func
;
82 /* call new creator function for all current probes */
84 prexstat
= _tnfctl_probes_traverse(hndl
,
85 _tnfctl_creator_wrapper
, NULL
);
90 return (TNFCTL_ERR_NONE
);
94 _tnfctl_destructor_wrapper(tnfctl_handle_t
*hndl
, prbctlref_t
*probe
, void *cd
)
96 assert(hndl
->destroy_func
);
97 hndl
->destroy_func(probe
->probe_handle
->client_registered_data
);
99 return (TNFCTL_ERR_NONE
);
103 _tnfctl_creator_wrapper(tnfctl_handle_t
*hndl
, prbctlref_t
*probe
, void *cd
)
105 tnfctl_probe_t
*p_handle
;
107 assert(hndl
->create_func
);
108 p_handle
= probe
->probe_handle
;
109 p_handle
->client_registered_data
= hndl
->create_func(hndl
, p_handle
);
111 return (TNFCTL_ERR_NONE
);
115 tnfctl_probe_apply(tnfctl_handle_t
*hndl
, tnfctl_probe_op_t func_p
,
118 struct pr_func_args pr_args
;
119 tnfctl_errcode_t prexstat
;
121 pr_args
.func_p
= func_p
;
122 pr_args
.calldata
= calldata
;
123 prexstat
= _tnfctl_probes_traverse(hndl
, apply_func
, &pr_args
);
128 tnfctl_probe_apply_ids(tnfctl_handle_t
*hndl
, ulong_t probe_count
,
129 ulong_t
*probe_ids
, tnfctl_probe_op_t func_p
,
136 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
137 boolean_t release_lock
;
139 /*LINTED statement has no consequent: else*/
140 LOCK_SYNC(hndl
, prexstat
, release_lock
);
142 /* select probes based on numbers */
144 for (i
= 0; i
< probe_count
; i
++, id_p
++) {
145 obj_p
= hndl
->objlist
;
147 if ((*id_p
>= obj_p
->min_probe_num
) &&
148 (*id_p
< (obj_p
->min_probe_num
+
155 prexstat
= TNFCTL_ERR_INVALIDPROBE
;
158 pos
= *id_p
- obj_p
->min_probe_num
;
159 probe
= &(obj_p
->probes
[pos
]);
160 prexstat
= func_p(hndl
, probe
->probe_handle
, calldata
);
166 /*LINTED statement has no consequent: else*/
167 UNLOCK(hndl
, release_lock
);
172 tnfctl_probe_state_get(tnfctl_handle_t
*hndl
, tnfctl_probe_t
*probe_hndl
,
173 tnfctl_probe_state_t
*state_p
)
175 tnf_probe_control_t
*prbctl_p
;
176 boolean_t release_lock
;
177 tnfctl_errcode_t prexstat
= TNFCTL_ERR_NONE
;
179 uintptr_t *func_addrs
;
181 if (hndl
->mode
== KERNEL_MODE
) {
182 prexstat
= _tnfctl_refresh_kernel(hndl
);
187 /*LINTED statement has no consequent: else*/
188 LOCK_SYNC(hndl
, prexstat
, release_lock
);
190 if (probe_hndl
->valid
== B_FALSE
) {
191 prexstat
= TNFCTL_ERR_INVALIDPROBE
;
195 state_p
->id
= probe_hndl
->probe_p
->probe_id
;
196 state_p
->attr_string
= probe_hndl
->probe_p
->attr_string
;
198 prbctl_p
= &probe_hndl
->probe_p
->wrkprbctl
;
199 state_p
->enabled
= (prbctl_p
->test_func
) ? B_TRUE
: B_FALSE
;
200 state_p
->traced
= (prbctl_p
->commit_func
==
201 (tnf_probe_func_t
) hndl
->commitfunc
) ? B_TRUE
: B_FALSE
;
202 state_p
->new_probe
= probe_hndl
->probe_p
->obj
->new_probe
;
203 state_p
->obj_name
= probe_hndl
->probe_p
->obj
->objname
;
204 state_p
->client_registered_data
= probe_hndl
->client_registered_data
;
206 if (hndl
->mode
== KERNEL_MODE
) {
207 state_p
->func_names
= NULL
;
208 state_p
->func_addrs
= NULL
;
209 /* skip code upto label */
213 /* process mode - get the probe functions */
214 prexstat
= _tnfctl_comb_decode(hndl
, (uintptr_t) prbctl_p
->probe_func
,
215 &func_names
, &func_addrs
);
219 /* if there are any probe functions */
220 if (func_names
[0] != NULL
) {
221 state_p
->func_names
= (const char * const *) func_names
;
222 state_p
->func_addrs
= func_addrs
;
224 state_p
->func_names
= NULL
;
225 state_p
->func_addrs
= NULL
;
229 /*LINTED statement has no consequent: else*/
230 UNLOCK(hndl
, release_lock
);
234 static tnfctl_errcode_t
235 check_operation(tnfctl_handle_t
*hndl
, tnfctl_probe_t
*probe_hndl
)
237 tnfctl_errcode_t prexstat
;
239 if (hndl
->mode
== KERNEL_MODE
) {
240 prexstat
= _tnfctl_refresh_kernel(hndl
);
243 } else if (hndl
->trace_buf_state
== TNFCTL_BUF_NONE
) {
244 /* process tracing */
245 return (TNFCTL_ERR_NOBUF
);
248 if (hndl
->trace_buf_state
== TNFCTL_BUF_BROKEN
)
249 return (TNFCTL_ERR_BUFBROKEN
);
251 if (probe_hndl
->valid
== B_FALSE
) {
252 return (TNFCTL_ERR_INVALIDPROBE
);
255 return (TNFCTL_ERR_NONE
);
259 tnfctl_probe_enable(tnfctl_handle_t
*hndl
, tnfctl_probe_t
*probe_hndl
, void *cd
)
261 tnf_probe_control_t
*prbctl_p
;
262 boolean_t release_lock
;
263 tnfctl_errcode_t prexstat
;
265 /*LINTED statement has no consequent: else*/
266 LOCK_SYNC(hndl
, prexstat
, release_lock
);
268 prexstat
= check_operation(hndl
, probe_hndl
);
272 prbctl_p
= &probe_hndl
->probe_p
->wrkprbctl
;
273 prbctl_p
->test_func
= (tnf_probe_test_func_t
) hndl
->testfunc
;
274 prexstat
= _tnfctl_flush_a_probe(hndl
, probe_hndl
->probe_p
,
275 offsetof(struct tnf_probe_control
, test_func
),
276 sizeof (tnf_probe_test_func_t
));
278 /*LINTED statement has no consequent: else*/
279 UNLOCK(hndl
, release_lock
);
284 tnfctl_probe_disable(tnfctl_handle_t
*hndl
, tnfctl_probe_t
*probe_hndl
,
287 tnf_probe_control_t
*prbctl_p
;
288 boolean_t release_lock
;
289 tnfctl_errcode_t prexstat
;
291 /*LINTED statement has no consequent: else*/
292 LOCK_SYNC(hndl
, prexstat
, release_lock
);
294 prexstat
= check_operation(hndl
, probe_hndl
);
298 prbctl_p
= &probe_hndl
->probe_p
->wrkprbctl
;
299 prbctl_p
->test_func
= (tnf_probe_test_func_t
) NULL
;
300 prexstat
= _tnfctl_flush_a_probe(hndl
, probe_hndl
->probe_p
,
301 offsetof(struct tnf_probe_control
, test_func
),
302 sizeof (tnf_probe_test_func_t
));
304 /*LINTED statement has no consequent: else*/
305 UNLOCK(hndl
, release_lock
);
310 tnfctl_probe_trace(tnfctl_handle_t
*hndl
, tnfctl_probe_t
*probe_hndl
, void *cd
)
312 tnf_probe_control_t
*prbctl_p
;
313 boolean_t release_lock
;
314 tnfctl_errcode_t prexstat
;
316 /*LINTED statement has no consequent: else*/
317 LOCK_SYNC(hndl
, prexstat
, release_lock
);
319 prexstat
= check_operation(hndl
, probe_hndl
);
323 prbctl_p
= &probe_hndl
->probe_p
->wrkprbctl
;
324 prbctl_p
->commit_func
= (tnf_probe_func_t
) hndl
->commitfunc
;
325 prexstat
= _tnfctl_flush_a_probe(hndl
, probe_hndl
->probe_p
,
326 offsetof(struct tnf_probe_control
, commit_func
),
327 sizeof (tnf_probe_func_t
));
330 /*LINTED statement has no consequent: else*/
331 UNLOCK(hndl
, release_lock
);
336 tnfctl_probe_untrace(tnfctl_handle_t
*hndl
, tnfctl_probe_t
*probe_hndl
,
339 tnf_probe_control_t
*prbctl_p
;
340 boolean_t release_lock
;
341 tnfctl_errcode_t prexstat
;
343 /*LINTED statement has no consequent: else*/
344 LOCK_SYNC(hndl
, prexstat
, release_lock
);
346 prexstat
= check_operation(hndl
, probe_hndl
);
350 prbctl_p
= &probe_hndl
->probe_p
->wrkprbctl
;
351 prbctl_p
->commit_func
= (tnf_probe_func_t
) hndl
->rollbackfunc
;
352 prexstat
= _tnfctl_flush_a_probe(hndl
, probe_hndl
->probe_p
,
353 offsetof(struct tnf_probe_control
, commit_func
),
354 sizeof (tnf_probe_func_t
));
357 /*LINTED statement has no consequent: else*/
358 UNLOCK(hndl
, release_lock
);
363 tnfctl_probe_connect(tnfctl_handle_t
*hndl
, tnfctl_probe_t
*probe_hndl
,
364 const char *lib_base_name
, const char *func
)
366 tnf_probe_control_t
*prbctl_p
;
367 boolean_t release_lock
;
368 tnfctl_errcode_t prexstat
;
372 if (hndl
->mode
== KERNEL_MODE
)
373 return (TNFCTL_ERR_BADARG
);
375 /*LINTED statement has no consequent: else*/
376 LOCK_SYNC(hndl
, prexstat
, release_lock
);
378 prexstat
= check_operation(hndl
, probe_hndl
);
383 prexstat
= TNFCTL_ERR_NONE
;
388 prexstat
= _tnfctl_sym_obj_find(hndl
, lib_base_name
, func
,
391 prexstat
= _tnfctl_sym_find(hndl
, func
, &func_addr
);
393 /* check if function address was found */
397 prbctl_p
= &probe_hndl
->probe_p
->wrkprbctl
;
398 prexstat
= _tnfctl_comb_build(hndl
, PRB_COMB_CHAIN
,
399 func_addr
, (uintptr_t) prbctl_p
->probe_func
,
403 prbctl_p
->probe_func
= (tnf_probe_func_t
) comb
;
404 prexstat
= _tnfctl_flush_a_probe(hndl
, probe_hndl
->probe_p
,
405 offsetof(struct tnf_probe_control
, probe_func
),
406 sizeof (tnf_probe_func_t
));
409 /*LINTED statement has no consequent: else*/
410 UNLOCK(hndl
, release_lock
);
415 tnfctl_probe_disconnect_all(tnfctl_handle_t
*hndl
, tnfctl_probe_t
*probe_hndl
,
418 tnf_probe_control_t
*prbctl_p
;
419 boolean_t release_lock
;
420 tnfctl_errcode_t prexstat
;
422 if (hndl
->mode
== KERNEL_MODE
)
423 return (TNFCTL_ERR_BADARG
);
425 /*LINTED statement has no consequent: else*/
426 LOCK_SYNC(hndl
, prexstat
, release_lock
);
428 prexstat
= check_operation(hndl
, probe_hndl
);
432 prbctl_p
= &probe_hndl
->probe_p
->wrkprbctl
;
433 prbctl_p
->probe_func
= (tnf_probe_func_t
) hndl
->endfunc
;
434 prexstat
= _tnfctl_flush_a_probe(hndl
, probe_hndl
->probe_p
,
435 offsetof(struct tnf_probe_control
, probe_func
),
436 sizeof (tnf_probe_func_t
));
439 /*LINTED statement has no consequent: else*/
440 UNLOCK(hndl
, release_lock
);
445 * Important that this function be tail recursive to minimize depth
446 * of call chain that is called for every probe
448 static tnfctl_errcode_t
449 apply_func(tnfctl_handle_t
*hndl
, prbctlref_t
*probe
, void *cd
)
451 struct pr_func_args
*args
= cd
;
452 tnfctl_errcode_t prexstat
;
454 /* Call function only if match_func returns true */
455 prexstat
= (*(args
->func_p
))(hndl
, probe
->probe_handle
, args
->calldata
);