Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/cddl/dev/dtmalloc/dtmalloc.c
48266 views
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 [email protected]
22
*
23
*/
24
25
#include <sys/param.h>
26
#include <sys/systm.h>
27
#include <sys/conf.h>
28
#include <sys/ctype.h>
29
#include <sys/kernel.h>
30
#include <sys/malloc.h>
31
#include <sys/module.h>
32
33
#include <sys/dtrace.h>
34
#include <sys/dtrace_bsd.h>
35
36
extern bool dtrace_malloc_enabled;
37
static uint32_t dtrace_malloc_enabled_count;
38
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 dtrace_pattr_t dtmalloc_attr = {
48
{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
49
{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
50
{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
51
{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
52
{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
53
};
54
55
static dtrace_pops_t dtmalloc_pops = {
56
.dtps_provide = dtmalloc_provide,
57
.dtps_provide_module = NULL,
58
.dtps_enable = dtmalloc_enable,
59
.dtps_disable = dtmalloc_disable,
60
.dtps_suspend = NULL,
61
.dtps_resume = NULL,
62
.dtps_getargdesc = dtmalloc_getargdesc,
63
.dtps_getargval = NULL,
64
.dtps_usermode = NULL,
65
.dtps_destroy = dtmalloc_destroy
66
};
67
68
static dtrace_provider_id_t dtmalloc_id;
69
70
static void
71
dtmalloc_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
72
{
73
const char *p = NULL;
74
75
switch (desc->dtargd_ndx) {
76
case 0:
77
p = "struct malloc_type *";
78
break;
79
case 1:
80
p = "struct malloc_type_internal *";
81
break;
82
case 2:
83
p = "struct malloc_type_stats *";
84
break;
85
case 3:
86
p = "unsigned long";
87
break;
88
case 4:
89
p = "int";
90
break;
91
default:
92
desc->dtargd_ndx = DTRACE_ARGNONE;
93
break;
94
}
95
96
if (p != NULL)
97
strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
98
99
return;
100
}
101
102
static void
103
dtmalloc_type_cb(struct malloc_type *mtp, void *arg __unused)
104
{
105
char name[DTRACE_FUNCNAMELEN];
106
struct malloc_type_internal *mtip = &mtp->ks_mti;
107
int i;
108
109
/*
110
* malloc_type descriptions are allowed to contain whitespace, but
111
* DTrace probe identifiers are not, so replace the whitespace with
112
* underscores.
113
*/
114
strlcpy(name, mtp->ks_shortdesc, sizeof(name));
115
for (i = 0; name[i] != 0; i++)
116
if (isspace(name[i]))
117
name[i] = '_';
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
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
138
dtmalloc_destroy(void *arg, dtrace_id_t id, void *parg)
139
{
140
}
141
142
static void
143
dtmalloc_enable(void *arg, dtrace_id_t id, void *parg)
144
{
145
uint32_t *p = parg;
146
*p = id;
147
dtrace_malloc_enabled_count++;
148
if (dtrace_malloc_enabled_count == 1)
149
dtrace_malloc_enabled = true;
150
}
151
152
static void
153
dtmalloc_disable(void *arg, dtrace_id_t id, void *parg)
154
{
155
uint32_t *p = parg;
156
*p = 0;
157
dtrace_malloc_enabled_count--;
158
if (dtrace_malloc_enabled_count == 0)
159
dtrace_malloc_enabled = false;
160
}
161
162
static void
163
dtmalloc_load(void *dummy)
164
{
165
if (dtrace_register("dtmalloc", &dtmalloc_attr, DTRACE_PRIV_USER,
166
NULL, &dtmalloc_pops, NULL, &dtmalloc_id) != 0)
167
return;
168
169
dtrace_malloc_probe = dtrace_probe;
170
}
171
172
173
static int
174
dtmalloc_unload(void)
175
{
176
int error = 0;
177
178
dtrace_malloc_probe = NULL;
179
180
if ((error = dtrace_unregister(dtmalloc_id)) != 0)
181
return (error);
182
183
return (error);
184
}
185
186
static int
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
SYSINIT(dtmalloc_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, dtmalloc_load, NULL);
211
SYSUNINIT(dtmalloc_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, dtmalloc_unload, NULL);
212
213
DEV_MODULE(dtmalloc, dtmalloc_modevent, NULL);
214
MODULE_VERSION(dtmalloc, 1);
215
MODULE_DEPEND(dtmalloc, dtrace, 1, 1, 1);
216
MODULE_DEPEND(dtmalloc, opensolaris, 1, 1, 1);
217
218