memstat.c revision 224569
1228753Smm/*-
2228753Smm * Copyright (c) 2005 Robert N. M. Watson
3228753Smm * All rights reserved.
4228753Smm *
5228753Smm * Redistribution and use in source and binary forms, with or without
6228753Smm * modification, are permitted provided that the following conditions
7228753Smm * are met:
8228753Smm * 1. Redistributions of source code must retain the above copyright
9228753Smm *    notice, this list of conditions and the following disclaimer.
10228753Smm * 2. Redistributions in binary form must reproduce the above copyright
11228753Smm *    notice, this list of conditions and the following disclaimer in the
12228753Smm *    documentation and/or other materials provided with the distribution.
13228753Smm *
14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15228753Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16228753Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17228753Smm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18228753Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19228753Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20228753Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21228753Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22228753Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23228753Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24228753Smm * SUCH DAMAGE.
25228753Smm *
26228753Smm * $FreeBSD: head/lib/libmemstat/memstat.c 224569 2011-08-01 09:43:35Z pluknet $
27228753Smm */
28228753Smm
29228753Smm#include <sys/param.h>
30228753Smm#include <sys/sysctl.h>
31228753Smm
32228753Smm#include <err.h>
33228753Smm#include <errno.h>
34228753Smm#include <stdio.h>
35228753Smm#include <stdlib.h>
36228753Smm#include <string.h>
37228753Smm
38228753Smm#include "memstat.h"
39228753Smm#include "memstat_internal.h"
40228753Smm
41228753Smmconst char *
42228753Smmmemstat_strerror(int error)
43228753Smm{
44228753Smm
45228753Smm	switch (error) {
46228753Smm	case MEMSTAT_ERROR_NOMEMORY:
47228753Smm		return ("Cannot allocate memory");
48228753Smm	case MEMSTAT_ERROR_VERSION:
49228753Smm		return ("Version mismatch");
50228753Smm	case MEMSTAT_ERROR_PERMISSION:
51228753Smm		return ("Permission denied");
52228753Smm	case MEMSTAT_ERROR_DATAERROR:
53228753Smm		return ("Data format error");
54228753Smm	case MEMSTAT_ERROR_KVM:
55228753Smm		return ("KVM error");
56228753Smm	case MEMSTAT_ERROR_KVM_NOSYMBOL:
57228753Smm		return ("KVM unable to find symbol");
58228753Smm	case MEMSTAT_ERROR_KVM_SHORTREAD:
59228753Smm		return ("KVM short read");
60228753Smm	case MEMSTAT_ERROR_UNDEFINED:
61228753Smm	default:
62228753Smm		return ("Unknown error");
63228753Smm	}
64228753Smm}
65228753Smm
66228753Smmstruct memory_type_list *
67228753Smmmemstat_mtl_alloc(void)
68228753Smm{
69228753Smm	struct memory_type_list *mtlp;
70228753Smm
71228753Smm	mtlp = malloc(sizeof(*mtlp));
72228753Smm	if (mtlp == NULL)
73228753Smm		return (NULL);
74228753Smm
75228753Smm	LIST_INIT(&mtlp->mtl_list);
76228753Smm	mtlp->mtl_error = MEMSTAT_ERROR_UNDEFINED;
77228753Smm	return (mtlp);
78228753Smm}
79228753Smm
80228753Smmstruct memory_type *
81228753Smmmemstat_mtl_first(struct memory_type_list *list)
82228753Smm{
83228753Smm
84228753Smm	return (LIST_FIRST(&list->mtl_list));
85228753Smm}
86228753Smm
87228753Smmstruct memory_type *
88228753Smmmemstat_mtl_next(struct memory_type *mtp)
89228753Smm{
90228753Smm
91228753Smm	return (LIST_NEXT(mtp, mt_list));
92228753Smm}
93228753Smm
94228753Smmvoid
95228753Smm_memstat_mtl_empty(struct memory_type_list *list)
96228753Smm{
97228753Smm	struct memory_type *mtp;
98228753Smm
99228753Smm	while ((mtp = LIST_FIRST(&list->mtl_list))) {
100228753Smm		free(mtp->mt_percpu_alloc);
101228753Smm		free(mtp->mt_percpu_cache);
102228753Smm		LIST_REMOVE(mtp, mt_list);
103228753Smm		free(mtp);
104228753Smm	}
105228753Smm}
106228753Smm
107228753Smmvoid
108228753Smmmemstat_mtl_free(struct memory_type_list *list)
109228753Smm{
110228753Smm
111228753Smm	_memstat_mtl_empty(list);
112228753Smm	free(list);
113228753Smm}
114228753Smm
115228753Smmint
116228753Smmmemstat_mtl_geterror(struct memory_type_list *list)
117228753Smm{
118228753Smm
119228753Smm	return (list->mtl_error);
120228753Smm}
121228753Smm
122228753Smm/*
123228753Smm * Look for an existing memory_type entry in a memory_type list, based on the
124228753Smm * allocator and name of the type.  If not found, return NULL.  No errno or
125228753Smm * memstat error.
126228753Smm */
127228753Smmstruct memory_type *
128228753Smmmemstat_mtl_find(struct memory_type_list *list, int allocator,
129228753Smm    const char *name)
130228753Smm{
131228753Smm	struct memory_type *mtp;
132228753Smm
133228753Smm	LIST_FOREACH(mtp, &list->mtl_list, mt_list) {
134228753Smm		if ((mtp->mt_allocator == allocator ||
135228753Smm		    allocator == ALLOCATOR_ANY) &&
136228753Smm		    strcmp(mtp->mt_name, name) == 0)
137228753Smm			return (mtp);
138228753Smm	}
139228753Smm	return (NULL);
140228753Smm}
141228753Smm
142228753Smm/*
143228753Smm * Allocate a new memory_type with the specificed allocator type and name,
144228753Smm * then insert into the list.  The structure will be zero'd.
145228753Smm *
146228753Smm * libmemstat(3) internal function.
147228753Smm */
148228753Smmstruct memory_type *
149228753Smm_memstat_mt_allocate(struct memory_type_list *list, int allocator,
150228753Smm    const char *name, int maxcpus)
151228753Smm{
152228753Smm	struct memory_type *mtp;
153228753Smm
154228753Smm	mtp = malloc(sizeof(*mtp));
155228753Smm	if (mtp == NULL)
156228753Smm		return (NULL);
157228753Smm
158228753Smm	bzero(mtp, sizeof(*mtp));
159228753Smm
160228753Smm	mtp->mt_allocator = allocator;
161228753Smm	mtp->mt_percpu_alloc = malloc(sizeof(struct mt_percpu_alloc_s) *
162228753Smm	    maxcpus);
163228753Smm	mtp->mt_percpu_cache = malloc(sizeof(struct mt_percpu_cache_s) *
164228753Smm	    maxcpus);
165228753Smm	strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME);
166228753Smm	LIST_INSERT_HEAD(&list->mtl_list, mtp, mt_list);
167228753Smm	return (mtp);
168228753Smm}
169228753Smm
170228753Smm/*
171228753Smm * Reset any libmemstat(3)-owned statistics in a memory_type record so that
172228753Smm * it can be reused without incremental addition problems.  Caller-owned
173228753Smm * memory is left "as-is", and must be updated by the caller if desired.
174228753Smm *
175228753Smm * libmemstat(3) internal function.
176228753Smm */
177228753Smmvoid
178228753Smm_memstat_mt_reset_stats(struct memory_type *mtp, int maxcpus)
179228753Smm{
180228753Smm	int i;
181228753Smm
182228753Smm	mtp->mt_countlimit = 0;
183228753Smm	mtp->mt_byteslimit = 0;
184228753Smm	mtp->mt_sizemask = 0;
185228753Smm	mtp->mt_size = 0;
186228753Smm
187228753Smm	mtp->mt_memalloced = 0;
188228753Smm	mtp->mt_memfreed = 0;
189228753Smm	mtp->mt_numallocs = 0;
190228753Smm	mtp->mt_numfrees = 0;
191228753Smm	mtp->mt_bytes = 0;
192228753Smm	mtp->mt_count = 0;
193228753Smm	mtp->mt_free = 0;
194228753Smm	mtp->mt_failures = 0;
195228753Smm	mtp->mt_sleeps = 0;
196228753Smm
197228753Smm	mtp->mt_zonefree = 0;
198228753Smm	mtp->mt_kegfree = 0;
199228753Smm
200228753Smm	for (i = 0; i < maxcpus; i++) {
201228753Smm		mtp->mt_percpu_alloc[i].mtp_memalloced = 0;
202228753Smm		mtp->mt_percpu_alloc[i].mtp_memfreed = 0;
203228753Smm		mtp->mt_percpu_alloc[i].mtp_numallocs = 0;
204228753Smm		mtp->mt_percpu_alloc[i].mtp_numfrees = 0;
205228753Smm		mtp->mt_percpu_alloc[i].mtp_sizemask = 0;
206228753Smm		mtp->mt_percpu_cache[i].mtp_free = 0;
207228753Smm	}
208228753Smm}
209228753Smm
210228753Smm/*
211228753Smm * Accessor methods for struct memory_type.  Avoids encoding the structure
212228753Smm * ABI into the application.
213228753Smm */
214228753Smmconst char *
215228753Smmmemstat_get_name(const struct memory_type *mtp)
216228753Smm{
217228753Smm
218228753Smm	return (mtp->mt_name);
219228753Smm}
220228753Smm
221228753Smmint
222228753Smmmemstat_get_allocator(const struct memory_type *mtp)
223228753Smm{
224228753Smm
225228753Smm	return (mtp->mt_allocator);
226228753Smm}
227228753Smm
228228753Smmuint64_t
229228753Smmmemstat_get_countlimit(const struct memory_type *mtp)
230228753Smm{
231228753Smm
232228753Smm	return (mtp->mt_countlimit);
233228753Smm}
234228753Smm
235228753Smmuint64_t
236228753Smmmemstat_get_byteslimit(const struct memory_type *mtp)
237228753Smm{
238228753Smm
239228753Smm	return (mtp->mt_byteslimit);
240228753Smm}
241228753Smm
242228753Smmuint64_t
243228753Smmmemstat_get_sizemask(const struct memory_type *mtp)
244228753Smm{
245228753Smm
246228753Smm	return (mtp->mt_sizemask);
247228753Smm}
248228753Smm
249228753Smmuint64_t
250228753Smmmemstat_get_size(const struct memory_type *mtp)
251228753Smm{
252228753Smm
253228753Smm	return (mtp->mt_size);
254228753Smm}
255228753Smm
256228753Smmuint64_t
257228753Smmmemstat_get_memalloced(const struct memory_type *mtp)
258228753Smm{
259228753Smm
260228753Smm	return (mtp->mt_memalloced);
261228753Smm}
262228753Smm
263228753Smmuint64_t
264228753Smmmemstat_get_memfreed(const struct memory_type *mtp)
265228753Smm{
266228753Smm
267228753Smm	return (mtp->mt_memfreed);
268228753Smm}
269228753Smm
270228753Smmuint64_t
271228753Smmmemstat_get_numallocs(const struct memory_type *mtp)
272228753Smm{
273228753Smm
274228753Smm	return (mtp->mt_numallocs);
275228753Smm}
276228753Smm
277228753Smmuint64_t
278228753Smmmemstat_get_numfrees(const struct memory_type *mtp)
279228753Smm{
280228753Smm
281228753Smm	return (mtp->mt_numfrees);
282228753Smm}
283228753Smm
284228753Smmuint64_t
285228753Smmmemstat_get_bytes(const struct memory_type *mtp)
286228753Smm{
287228753Smm
288228753Smm	return (mtp->mt_bytes);
289228753Smm}
290228753Smm
291228753Smmuint64_t
292228753Smmmemstat_get_count(const struct memory_type *mtp)
293228753Smm{
294228753Smm
295228753Smm	return (mtp->mt_count);
296228753Smm}
297228753Smm
298228753Smmuint64_t
299228753Smmmemstat_get_free(const struct memory_type *mtp)
300228753Smm{
301228753Smm
302228753Smm	return (mtp->mt_free);
303228753Smm}
304228753Smm
305228753Smmuint64_t
306228753Smmmemstat_get_failures(const struct memory_type *mtp)
307228753Smm{
308228753Smm
309228753Smm	return (mtp->mt_failures);
310228753Smm}
311228753Smm
312228753Smmuint64_t
313228753Smmmemstat_get_sleeps(const struct memory_type *mtp)
314228753Smm{
315228753Smm
316228753Smm	return (mtp->mt_sleeps);
317228753Smm}
318228753Smm
319228753Smmvoid *
320228753Smmmemstat_get_caller_pointer(const struct memory_type *mtp, int index)
321228753Smm{
322228753Smm
323228753Smm	return (mtp->mt_caller_pointer[index]);
324228753Smm}
325228753Smm
326228753Smmvoid
327228753Smmmemstat_set_caller_pointer(struct memory_type *mtp, int index, void *value)
328228753Smm{
329228753Smm
330228753Smm	mtp->mt_caller_pointer[index] = value;
331228753Smm}
332228753Smm
333228753Smmuint64_t
334228753Smmmemstat_get_caller_uint64(const struct memory_type *mtp, int index)
335228753Smm{
336228753Smm
337228753Smm	return (mtp->mt_caller_uint64[index]);
338228753Smm}
339228753Smm
340228753Smmvoid
341228753Smmmemstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value)
342228753Smm{
343228753Smm
344228753Smm	mtp->mt_caller_uint64[index] = value;
345228753Smm}
346228753Smm
347228753Smmuint64_t
348228753Smmmemstat_get_zonefree(const struct memory_type *mtp)
349228753Smm{
350228753Smm
351228753Smm	return (mtp->mt_zonefree);
352228753Smm}
353228753Smm
354228753Smmuint64_t
355228753Smmmemstat_get_kegfree(const struct memory_type *mtp)
356228753Smm{
357228753Smm
358228753Smm	return (mtp->mt_kegfree);
359228753Smm}
360228753Smm
361228753Smmuint64_t
362228753Smmmemstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu)
363228753Smm{
364228753Smm
365228753Smm	return (mtp->mt_percpu_alloc[cpu].mtp_memalloced);
366228753Smm}
367228753Smm
368228753Smmuint64_t
369228753Smmmemstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu)
370228753Smm{
371228753Smm
372228753Smm	return (mtp->mt_percpu_alloc[cpu].mtp_memfreed);
373228753Smm}
374228753Smm
375228753Smmuint64_t
376228753Smmmemstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu)
377228753Smm{
378228753Smm
379228753Smm	return (mtp->mt_percpu_alloc[cpu].mtp_numallocs);
380228753Smm}
381228753Smm
382228753Smmuint64_t
383228753Smmmemstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu)
384228753Smm{
385228753Smm
386228753Smm	return (mtp->mt_percpu_alloc[cpu].mtp_numfrees);
387228753Smm}
388228753Smm
389228753Smmuint64_t
390228753Smmmemstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu)
391228753Smm{
392228753Smm
393228753Smm	return (mtp->mt_percpu_alloc[cpu].mtp_sizemask);
394228753Smm}
395228753Smm
396228753Smmvoid *
397228753Smmmemstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu,
398228753Smm    int index)
399228753Smm{
400228753Smm
401228753Smm	return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]);
402228753Smm}
403228753Smm
404228753Smmvoid
405228753Smmmemstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu,
406228753Smm    int index, void *value)
407228753Smm{
408228753Smm
409228753Smm	mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value;
410228753Smm}
411228753Smm
412228753Smmuint64_t
413228753Smmmemstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu,
414228753Smm    int index)
415228753Smm{
416228753Smm
417228753Smm	return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]);
418228753Smm}
419228753Smm
420228753Smmvoid
421228753Smmmemstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index,
422228753Smm    uint64_t value)
423228753Smm{
424228753Smm
425228753Smm	mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value;
426228753Smm}
427228753Smm
428228753Smmuint64_t
429228753Smmmemstat_get_percpu_free(const struct memory_type *mtp, int cpu)
430228753Smm{
431228753Smm
432228753Smm	return (mtp->mt_percpu_cache[cpu].mtp_free);
433228753Smm}
434228753Smm