1147997Srwatson/*-
2147997Srwatson * Copyright (c) 2005 Robert N. M. Watson
3147997Srwatson * All rights reserved.
4147997Srwatson *
5147997Srwatson * Redistribution and use in source and binary forms, with or without
6147997Srwatson * modification, are permitted provided that the following conditions
7147997Srwatson * are met:
8147997Srwatson * 1. Redistributions of source code must retain the above copyright
9147997Srwatson *    notice, this list of conditions and the following disclaimer.
10147997Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11147997Srwatson *    notice, this list of conditions and the following disclaimer in the
12147997Srwatson *    documentation and/or other materials provided with the distribution.
13147997Srwatson *
14147997Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15147997Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16147997Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17147997Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18147997Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19147997Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20147997Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21147997Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22147997Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23147997Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24147997Srwatson * SUCH DAMAGE.
25147997Srwatson *
26147997Srwatson * $FreeBSD$
27147997Srwatson */
28147997Srwatson
29147997Srwatson#include <sys/param.h>
30147997Srwatson#include <sys/sysctl.h>
31147997Srwatson
32147997Srwatson#include <err.h>
33147997Srwatson#include <errno.h>
34147997Srwatson#include <stdio.h>
35147997Srwatson#include <stdlib.h>
36147997Srwatson#include <string.h>
37147997Srwatson
38147997Srwatson#include "memstat.h"
39147997Srwatson#include "memstat_internal.h"
40147997Srwatson
41148359Srwatsonconst char *
42148359Srwatsonmemstat_strerror(int error)
43148359Srwatson{
44148359Srwatson
45148359Srwatson	switch (error) {
46148359Srwatson	case MEMSTAT_ERROR_NOMEMORY:
47148359Srwatson		return ("Cannot allocate memory");
48148359Srwatson	case MEMSTAT_ERROR_VERSION:
49148359Srwatson		return ("Version mismatch");
50148359Srwatson	case MEMSTAT_ERROR_PERMISSION:
51148359Srwatson		return ("Permission denied");
52148359Srwatson	case MEMSTAT_ERROR_DATAERROR:
53148359Srwatson		return ("Data format error");
54148627Srwatson	case MEMSTAT_ERROR_KVM:
55148627Srwatson		return ("KVM error");
56148627Srwatson	case MEMSTAT_ERROR_KVM_NOSYMBOL:
57148627Srwatson		return ("KVM unable to find symbol");
58148627Srwatson	case MEMSTAT_ERROR_KVM_SHORTREAD:
59148627Srwatson		return ("KVM short read");
60148359Srwatson	case MEMSTAT_ERROR_UNDEFINED:
61148359Srwatson	default:
62148359Srwatson		return ("Unknown error");
63148359Srwatson	}
64148359Srwatson}
65148359Srwatson
66147997Srwatsonstruct memory_type_list *
67147997Srwatsonmemstat_mtl_alloc(void)
68147997Srwatson{
69147997Srwatson	struct memory_type_list *mtlp;
70147997Srwatson
71147997Srwatson	mtlp = malloc(sizeof(*mtlp));
72147997Srwatson	if (mtlp == NULL)
73147997Srwatson		return (NULL);
74147997Srwatson
75148357Srwatson	LIST_INIT(&mtlp->mtl_list);
76148357Srwatson	mtlp->mtl_error = MEMSTAT_ERROR_UNDEFINED;
77147997Srwatson	return (mtlp);
78147997Srwatson}
79147997Srwatson
80147997Srwatsonstruct memory_type *
81147997Srwatsonmemstat_mtl_first(struct memory_type_list *list)
82147997Srwatson{
83147997Srwatson
84148357Srwatson	return (LIST_FIRST(&list->mtl_list));
85147997Srwatson}
86147997Srwatson
87147997Srwatsonstruct memory_type *
88147997Srwatsonmemstat_mtl_next(struct memory_type *mtp)
89147997Srwatson{
90147997Srwatson
91147997Srwatson	return (LIST_NEXT(mtp, mt_list));
92147997Srwatson}
93147997Srwatson
94147997Srwatsonvoid
95148619Srwatson_memstat_mtl_empty(struct memory_type_list *list)
96147997Srwatson{
97147997Srwatson	struct memory_type *mtp;
98147997Srwatson
99148357Srwatson	while ((mtp = LIST_FIRST(&list->mtl_list))) {
100224569Spluknet		free(mtp->mt_percpu_alloc);
101224569Spluknet		free(mtp->mt_percpu_cache);
102147997Srwatson		LIST_REMOVE(mtp, mt_list);
103147997Srwatson		free(mtp);
104147997Srwatson	}
105148619Srwatson}
106148619Srwatson
107148619Srwatsonvoid
108148619Srwatsonmemstat_mtl_free(struct memory_type_list *list)
109148619Srwatson{
110148619Srwatson
111148619Srwatson	_memstat_mtl_empty(list);
112147997Srwatson	free(list);
113147997Srwatson}
114147997Srwatson
115148357Srwatsonint
116148357Srwatsonmemstat_mtl_geterror(struct memory_type_list *list)
117148357Srwatson{
118148357Srwatson
119148357Srwatson	return (list->mtl_error);
120148357Srwatson}
121148357Srwatson
122147997Srwatson/*
123147997Srwatson * Look for an existing memory_type entry in a memory_type list, based on the
124148357Srwatson * allocator and name of the type.  If not found, return NULL.  No errno or
125148357Srwatson * memstat error.
126147997Srwatson */
127147997Srwatsonstruct memory_type *
128147997Srwatsonmemstat_mtl_find(struct memory_type_list *list, int allocator,
129147997Srwatson    const char *name)
130147997Srwatson{
131147997Srwatson	struct memory_type *mtp;
132147997Srwatson
133148357Srwatson	LIST_FOREACH(mtp, &list->mtl_list, mt_list) {
134147997Srwatson		if ((mtp->mt_allocator == allocator ||
135147997Srwatson		    allocator == ALLOCATOR_ANY) &&
136147997Srwatson		    strcmp(mtp->mt_name, name) == 0)
137147997Srwatson			return (mtp);
138147997Srwatson	}
139147997Srwatson	return (NULL);
140147997Srwatson}
141147997Srwatson
142147997Srwatson/*
143147997Srwatson * Allocate a new memory_type with the specificed allocator type and name,
144147997Srwatson * then insert into the list.  The structure will be zero'd.
145148354Srwatson *
146148354Srwatson * libmemstat(3) internal function.
147147997Srwatson */
148147997Srwatsonstruct memory_type *
149148354Srwatson_memstat_mt_allocate(struct memory_type_list *list, int allocator,
150224569Spluknet    const char *name, int maxcpus)
151147997Srwatson{
152147997Srwatson	struct memory_type *mtp;
153147997Srwatson
154147997Srwatson	mtp = malloc(sizeof(*mtp));
155147997Srwatson	if (mtp == NULL)
156147997Srwatson		return (NULL);
157147997Srwatson
158147997Srwatson	bzero(mtp, sizeof(*mtp));
159147997Srwatson
160147997Srwatson	mtp->mt_allocator = allocator;
161224569Spluknet	mtp->mt_percpu_alloc = malloc(sizeof(struct mt_percpu_alloc_s) *
162224569Spluknet	    maxcpus);
163224569Spluknet	mtp->mt_percpu_cache = malloc(sizeof(struct mt_percpu_cache_s) *
164224569Spluknet	    maxcpus);
165147997Srwatson	strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME);
166148357Srwatson	LIST_INSERT_HEAD(&list->mtl_list, mtp, mt_list);
167147997Srwatson	return (mtp);
168147997Srwatson}
169147997Srwatson
170147997Srwatson/*
171147997Srwatson * Reset any libmemstat(3)-owned statistics in a memory_type record so that
172147997Srwatson * it can be reused without incremental addition problems.  Caller-owned
173147997Srwatson * memory is left "as-is", and must be updated by the caller if desired.
174148354Srwatson *
175148354Srwatson * libmemstat(3) internal function.
176147997Srwatson */
177147997Srwatsonvoid
178224569Spluknet_memstat_mt_reset_stats(struct memory_type *mtp, int maxcpus)
179147997Srwatson{
180147997Srwatson	int i;
181147997Srwatson
182147997Srwatson	mtp->mt_countlimit = 0;
183147997Srwatson	mtp->mt_byteslimit = 0;
184147997Srwatson	mtp->mt_sizemask = 0;
185147997Srwatson	mtp->mt_size = 0;
186147997Srwatson
187147997Srwatson	mtp->mt_memalloced = 0;
188147997Srwatson	mtp->mt_memfreed = 0;
189147997Srwatson	mtp->mt_numallocs = 0;
190147997Srwatson	mtp->mt_numfrees = 0;
191147997Srwatson	mtp->mt_bytes = 0;
192147997Srwatson	mtp->mt_count = 0;
193147997Srwatson	mtp->mt_free = 0;
194147997Srwatson	mtp->mt_failures = 0;
195209215Ssbruno	mtp->mt_sleeps = 0;
196147997Srwatson
197147997Srwatson	mtp->mt_zonefree = 0;
198148170Srwatson	mtp->mt_kegfree = 0;
199147997Srwatson
200224569Spluknet	for (i = 0; i < maxcpus; i++) {
201147997Srwatson		mtp->mt_percpu_alloc[i].mtp_memalloced = 0;
202147997Srwatson		mtp->mt_percpu_alloc[i].mtp_memfreed = 0;
203147997Srwatson		mtp->mt_percpu_alloc[i].mtp_numallocs = 0;
204147997Srwatson		mtp->mt_percpu_alloc[i].mtp_numfrees = 0;
205147997Srwatson		mtp->mt_percpu_alloc[i].mtp_sizemask = 0;
206147997Srwatson		mtp->mt_percpu_cache[i].mtp_free = 0;
207147997Srwatson	}
208147997Srwatson}
209147997Srwatson
210147997Srwatson/*
211147997Srwatson * Accessor methods for struct memory_type.  Avoids encoding the structure
212147997Srwatson * ABI into the application.
213147997Srwatson */
214147997Srwatsonconst char *
215147997Srwatsonmemstat_get_name(const struct memory_type *mtp)
216147997Srwatson{
217147997Srwatson
218147997Srwatson	return (mtp->mt_name);
219147997Srwatson}
220147997Srwatson
221147997Srwatsonint
222147997Srwatsonmemstat_get_allocator(const struct memory_type *mtp)
223147997Srwatson{
224147997Srwatson
225147997Srwatson	return (mtp->mt_allocator);
226147997Srwatson}
227147997Srwatson
228147997Srwatsonuint64_t
229147997Srwatsonmemstat_get_countlimit(const struct memory_type *mtp)
230147997Srwatson{
231147997Srwatson
232147997Srwatson	return (mtp->mt_countlimit);
233147997Srwatson}
234147997Srwatson
235147997Srwatsonuint64_t
236147997Srwatsonmemstat_get_byteslimit(const struct memory_type *mtp)
237147997Srwatson{
238147997Srwatson
239147997Srwatson	return (mtp->mt_byteslimit);
240147997Srwatson}
241147997Srwatson
242147997Srwatsonuint64_t
243147997Srwatsonmemstat_get_sizemask(const struct memory_type *mtp)
244147997Srwatson{
245147997Srwatson
246147997Srwatson	return (mtp->mt_sizemask);
247147997Srwatson}
248147997Srwatson
249147997Srwatsonuint64_t
250147997Srwatsonmemstat_get_size(const struct memory_type *mtp)
251147997Srwatson{
252147997Srwatson
253147997Srwatson	return (mtp->mt_size);
254147997Srwatson}
255147997Srwatson
256147997Srwatsonuint64_t
257147997Srwatsonmemstat_get_memalloced(const struct memory_type *mtp)
258147997Srwatson{
259147997Srwatson
260147997Srwatson	return (mtp->mt_memalloced);
261147997Srwatson}
262147997Srwatson
263147997Srwatsonuint64_t
264147997Srwatsonmemstat_get_memfreed(const struct memory_type *mtp)
265147997Srwatson{
266147997Srwatson
267147997Srwatson	return (mtp->mt_memfreed);
268147997Srwatson}
269147997Srwatson
270147997Srwatsonuint64_t
271147997Srwatsonmemstat_get_numallocs(const struct memory_type *mtp)
272147997Srwatson{
273147997Srwatson
274147997Srwatson	return (mtp->mt_numallocs);
275147997Srwatson}
276147997Srwatson
277147997Srwatsonuint64_t
278147997Srwatsonmemstat_get_numfrees(const struct memory_type *mtp)
279147997Srwatson{
280147997Srwatson
281147997Srwatson	return (mtp->mt_numfrees);
282147997Srwatson}
283147997Srwatson
284147997Srwatsonuint64_t
285147997Srwatsonmemstat_get_bytes(const struct memory_type *mtp)
286147997Srwatson{
287147997Srwatson
288147997Srwatson	return (mtp->mt_bytes);
289147997Srwatson}
290147997Srwatson
291147997Srwatsonuint64_t
292147997Srwatsonmemstat_get_count(const struct memory_type *mtp)
293147997Srwatson{
294147997Srwatson
295147997Srwatson	return (mtp->mt_count);
296147997Srwatson}
297147997Srwatson
298147997Srwatsonuint64_t
299147997Srwatsonmemstat_get_free(const struct memory_type *mtp)
300147997Srwatson{
301147997Srwatson
302147997Srwatson	return (mtp->mt_free);
303147997Srwatson}
304147997Srwatson
305147997Srwatsonuint64_t
306147997Srwatsonmemstat_get_failures(const struct memory_type *mtp)
307147997Srwatson{
308147997Srwatson
309147997Srwatson	return (mtp->mt_failures);
310147997Srwatson}
311147997Srwatson
312209215Ssbrunouint64_t
313209215Ssbrunomemstat_get_sleeps(const struct memory_type *mtp)
314209215Ssbruno{
315209215Ssbruno
316209215Ssbruno	return (mtp->mt_sleeps);
317209215Ssbruno}
318209215Ssbruno
319147997Srwatsonvoid *
320147997Srwatsonmemstat_get_caller_pointer(const struct memory_type *mtp, int index)
321147997Srwatson{
322147997Srwatson
323147997Srwatson	return (mtp->mt_caller_pointer[index]);
324147997Srwatson}
325147997Srwatson
326147997Srwatsonvoid
327147997Srwatsonmemstat_set_caller_pointer(struct memory_type *mtp, int index, void *value)
328147997Srwatson{
329147997Srwatson
330147997Srwatson	mtp->mt_caller_pointer[index] = value;
331147997Srwatson}
332147997Srwatson
333147997Srwatsonuint64_t
334147997Srwatsonmemstat_get_caller_uint64(const struct memory_type *mtp, int index)
335147997Srwatson{
336147997Srwatson
337147997Srwatson	return (mtp->mt_caller_uint64[index]);
338147997Srwatson}
339147997Srwatson
340147997Srwatsonvoid
341147997Srwatsonmemstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value)
342147997Srwatson{
343147997Srwatson
344147997Srwatson	mtp->mt_caller_uint64[index] = value;
345147997Srwatson}
346147997Srwatson
347147997Srwatsonuint64_t
348147997Srwatsonmemstat_get_zonefree(const struct memory_type *mtp)
349147997Srwatson{
350147997Srwatson
351147997Srwatson	return (mtp->mt_zonefree);
352147997Srwatson}
353147997Srwatson
354147997Srwatsonuint64_t
355148170Srwatsonmemstat_get_kegfree(const struct memory_type *mtp)
356148170Srwatson{
357148170Srwatson
358148170Srwatson	return (mtp->mt_kegfree);
359148170Srwatson}
360148170Srwatson
361148170Srwatsonuint64_t
362147997Srwatsonmemstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu)
363147997Srwatson{
364147997Srwatson
365147997Srwatson	return (mtp->mt_percpu_alloc[cpu].mtp_memalloced);
366147997Srwatson}
367147997Srwatson
368147997Srwatsonuint64_t
369147997Srwatsonmemstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu)
370147997Srwatson{
371147997Srwatson
372147997Srwatson	return (mtp->mt_percpu_alloc[cpu].mtp_memfreed);
373147997Srwatson}
374147997Srwatson
375147997Srwatsonuint64_t
376147997Srwatsonmemstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu)
377147997Srwatson{
378147997Srwatson
379147997Srwatson	return (mtp->mt_percpu_alloc[cpu].mtp_numallocs);
380147997Srwatson}
381147997Srwatson
382147997Srwatsonuint64_t
383147997Srwatsonmemstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu)
384147997Srwatson{
385147997Srwatson
386147997Srwatson	return (mtp->mt_percpu_alloc[cpu].mtp_numfrees);
387147997Srwatson}
388147997Srwatson
389147997Srwatsonuint64_t
390147997Srwatsonmemstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu)
391147997Srwatson{
392147997Srwatson
393147997Srwatson	return (mtp->mt_percpu_alloc[cpu].mtp_sizemask);
394147997Srwatson}
395147997Srwatson
396147997Srwatsonvoid *
397147997Srwatsonmemstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu,
398147997Srwatson    int index)
399147997Srwatson{
400147997Srwatson
401147997Srwatson	return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]);
402147997Srwatson}
403147997Srwatson
404147997Srwatsonvoid
405147997Srwatsonmemstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu,
406147997Srwatson    int index, void *value)
407147997Srwatson{
408147997Srwatson
409147997Srwatson	mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value;
410147997Srwatson}
411147997Srwatson
412147997Srwatsonuint64_t
413147997Srwatsonmemstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu,
414147997Srwatson    int index)
415147997Srwatson{
416147997Srwatson
417147997Srwatson	return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]);
418147997Srwatson}
419147997Srwatson
420147997Srwatsonvoid
421147997Srwatsonmemstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index,
422147997Srwatson    uint64_t value)
423147997Srwatson{
424147997Srwatson
425147997Srwatson	mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value;
426147997Srwatson}
427147997Srwatson
428147997Srwatsonuint64_t
429147997Srwatsonmemstat_get_percpu_free(const struct memory_type *mtp, int cpu)
430147997Srwatson{
431147997Srwatson
432147997Srwatson	return (mtp->mt_percpu_cache[cpu].mtp_free);
433147997Srwatson}
434