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