1 /* $NetBSD: dtmalloc.c,v 1.2 2010/02/21 01:46:33 darran Exp $ */
2
3 /*
4 * CDDL HEADER START
5 *
6 * The contents of this file are subject to the terms of the
7 * Common Development and Distribution License (the "License").
8 * You may not use this file except in compliance with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 *
23 * Portions Copyright 2006-2008 John Birrell jb@freebsd.org
24 *
25 * $FreeBSD: src/sys/cddl/dev/dtmalloc/dtmalloc.c,v 1.1.4.1 2009/08/03 08:13:06 kensmith Exp $
26 *
27 */
28
29 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/conf.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
35 #include <sys/module.h>
36
37 #include <sys/dtrace.h>
38 #include <sys/dtrace_bsd.h>
39
40 static d_open_t dtmalloc_open;
41 static int dtmalloc_unload(void);
42 static void dtmalloc_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
43 static void dtmalloc_provide(void *, dtrace_probedesc_t *);
44 static void dtmalloc_destroy(void *, dtrace_id_t, void *);
45 static void dtmalloc_enable(void *, dtrace_id_t, void *);
46 static void dtmalloc_disable(void *, dtrace_id_t, void *);
47 static void dtmalloc_load(void *);
48
49 static struct cdevsw dtmalloc_cdevsw = {
50 .d_version = D_VERSION,
51 .d_open = dtmalloc_open,
52 .d_name = "dtmalloc",
53 };
54
55 static dtrace_pattr_t dtmalloc_attr = {
56 { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
57 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
58 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
59 { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
60 { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
61 };
62
63 static dtrace_pops_t dtmalloc_pops = {
64 dtmalloc_provide,
65 NULL,
66 dtmalloc_enable,
67 dtmalloc_disable,
68 NULL,
69 NULL,
70 dtmalloc_getargdesc,
71 NULL,
72 NULL,
73 dtmalloc_destroy
74 };
75
76 static struct cdev *dtmalloc_cdev;
77 static dtrace_provider_id_t dtmalloc_id;
78
79 static void
dtmalloc_getargdesc(void * arg,dtrace_id_t id,void * parg,dtrace_argdesc_t * desc)80 dtmalloc_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
81 {
82 const char *p = NULL;
83
84 switch (desc->dtargd_ndx) {
85 case 0:
86 p = "struct malloc_type *";
87 break;
88 case 1:
89 p = "struct malloc_type_internal *";
90 break;
91 case 2:
92 p = "struct malloc_type_stats *";
93 break;
94 case 3:
95 p = "unsigned long";
96 break;
97 case 4:
98 p = "int";
99 break;
100 default:
101 desc->dtargd_ndx = DTRACE_ARGNONE;
102 break;
103 }
104
105 if (p != NULL)
106 strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
107
108 return;
109 }
110
111 static void
dtmalloc_type_cb(struct malloc_type * mtp,void * arg __unused)112 dtmalloc_type_cb(struct malloc_type *mtp, void *arg __unused)
113 {
114 char name[DTRACE_FUNCNAMELEN];
115 struct malloc_type_internal *mtip = mtp->ks_handle;
116
117 strlcpy(name, mtp->ks_shortdesc, sizeof(name));
118
119 if (dtrace_probe_lookup(dtmalloc_id, NULL, name, "malloc") != 0)
120 return;
121
122 (void) dtrace_probe_create(dtmalloc_id, NULL, name, "malloc", 0,
123 &mtip->mti_probes[DTMALLOC_PROBE_MALLOC]);
124 (void) dtrace_probe_create(dtmalloc_id, NULL, name, "free", 0,
125 &mtip->mti_probes[DTMALLOC_PROBE_FREE]);
126 }
127
128 static void
dtmalloc_provide(void * arg,dtrace_probedesc_t * desc)129 dtmalloc_provide(void *arg, dtrace_probedesc_t *desc)
130 {
131 if (desc != NULL)
132 return;
133
134 malloc_type_list(dtmalloc_type_cb, desc);
135 }
136
137 static void
dtmalloc_destroy(void * arg,dtrace_id_t id,void * parg)138 dtmalloc_destroy(void *arg, dtrace_id_t id, void *parg)
139 {
140 }
141
142 static void
dtmalloc_enable(void * arg,dtrace_id_t id,void * parg)143 dtmalloc_enable(void *arg, dtrace_id_t id, void *parg)
144 {
145 uint32_t *p = parg;
146 *p = id;
147 }
148
149 static void
dtmalloc_disable(void * arg,dtrace_id_t id,void * parg)150 dtmalloc_disable(void *arg, dtrace_id_t id, void *parg)
151 {
152 uint32_t *p = parg;
153 *p = 0;
154 }
155
156 static void
dtmalloc_load(void * dummy)157 dtmalloc_load(void *dummy)
158 {
159 /* Create the /dev/dtrace/dtmalloc entry. */
160 dtmalloc_cdev = make_dev(&dtmalloc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
161 "dtrace/dtmalloc");
162
163 if (dtrace_register("dtmalloc", &dtmalloc_attr, DTRACE_PRIV_USER,
164 NULL, &dtmalloc_pops, NULL, &dtmalloc_id) != 0)
165 return;
166
167 dtrace_malloc_probe = dtrace_probe;
168 }
169
170
171 static int
dtmalloc_unload()172 dtmalloc_unload()
173 {
174 int error = 0;
175
176 dtrace_malloc_probe = NULL;
177
178 if ((error = dtrace_unregister(dtmalloc_id)) != 0)
179 return (error);
180
181 destroy_dev(dtmalloc_cdev);
182
183 return (error);
184 }
185
186 static int
dtmalloc_modevent(module_t mod __unused,int type,void * data __unused)187 dtmalloc_modevent(module_t mod __unused, int type, void *data __unused)
188 {
189 int error = 0;
190
191 switch (type) {
192 case MOD_LOAD:
193 break;
194
195 case MOD_UNLOAD:
196 break;
197
198 case MOD_SHUTDOWN:
199 break;
200
201 default:
202 error = EOPNOTSUPP;
203 break;
204
205 }
206
207 return (error);
208 }
209
210 static int
dtmalloc_open(struct cdev * dev __unused,int oflags __unused,int devtype __unused,struct thread * td __unused)211 dtmalloc_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *td __unused)
212 {
213 return (0);
214 }
215
216 SYSINIT(dtmalloc_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, dtmalloc_load, NULL);
217 SYSUNINIT(dtmalloc_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, dtmalloc_unload, NULL);
218
219 DEV_MODULE(dtmalloc, dtmalloc_modevent, NULL);
220 MODULE_VERSION(dtmalloc, 1);
221 MODULE_DEPEND(dtmalloc, dtrace, 1, 1, 1);
222 MODULE_DEPEND(dtmalloc, opensolaris, 1, 1, 1);
223