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