xref: /freebsd/lib/libmemstat/memstat.c (revision fce1f260f16b8775bc732df5ad1992bd1a80a7db)
1 /*-
2  * Copyright (c) 2005 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 
29 #include <sys/param.h>
30 #include <sys/sysctl.h>
31 
32 #include <err.h>
33 #include <errno.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "memstat.h"
39 #include "memstat_internal.h"
40 
41 struct memory_type_list *
42 memstat_mtl_alloc(void)
43 {
44 	struct memory_type_list *mtlp;
45 
46 	mtlp = malloc(sizeof(*mtlp));
47 	if (mtlp == NULL)
48 		return (NULL);
49 
50 	LIST_INIT(mtlp);
51 	return (mtlp);
52 }
53 
54 struct memory_type *
55 memstat_mtl_first(struct memory_type_list *list)
56 {
57 
58 	return (LIST_FIRST(list));
59 }
60 
61 struct memory_type *
62 memstat_mtl_next(struct memory_type *mtp)
63 {
64 
65 	return (LIST_NEXT(mtp, mt_list));
66 }
67 
68 void
69 memstat_mtl_free(struct memory_type_list *list)
70 {
71 	struct memory_type *mtp;
72 
73 	while ((mtp = LIST_FIRST(list))) {
74 		LIST_REMOVE(mtp, mt_list);
75 		free(mtp);
76 	}
77 	free(list);
78 }
79 
80 /*
81  * Look for an existing memory_type entry in a memory_type list, based on the
82  * allocator and name of the type.  If not found, return NULL.  O(n).
83  */
84 struct memory_type *
85 memstat_mtl_find(struct memory_type_list *list, int allocator,
86     const char *name)
87 {
88 	struct memory_type *mtp;
89 
90 	LIST_FOREACH(mtp, list, mt_list) {
91 		if ((mtp->mt_allocator == allocator ||
92 		    allocator == ALLOCATOR_ANY) &&
93 		    strcmp(mtp->mt_name, name) == 0)
94 			return (mtp);
95 	}
96 	return (NULL);
97 }
98 
99 /*
100  * Allocate a new memory_type with the specificed allocator type and name,
101  * then insert into the list.  The structure will be zero'd.
102  */
103 struct memory_type *
104 memstat_mt_allocate(struct memory_type_list *list, int allocator,
105     const char *name)
106 {
107 	struct memory_type *mtp;
108 
109 	mtp = malloc(sizeof(*mtp));
110 	if (mtp == NULL)
111 		return (NULL);
112 
113 	bzero(mtp, sizeof(*mtp));
114 
115 	mtp->mt_allocator = allocator;
116 	strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME);
117 	LIST_INSERT_HEAD(list, mtp, mt_list);
118 	return (mtp);
119 }
120 
121 /*
122  * Reset any libmemstat(3)-owned statistics in a memory_type record so that
123  * it can be reused without incremental addition problems.  Caller-owned
124  * memory is left "as-is", and must be updated by the caller if desired.
125  */
126 void
127 memstat_mt_reset_stats(struct memory_type *mtp)
128 {
129 	int i;
130 
131 	mtp->mt_countlimit = 0;
132 	mtp->mt_byteslimit = 0;
133 	mtp->mt_sizemask = 0;
134 	mtp->mt_size = 0;
135 
136 	mtp->mt_memalloced = 0;
137 	mtp->mt_memfreed = 0;
138 	mtp->mt_numallocs = 0;
139 	mtp->mt_numfrees = 0;
140 	mtp->mt_bytes = 0;
141 	mtp->mt_count = 0;
142 	mtp->mt_free = 0;
143 	mtp->mt_failures = 0;
144 
145 	mtp->mt_zonefree = 0;
146 	mtp->mt_kegfree = 0;
147 
148 	for (i = 0; i < MEMSTAT_MAXCPU; i++) {
149 		mtp->mt_percpu_alloc[i].mtp_memalloced = 0;
150 		mtp->mt_percpu_alloc[i].mtp_memfreed = 0;
151 		mtp->mt_percpu_alloc[i].mtp_numallocs = 0;
152 		mtp->mt_percpu_alloc[i].mtp_numfrees = 0;
153 		mtp->mt_percpu_alloc[i].mtp_sizemask = 0;
154 		mtp->mt_percpu_cache[i].mtp_free = 0;
155 	}
156 }
157 
158 /*
159  * Accessor methods for struct memory_type.  Avoids encoding the structure
160  * ABI into the application.
161  */
162 const char *
163 memstat_get_name(const struct memory_type *mtp)
164 {
165 
166 	return (mtp->mt_name);
167 }
168 
169 int
170 memstat_get_allocator(const struct memory_type *mtp)
171 {
172 
173 	return (mtp->mt_allocator);
174 }
175 
176 uint64_t
177 memstat_get_countlimit(const struct memory_type *mtp)
178 {
179 
180 	return (mtp->mt_countlimit);
181 }
182 
183 uint64_t
184 memstat_get_byteslimit(const struct memory_type *mtp)
185 {
186 
187 	return (mtp->mt_byteslimit);
188 }
189 
190 uint64_t
191 memstat_get_sizemask(const struct memory_type *mtp)
192 {
193 
194 	return (mtp->mt_sizemask);
195 }
196 
197 uint64_t
198 memstat_get_size(const struct memory_type *mtp)
199 {
200 
201 	return (mtp->mt_size);
202 }
203 
204 uint64_t
205 memstat_get_memalloced(const struct memory_type *mtp)
206 {
207 
208 	return (mtp->mt_memalloced);
209 }
210 
211 uint64_t
212 memstat_get_memfreed(const struct memory_type *mtp)
213 {
214 
215 	return (mtp->mt_memfreed);
216 }
217 
218 uint64_t
219 memstat_get_numallocs(const struct memory_type *mtp)
220 {
221 
222 	return (mtp->mt_numallocs);
223 }
224 
225 uint64_t
226 memstat_get_numfrees(const struct memory_type *mtp)
227 {
228 
229 	return (mtp->mt_numfrees);
230 }
231 
232 uint64_t
233 memstat_get_bytes(const struct memory_type *mtp)
234 {
235 
236 	return (mtp->mt_bytes);
237 }
238 
239 uint64_t
240 memstat_get_count(const struct memory_type *mtp)
241 {
242 
243 	return (mtp->mt_count);
244 }
245 
246 uint64_t
247 memstat_get_free(const struct memory_type *mtp)
248 {
249 
250 	return (mtp->mt_free);
251 }
252 
253 uint64_t
254 memstat_get_failures(const struct memory_type *mtp)
255 {
256 
257 	return (mtp->mt_failures);
258 }
259 
260 void *
261 memstat_get_caller_pointer(const struct memory_type *mtp, int index)
262 {
263 
264 	return (mtp->mt_caller_pointer[index]);
265 }
266 
267 void
268 memstat_set_caller_pointer(struct memory_type *mtp, int index, void *value)
269 {
270 
271 	mtp->mt_caller_pointer[index] = value;
272 }
273 
274 uint64_t
275 memstat_get_caller_uint64(const struct memory_type *mtp, int index)
276 {
277 
278 	return (mtp->mt_caller_uint64[index]);
279 }
280 
281 void
282 memstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value)
283 {
284 
285 	mtp->mt_caller_uint64[index] = value;
286 }
287 
288 uint64_t
289 memstat_get_zonefree(const struct memory_type *mtp)
290 {
291 
292 	return (mtp->mt_zonefree);
293 }
294 
295 uint64_t
296 memstat_get_kegfree(const struct memory_type *mtp)
297 {
298 
299 	return (mtp->mt_kegfree);
300 }
301 
302 uint64_t
303 memstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu)
304 {
305 
306 	return (mtp->mt_percpu_alloc[cpu].mtp_memalloced);
307 }
308 
309 uint64_t
310 memstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu)
311 {
312 
313 	return (mtp->mt_percpu_alloc[cpu].mtp_memfreed);
314 }
315 
316 uint64_t
317 memstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu)
318 {
319 
320 	return (mtp->mt_percpu_alloc[cpu].mtp_numallocs);
321 }
322 
323 uint64_t
324 memstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu)
325 {
326 
327 	return (mtp->mt_percpu_alloc[cpu].mtp_numfrees);
328 }
329 
330 uint64_t
331 memstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu)
332 {
333 
334 	return (mtp->mt_percpu_alloc[cpu].mtp_sizemask);
335 }
336 
337 void *
338 memstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu,
339     int index)
340 {
341 
342 	return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]);
343 }
344 
345 void
346 memstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu,
347     int index, void *value)
348 {
349 
350 	mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value;
351 }
352 
353 uint64_t
354 memstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu,
355     int index)
356 {
357 
358 	return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]);
359 }
360 
361 void
362 memstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index,
363     uint64_t value)
364 {
365 
366 	mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value;
367 }
368 
369 uint64_t
370 memstat_get_percpu_free(const struct memory_type *mtp, int cpu)
371 {
372 
373 	return (mtp->mt_percpu_cache[cpu].mtp_free);
374 }
375