1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * Interface to close a tnfctl handle
30 */
31
32 #include "tnfctl_int.h"
33 #include "kernel_int.h"
34 #include "dbg.h"
35
36 #include <stdlib.h>
37 #include <signal.h>
38 #include <errno.h>
39
40 /* for bug 1253419 - guard against multiple tracing */
41
42 extern mutex_t _tnfctl_internalguard_lock;
43
44 /*
45 * Close a tnfctl handle - close any open fds and free up any memory
46 * that was allocated.
47 */
48 tnfctl_errcode_t
tnfctl_close(tnfctl_handle_t * hdl,tnfctl_targ_op_t action)49 tnfctl_close(tnfctl_handle_t *hdl, tnfctl_targ_op_t action)
50 {
51 tnfctl_errcode_t prexstat;
52 prb_status_t prbstat;
53 prb_proc_ctl_t *proc_p;
54 tnfctl_probe_t *probe_hdl, *tmp_hdl;
55
56 if (hdl == NULL)
57 return (TNFCTL_ERR_NONE);
58
59 if (hdl->mode == KERNEL_MODE) {
60 prexstat = _tnfctl_prbk_close(hdl);
61 if (prexstat)
62 return (prexstat);
63 }
64
65 if (hdl->mode == INTERNAL_MODE) {
66 _tnfctl_internal_releaselock();
67 } else if (hdl->mode != KERNEL_MODE) {
68 _tnfctl_external_releaselock(hdl);
69 }
70
71 _tnfctl_free_objs_and_probes(hdl);
72
73 /* free probe handles */
74 probe_hdl = hdl->probe_handle_list_head;
75 while (probe_hdl != NULL) {
76 /* call the destructor function for client probe data */
77 if (hdl->destroy_func)
78 hdl->destroy_func(probe_hdl->client_registered_data);
79 tmp_hdl = probe_hdl;
80 probe_hdl = probe_hdl->next;
81 free(tmp_hdl);
82 }
83 hdl->probe_handle_list_head = NULL;
84
85 if (hdl->mode != DIRECT_MODE) {
86 /* indirect, internal, or kernel mode */
87 free(hdl);
88 return (TNFCTL_ERR_NONE);
89 }
90
91 /* DIRECT_MODE */
92
93 proc_p = hdl->proc_p;
94 if (proc_p == NULL) {
95 free(hdl);
96 return (TNFCTL_ERR_NONE);
97 }
98
99 switch (action) {
100 case TNFCTL_TARG_DEFAULT:
101 break;
102 case TNFCTL_TARG_KILL:
103 prbstat = prb_proc_setklc(proc_p, B_TRUE);
104 if (prbstat)
105 return (_tnfctl_map_to_errcode(prbstat));
106 prbstat = prb_proc_setrlc(proc_p, B_FALSE);
107 if (prbstat)
108 return (_tnfctl_map_to_errcode(prbstat));
109 break;
110 case TNFCTL_TARG_RESUME:
111 prbstat = prb_proc_setklc(proc_p, B_FALSE);
112 if (prbstat)
113 return (_tnfctl_map_to_errcode(prbstat));
114 prbstat = prb_proc_setrlc(proc_p, B_TRUE);
115 if (prbstat)
116 return (_tnfctl_map_to_errcode(prbstat));
117 break;
118 case TNFCTL_TARG_SUSPEND:
119 prbstat = prb_proc_setklc(proc_p, B_FALSE);
120 if (prbstat)
121 return (_tnfctl_map_to_errcode(prbstat));
122 prbstat = prb_proc_setrlc(proc_p, B_FALSE);
123 if (prbstat)
124 return (_tnfctl_map_to_errcode(prbstat));
125 break;
126 default:
127 return (TNFCTL_ERR_BADARG);
128 }
129 prbstat = prb_proc_close(proc_p);
130 free(hdl);
131 return (_tnfctl_map_to_errcode(prbstat));
132 }
133
134 tnfctl_errcode_t
_tnfctl_internal_releaselock()135 _tnfctl_internal_releaselock()
136 {
137 mutex_lock(&_tnfctl_internalguard_lock);
138 _tnfctl_internal_tracing_flag = 0;
139 mutex_unlock(&_tnfctl_internalguard_lock);
140 return (TNFCTL_ERR_NONE);
141 }
142
143 tnfctl_errcode_t
_tnfctl_external_releaselock(tnfctl_handle_t * hdl)144 _tnfctl_external_releaselock(tnfctl_handle_t *hdl)
145 {
146 tnfctl_errcode_t prexstat;
147 prb_status_t prbstat;
148 uintptr_t targ_symbol_ptr;
149 pid_t pidzero = 0;
150
151 prexstat = _tnfctl_sym_find(hdl, TNFCTL_EXTERNAL_TRACEDPID,
152 &targ_symbol_ptr);
153 if (prexstat) {
154 return (prexstat);
155 }
156 prbstat = hdl->p_write(hdl->proc_p, targ_symbol_ptr,
157 &pidzero, sizeof (pidzero));
158 if (prbstat) {
159 return (_tnfctl_map_to_errcode(prbstat));
160 }
161 return (TNFCTL_ERR_NONE);
162 }
163