]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/cddl/dev/dtmalloc/dtmalloc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / cddl / dev / dtmalloc / dtmalloc.c
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 2006-2008 John Birrell jb@freebsd.org
22  *
23  * $FreeBSD$
24  *
25  */
26
27 #include <sys/cdefs.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/conf.h>
31 #include <sys/ctype.h>
32 #include <sys/kernel.h>
33 #include <sys/malloc.h>
34 #include <sys/module.h>
35
36 #include <sys/dtrace.h>
37 #include <sys/dtrace_bsd.h>
38
39 static d_open_t dtmalloc_open;
40 static int      dtmalloc_unload(void);
41 static void     dtmalloc_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
42 static void     dtmalloc_provide(void *, dtrace_probedesc_t *);
43 static void     dtmalloc_destroy(void *, dtrace_id_t, void *);
44 static void     dtmalloc_enable(void *, dtrace_id_t, void *);
45 static void     dtmalloc_disable(void *, dtrace_id_t, void *);
46 static void     dtmalloc_load(void *);
47
48 static struct cdevsw dtmalloc_cdevsw = {
49         .d_version      = D_VERSION,
50         .d_open         = dtmalloc_open,
51         .d_name         = "dtmalloc",
52 };
53
54 static dtrace_pattr_t dtmalloc_attr = {
55 { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
56 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
57 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
58 { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
59 { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
60 };
61
62 static dtrace_pops_t dtmalloc_pops = {
63         dtmalloc_provide,
64         NULL,
65         dtmalloc_enable,
66         dtmalloc_disable,
67         NULL,
68         NULL,
69         dtmalloc_getargdesc,
70         NULL,
71         NULL,
72         dtmalloc_destroy
73 };
74
75 static struct cdev              *dtmalloc_cdev;
76 static dtrace_provider_id_t     dtmalloc_id;
77
78 static void
79 dtmalloc_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
80 {
81         const char *p = NULL;
82
83         switch (desc->dtargd_ndx) {
84         case 0:
85                 p = "struct malloc_type *";
86                 break;
87         case 1:
88                 p = "struct malloc_type_internal *";
89                 break;
90         case 2:
91                 p = "struct malloc_type_stats *";
92                 break;
93         case 3:
94                 p = "unsigned long";
95                 break;
96         case 4:
97                 p = "int";
98                 break;
99         default:
100                 desc->dtargd_ndx = DTRACE_ARGNONE;
101                 break;
102         }
103
104         if (p != NULL)
105                 strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
106
107         return;
108 }
109
110 static void
111 dtmalloc_type_cb(struct malloc_type *mtp, void *arg __unused)
112 {
113         char name[DTRACE_FUNCNAMELEN];
114         struct malloc_type_internal *mtip = mtp->ks_handle;
115         int i;
116
117         /*
118          * malloc_type descriptions are allowed to contain whitespace, but
119          * DTrace probe identifiers are not, so replace the whitespace with
120          * underscores.
121          */
122         strlcpy(name, mtp->ks_shortdesc, sizeof(name));
123         for (i = 0; name[i] != 0; i++)
124                 if (isspace(name[i]))
125                         name[i] = '_';
126
127         if (dtrace_probe_lookup(dtmalloc_id, NULL, name, "malloc") != 0)
128                 return;
129
130         (void) dtrace_probe_create(dtmalloc_id, NULL, name, "malloc", 0,
131             &mtip->mti_probes[DTMALLOC_PROBE_MALLOC]);
132         (void) dtrace_probe_create(dtmalloc_id, NULL, name, "free", 0,
133             &mtip->mti_probes[DTMALLOC_PROBE_FREE]);
134 }
135
136 static void
137 dtmalloc_provide(void *arg, dtrace_probedesc_t *desc)
138 {
139         if (desc != NULL)
140                 return;
141
142         malloc_type_list(dtmalloc_type_cb, desc);
143 }
144
145 static void
146 dtmalloc_destroy(void *arg, dtrace_id_t id, void *parg)
147 {
148 }
149
150 static void
151 dtmalloc_enable(void *arg, dtrace_id_t id, void *parg)
152 {
153         uint32_t *p = parg;
154         *p = id;
155 }
156
157 static void
158 dtmalloc_disable(void *arg, dtrace_id_t id, void *parg)
159 {
160         uint32_t *p = parg;
161         *p = 0;
162 }
163
164 static void
165 dtmalloc_load(void *dummy)
166 {
167         /* Create the /dev/dtrace/dtmalloc entry. */
168         dtmalloc_cdev = make_dev(&dtmalloc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
169             "dtrace/dtmalloc");
170
171         if (dtrace_register("dtmalloc", &dtmalloc_attr, DTRACE_PRIV_USER,
172             NULL, &dtmalloc_pops, NULL, &dtmalloc_id) != 0)
173                 return;
174
175         dtrace_malloc_probe = dtrace_probe;
176 }
177
178
179 static int
180 dtmalloc_unload()
181 {
182         int error = 0;
183
184         dtrace_malloc_probe = NULL;
185
186         if ((error = dtrace_unregister(dtmalloc_id)) != 0)
187                 return (error);
188
189         destroy_dev(dtmalloc_cdev);
190
191         return (error);
192 }
193
194 static int
195 dtmalloc_modevent(module_t mod __unused, int type, void *data __unused)
196 {
197         int error = 0;
198
199         switch (type) {
200         case MOD_LOAD:
201                 break;
202
203         case MOD_UNLOAD:
204                 break;
205
206         case MOD_SHUTDOWN:
207                 break;
208
209         default:
210                 error = EOPNOTSUPP;
211                 break;
212
213         }
214
215         return (error);
216 }
217
218 static int
219 dtmalloc_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *td __unused)
220 {
221         return (0);
222 }
223
224 SYSINIT(dtmalloc_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, dtmalloc_load, NULL);
225 SYSUNINIT(dtmalloc_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, dtmalloc_unload, NULL);
226
227 DEV_MODULE(dtmalloc, dtmalloc_modevent, NULL);
228 MODULE_VERSION(dtmalloc, 1);
229 MODULE_DEPEND(dtmalloc, dtrace, 1, 1, 1);
230 MODULE_DEPEND(dtmalloc, opensolaris, 1, 1, 1);