8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libtnfctl / probes_ext.c
blob5c4aed143072736ea61a41cd08d1f13a2208cf10
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Published interfaces for probe control.
32 #ifndef DEBUG
33 #define NDEBUG 1
34 #endif
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <assert.h>
41 #include <stddef.h>
43 #include "tnfctl_int.h"
44 #include "kernel_int.h"
45 #include "dbg.h"
47 struct pr_func_args {
48 tnfctl_probe_op_t func_p;
49 void *calldata;
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 *);
59 tnfctl_errcode_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
70 * probes
72 prexstat = _tnfctl_probes_traverse(hndl,
73 _tnfctl_destructor_wrapper, NULL);
74 if (prexstat)
75 return (prexstat);
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 */
83 if (create_func) {
84 prexstat = _tnfctl_probes_traverse(hndl,
85 _tnfctl_creator_wrapper, NULL);
86 if (prexstat)
87 return (prexstat);
90 return (TNFCTL_ERR_NONE);
93 tnfctl_errcode_t
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);
102 tnfctl_errcode_t
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);
114 tnfctl_errcode_t
115 tnfctl_probe_apply(tnfctl_handle_t *hndl, tnfctl_probe_op_t func_p,
116 void *calldata)
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);
124 return (prexstat);
127 tnfctl_errcode_t
128 tnfctl_probe_apply_ids(tnfctl_handle_t *hndl, ulong_t probe_count,
129 ulong_t *probe_ids, tnfctl_probe_op_t func_p,
130 void *calldata)
132 ulong_t *id_p;
133 ulong_t i, pos;
134 objlist_t *obj_p;
135 prbctlref_t *probe;
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 */
143 id_p = probe_ids;
144 for (i = 0; i < probe_count; i++, id_p++) {
145 obj_p = hndl->objlist;
146 while (obj_p) {
147 if ((*id_p >= obj_p->min_probe_num) &&
148 (*id_p < (obj_p->min_probe_num +
149 obj_p->probecnt))) {
150 break;
152 obj_p = obj_p->next;
154 if (obj_p == NULL) {
155 prexstat = TNFCTL_ERR_INVALIDPROBE;
156 goto end_of_func;
158 pos = *id_p - obj_p->min_probe_num;
159 probe = &(obj_p->probes[pos]);
160 prexstat = func_p(hndl, probe->probe_handle, calldata);
161 if (prexstat)
162 goto end_of_func;
165 end_of_func:
166 /*LINTED statement has no consequent: else*/
167 UNLOCK(hndl, release_lock);
168 return (prexstat);
171 tnfctl_errcode_t
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;
178 char **func_names;
179 uintptr_t *func_addrs;
181 if (hndl->mode == KERNEL_MODE) {
182 prexstat = _tnfctl_refresh_kernel(hndl);
183 if (prexstat)
184 return (prexstat);
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;
192 goto end_of_func;
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 */
210 goto end_of_func;
213 /* process mode - get the probe functions */
214 prexstat = _tnfctl_comb_decode(hndl, (uintptr_t) prbctl_p->probe_func,
215 &func_names, &func_addrs);
216 if (prexstat)
217 goto end_of_func;
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;
223 } else {
224 state_p->func_names = NULL;
225 state_p->func_addrs = NULL;
228 end_of_func:
229 /*LINTED statement has no consequent: else*/
230 UNLOCK(hndl, release_lock);
231 return (prexstat);
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);
241 if (prexstat)
242 return (prexstat);
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);
258 tnfctl_errcode_t
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);
269 if (prexstat)
270 goto end_of_func;
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));
277 end_of_func:
278 /*LINTED statement has no consequent: else*/
279 UNLOCK(hndl, release_lock);
280 return (prexstat);
283 tnfctl_errcode_t
284 tnfctl_probe_disable(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_hndl,
285 void *cd)
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);
295 if (prexstat)
296 goto end_of_func;
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));
303 end_of_func:
304 /*LINTED statement has no consequent: else*/
305 UNLOCK(hndl, release_lock);
306 return (prexstat);
309 tnfctl_errcode_t
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);
320 if (prexstat)
321 goto end_of_func;
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));
329 end_of_func:
330 /*LINTED statement has no consequent: else*/
331 UNLOCK(hndl, release_lock);
332 return (prexstat);
335 tnfctl_errcode_t
336 tnfctl_probe_untrace(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_hndl,
337 void *cd)
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);
347 if (prexstat)
348 goto end_of_func;
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));
356 end_of_func:
357 /*LINTED statement has no consequent: else*/
358 UNLOCK(hndl, release_lock);
359 return (prexstat);
362 tnfctl_errcode_t
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;
369 uintptr_t func_addr;
370 uintptr_t comb;
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);
379 if (prexstat)
380 goto end_of_func;
382 if (func == NULL) {
383 prexstat = TNFCTL_ERR_NONE;
384 goto end_of_func;
387 if (lib_base_name) {
388 prexstat = _tnfctl_sym_obj_find(hndl, lib_base_name, func,
389 &func_addr);
390 } else {
391 prexstat = _tnfctl_sym_find(hndl, func, &func_addr);
393 /* check if function address was found */
394 if (prexstat)
395 goto end_of_func;
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,
400 &comb);
401 if (prexstat)
402 goto end_of_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));
408 end_of_func:
409 /*LINTED statement has no consequent: else*/
410 UNLOCK(hndl, release_lock);
411 return (prexstat);
414 tnfctl_errcode_t
415 tnfctl_probe_disconnect_all(tnfctl_handle_t *hndl, tnfctl_probe_t *probe_hndl,
416 void *cd)
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);
429 if (prexstat)
430 goto end_of_func;
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));
438 end_of_func:
439 /*LINTED statement has no consequent: else*/
440 UNLOCK(hndl, release_lock);
441 return (prexstat);
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);
456 return (prexstat);