1882360b9b
dynamic memory allocation to hold per-CPU memory types data (sized to mp_maxid for UMA, and to mp_maxcpus for malloc to match the kernel). That fixes libmemstat with arbitrary large MAXCPU values and therefore eliminates MEMSTAT_ERROR_TOOMANYCPUS error type. Reviewed by: jhb Approved by: re (kib)
493 lines
17 KiB
Groff
493 lines
17 KiB
Groff
.\" Copyright (c) 2005 Robert N. M. Watson
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
.\" SUCH DAMAGE.
|
|
.\"
|
|
.\" $FreeBSD$
|
|
.\"
|
|
.Dd July 21, 2011
|
|
.Dt LIBMEMSTAT 3
|
|
.Os
|
|
.Sh NAME
|
|
.Nm libmemstat
|
|
.Nd "library interface to retrieve kernel memory allocator statistics"
|
|
.Sh LIBRARY
|
|
.Lb libmemstat
|
|
.Sh SYNOPSIS
|
|
.In sys/types.h
|
|
.In memstat.h
|
|
.Ss General Functions
|
|
.Ft "const char *"
|
|
.Fn memstat_strerror "int error"
|
|
.Ss Memory Type List Management Functions
|
|
.Ft "struct memory_type_list *"
|
|
.Fn memstat_mtl_alloc "void"
|
|
.Ft "struct memory_type *"
|
|
.Fn memstat_mtl_first "struct memory_type_list *list"
|
|
.Ft "struct memory_type *"
|
|
.Fn memstat_mtl_next "struct memory_type *mtp"
|
|
.Ft "struct memory_type *"
|
|
.Fo memstat_mtl_find
|
|
.Fa "struct memory_type_list *list" "int allocator" "const char *name"
|
|
.Fc
|
|
.Ft void
|
|
.Fn memstat_mtl_free "struct memory_type_list *list"
|
|
.Ft int
|
|
.Fn memstat_mtl_geterror "struct memory_type_list *list"
|
|
.Ss Allocator Query Functions
|
|
.Ft int
|
|
.Fn memstat_kvm_all "struct memory_type_list *list" "void *kvm_handle"
|
|
.Ft int
|
|
.Fn memstat_kvm_malloc "struct memory_type_list *list" "void *kvm_handle"
|
|
.Ft int
|
|
.Fn memstat_kvm_uma "struct memory_type_list *list" "void *kvm_handle"
|
|
.Ft int
|
|
.Fn memstat_sysctl_all "struct memory_type_list *list" "int flags"
|
|
.Ft int
|
|
.Fn memstat_sysctl_malloc "struct memory_type_list *list" "int flags"
|
|
.Ft int
|
|
.Fn memstat_sysctl_uma "struct memory_type_list *list" "int flags"
|
|
.Ss Memory Type Accessor Methods
|
|
.Ft "const char *"
|
|
.Fn memstat_get_name "const struct memory_type *mtp"
|
|
.Ft int
|
|
.Fn memstat_get_allocator "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_countlimit "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_byteslimit "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_sizemask "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_size "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_memalloced "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_memfreed "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_numallocs "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_numfrees "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_bytes "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_count "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_free "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_failures "const struct memory_type *mtp"
|
|
.Ft "void *"
|
|
.Fn memstat_get_caller_pointer "const struct memory_type *mtp" "int index"
|
|
.Ft void
|
|
.Fo memstat_set_caller_pointer
|
|
.Fa "struct memory_type *mtp" "int index" "void *value"
|
|
.Fc
|
|
.Ft uint64_t
|
|
.Fn memstat_get_caller_uint64 "const struct memory_type *mtp" "int index"
|
|
.Ft void
|
|
.Fo memstat_set_caller_uint64
|
|
.Fa "struct memory_type *mtp" "int index" "uint64_t value"
|
|
.Fc
|
|
.Ft uint64_t
|
|
.Fn memstat_get_zonefree "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_kegfree "const struct memory_type *mtp"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_percpu_memalloced "const struct memory_type *mtp" "int cpu"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_percpu_memfreed "const struct memory_type *mtp" "int cpu"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_percpu_numallocs "const struct memory_type *mtp" "int cpu"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_percpu_numfrees "const struct memory_type *mtp" "int cpu"
|
|
.Ft uint64_t
|
|
.Fn memstat_get_percpu_sizemask "const struct memory_type *mtp" "int cpu"
|
|
.Ft "void *"
|
|
.Fo memstat_get_percpu_caller_pointer
|
|
.Fa "const struct memory_type *mtp" "int cpu" "int index"
|
|
.Fc
|
|
.Ft void
|
|
.Fo memstat_set_percpu_caller_pointer
|
|
.Fa "struct memory_type *mtp" "int cpu" "int index" "void *value"
|
|
.Fc
|
|
.Ft uint64_t
|
|
.Fo memstat_get_percpu_caller_uint64
|
|
.Fa "const struct memory_type *mtp" "int cpu" "int index"
|
|
.Fc
|
|
.Ft void
|
|
.Fo memstat_set_percpu_caller_uint64
|
|
.Fa "struct memory_type *mtp" "int cpu" "int index" "uint64_t value"
|
|
.Fc
|
|
.Ft uint64_t
|
|
.Fn memstat_get_percpu_free "const struct memory_type *mtp" "int cpu"
|
|
.Sh DESCRIPTION
|
|
.Nm
|
|
provides an interface to retrieve kernel memory allocator statistics, for
|
|
the purposes of debugging and system monitoring, insulating applications
|
|
from implementation details of the allocators, and allowing a tool to
|
|
transparently support multiple allocators.
|
|
.Nm
|
|
supports both retrieving a single statistics snapshot, as well as
|
|
incrementally updating statistics for long-term monitoring.
|
|
.Pp
|
|
.Nm
|
|
describes each memory type using a
|
|
.Vt "struct memory_type" ,
|
|
an opaque memory type accessed by the application using accessor functions
|
|
in the library.
|
|
.Nm
|
|
returns and updates chains of
|
|
.Vt "struct memory_type"
|
|
via a
|
|
.Vt "struct memory_type_list" ,
|
|
which will be allocated by calling
|
|
.Fn memstat_mtl_alloc ,
|
|
and freed on completion using
|
|
.Fn memstat_mtl_free .
|
|
Lists of memory types are populated via calls that query the kernel for
|
|
statistics information; currently:
|
|
.Fn memstat_kvm_all ,
|
|
.Fn memstat_kvm_malloc ,
|
|
.Fn memstat_kvm_uma ,
|
|
.Fn memstat_sysctl_all ,
|
|
.Fn memstat_sysctl_uma ,
|
|
and
|
|
.Fn memstat_sysctl_malloc .
|
|
Repeated calls will incrementally update the list of memory types, permitting
|
|
tracking over time without recreating all list state.
|
|
If an error is detected during a query call, error condition information may
|
|
be retrieved using
|
|
.Fn memstat_mtl_geterror ,
|
|
and converted to a user-readable string using
|
|
.Fn memstat_strerror .
|
|
.Pp
|
|
Freeing the list will free all memory type data in the list, and so
|
|
invalidates any outstanding pointers to entries in the list.
|
|
.Vt "struct memory_type"
|
|
entries in the list may be iterated over using
|
|
.Fn memstat_mtl_first
|
|
and
|
|
.Fn memstat_mtl_next ,
|
|
which respectively return the first entry in a list, and the next entry in a
|
|
list.
|
|
.Fn memstat_mtl_find ,
|
|
which will return a pointer to the first entry matching the passed
|
|
parameters.
|
|
.Pp
|
|
A series of accessor methods is provided to access fields of the structure,
|
|
including retrieving statistics and properties, as well as setting of caller
|
|
owned fields.
|
|
Direct application access to the data structure fields is not supported.
|
|
.Ss Library Vt memory_type Ss Fields
|
|
Each
|
|
.Vt "struct memory_type"
|
|
holds a description of the memory type, including its name and the allocator
|
|
it is managed by, as well as current statistics on use.
|
|
Some statistics are directly measured, others are derived from directly
|
|
measured statistics.
|
|
Certain high level statistics are present across all available allocators,
|
|
such as the number of allocation and free operations; other measurements,
|
|
such as the quantity of free items in per-CPU caches, or administrative
|
|
limit on the number of allocations, is available only for specific
|
|
allocators.
|
|
.Ss Caller Vt memory_type Ss Fields
|
|
.Vt "struct memory_type"
|
|
includes fields to allow the application to store data, in the form of
|
|
pointers and 64-bit integers, with memory types.
|
|
For example, the application author might make use of one of the caller
|
|
pointers to reference a more complex data structure tracking long-term
|
|
behavior of the memory type, or a window system object that is used to
|
|
render the state of the memory type.
|
|
General and per-CPU storage is provided with each
|
|
.Vt "struct memory_type"
|
|
in the form of an array of pointers and integers.
|
|
The array entries are accessed via the
|
|
.Fa index
|
|
argument to the get and set accessor methods.
|
|
Possible values of
|
|
.Fa index
|
|
range between
|
|
0
|
|
and
|
|
.Dv MEMSTAT_MAXCALLER .
|
|
.Pp
|
|
Caller-owned fields are initialized to
|
|
0
|
|
or
|
|
.Dv NULL
|
|
when a new
|
|
.Vt "struct memory_type"
|
|
is allocated and attached to a memory type list; these fields retain their
|
|
values across queries that update library-owned fields.
|
|
.Ss Allocator Types
|
|
Currently,
|
|
.Nm
|
|
supports two kernel allocators:
|
|
.Dv ALLOCATOR_UMA
|
|
for
|
|
.Xr uma 9 ,
|
|
and
|
|
.Dv ALLOCATOR_MALLOC
|
|
for
|
|
.Xr malloc 9 .
|
|
These values may be passed to
|
|
.Fn memstat_mtl_find ,
|
|
and will be returned by
|
|
.Fn memstat_get_allocator .
|
|
Two additional constants in the allocator name space are defined:
|
|
.Dv ALLOCATOR_UNKNOWN ,
|
|
which will only be returned as a result of a library error, and
|
|
.Dv ALLOCATOR_ANY ,
|
|
which can be used to specify that returning types matching any allocator is
|
|
permittable from
|
|
.Fn memstat_mtl_find .
|
|
.Ss Access Method List
|
|
The following accessor methods are defined, of which some will be valid for
|
|
a given memory type:
|
|
.Bl -tag -width indent
|
|
.It Fn memstat_get_name
|
|
Return a pointer to the name of the memory type.
|
|
Memory for the name is owned by
|
|
.Nm
|
|
and will be valid through a call to
|
|
.Fn memstat_mtl_free .
|
|
Note that names will be unique with respect to a single allocator, but that
|
|
the same name might be used by different memory types owned by different
|
|
memory allocators.
|
|
.It Fn memstat_get_allocator
|
|
Return an integer identifier for the memory allocator that owns the memory
|
|
type.
|
|
.It Fn memstat_get_countlimit
|
|
If the memory type has an administrative limit on the number of simultaneous
|
|
allocations, return it.
|
|
.It Fn memstat_get_byteslimit
|
|
If the memory type has an administrative limit on the number of bytes of
|
|
memory that may be simultaneously allocated for the memory type, return it.
|
|
.It Fn memstat_get_sizemask
|
|
If the memory type supports variable allocation sizes, return a bitmask of
|
|
sizes allocated for the memory type.
|
|
.It Fn memstat_get_size
|
|
If the memory type supports a fixed allocation size, return that size.
|
|
.It Fn memstat_get_memalloced
|
|
Return the total number of bytes allocated for the memory type over its
|
|
lifetime.
|
|
.It Fn memstat_get_memfreed
|
|
Return the total number of bytes freed for the memory type over its lifetime.
|
|
.It Fn memstat_get_numallocs
|
|
Return the total number of allocations for the memory type over its lifetime.
|
|
.It Fn memstat_get_numfrees
|
|
Return the total number of frees for the memory type over its lifetime.
|
|
.It Fn memstat_get_bytes
|
|
Return the current number of bytes allocated to the memory type.
|
|
.It Fn memstat_get_count
|
|
Return the current number of allocations for the memory type.
|
|
.It Fn memstat_get_free
|
|
If the memory allocator supports a cache, return the number of items in the
|
|
cache.
|
|
.It Fn memstat_get_failures
|
|
If the memory allocator and type permit allocation failures, return the
|
|
number of allocation failures measured.
|
|
.It Fn memstat_get_caller_pointer
|
|
Return a caller-owned pointer for the memory type.
|
|
.It Fn memstat_set_caller_pointer
|
|
Set a caller-owned pointer for the memory type.
|
|
.It Fn memstat_get_caller_uint64
|
|
Return a caller-owned integer for the memory type.
|
|
.It Fn memstat_set_caller_uint64
|
|
Set a caller-owned integer for the memory type.
|
|
.It Fn memstat_get_zonefree
|
|
If the memory allocator supports a multi-level allocation structure, return
|
|
the number of cached items in the zone.
|
|
These items will be in a fully constructed state available for immediate
|
|
use.
|
|
.It Fn memstat_get_kegfree
|
|
If the memory allocator supports a multi-level allocation structure, return
|
|
the number of cached items in the keg.
|
|
These items may be in a partially constructed state, and may require further
|
|
processing before they can be made available for use.
|
|
.It Fn memstat_get_percpu_memalloced
|
|
If the memory allocator supports per-CPU statistics, return the number of
|
|
bytes of memory allocated for the memory type on the CPU over its lifetime.
|
|
.It Fn memstat_get_percpu_memfreed
|
|
If the memory allocator supports per-CPU statistics, return the number of
|
|
bytes of memory freed from the memory type on the CPU over its lifetime.
|
|
.It Fn memstat_get_percpu_numallocs
|
|
If the memory allocator supports per-CPU statistics, return the number of
|
|
allocations for the memory type on the CPU over its lifetime.
|
|
.It Fn memstat_get_percpu_numfrees
|
|
If the memory allocator supports per-CPU statistics, return the number of
|
|
frees for the memory type on the CPU over its lifetime.
|
|
.It Fn memstat_get_percpu_sizemask
|
|
If the memory allocator supports variable size memory allocation and per-CPU
|
|
statistics, return the size bitmask for the memory type on the CPU.
|
|
.It Fn memstat_get_percpu_caller_pointer
|
|
Return a caller-owned per-CPU pointer for the memory type.
|
|
.It Fn memstat_set_percpu_caller_pointer
|
|
Set a caller-owned per-CPU pointer for the memory type.
|
|
.It Fn memstat_get_percpu_caller_uint64
|
|
Return a caller-owned per-CPU integer for the memory type.
|
|
.It Fn memsttat_set_percpu_caller_uint64
|
|
Set a caller-owned per-CPU integer for the memory type.
|
|
.It Fn memstat_get_percpu_free
|
|
If the memory allocator supports a per-CPU cache, return the number of free
|
|
items in the per-CPU cache of the designated CPU.
|
|
.El
|
|
.Sh RETURN VALUES
|
|
.Nm
|
|
functions fall into three categories: functions returning a pointer to an
|
|
object, functions returning an integer return value, and functions
|
|
implementing accessor methods returning data from a
|
|
.Vt "struct memory_type" .
|
|
.Pp
|
|
Functions returning a pointer to an object will generally return
|
|
.Dv NULL
|
|
on failure.
|
|
.Fn memstat_mtl_alloc
|
|
will return an error value via
|
|
.Va errno ,
|
|
which will consist of the value
|
|
.Er ENOMEM .
|
|
Functions
|
|
.Fn memstat_mtl_first ,
|
|
.Fn memstat_mtl_next ,
|
|
and
|
|
.Fn memstat_mtl_find
|
|
will return
|
|
.Dv NULL
|
|
when there is no entry or match in the list; however, this is not considered
|
|
a failure mode and no error value is available.
|
|
.Pp
|
|
Functions returning an integer success value will return
|
|
0
|
|
on success, or
|
|
\-1
|
|
on failure.
|
|
If a failure is returned, the list error access method,
|
|
.Fn memstat_mtl_geterror ,
|
|
may be used to retrieve the error state.
|
|
The string representation of the error may be retrieved using
|
|
.Fn memstat_strerror .
|
|
Possible error values are:
|
|
.Bl -tag -width ".Dv MEMSTAT_ERROR_KVM_SHORTREAD"
|
|
.It Dv MEMSTAT_ERROR_UNDEFINED
|
|
Undefined error.
|
|
Occurs if
|
|
.Fn memstat_mtl_geterror
|
|
is called on a list before an error associated with the list has occurred.
|
|
.It Dv MEMSTAT_ERROR_NOMEMORY
|
|
Insufficient memory.
|
|
Occurs if library calls to
|
|
.Xr malloc 3
|
|
fail, or if a system call to retrieve kernel statistics fails with
|
|
.Er ENOMEM .
|
|
.It Dv MEMSTAT_ERROR_VERSION
|
|
Returned if the current version of
|
|
.Nm
|
|
is unable to interpret the statistics data returned by the kernel due to an
|
|
explicit version mismatch, or to differences in data structures that cannot
|
|
be reconciled.
|
|
.It Dv MEMSTAT_ERROR_PERMISSION
|
|
Returned if a statistics source returns
|
|
.Va errno
|
|
values of
|
|
.Er EACCES
|
|
or
|
|
.Er EPERM .
|
|
.It Dv MEMSTAT_ERROR_DATAERROR
|
|
Returned if
|
|
.Nm
|
|
is unable to interpret statistics data returned by the data source, even
|
|
though there does not appear to be a version problem.
|
|
.It Dv MEMSTAT_ERROR_KVM
|
|
Returned if
|
|
.Nm
|
|
experiences an error while using
|
|
.Xr kvm 3
|
|
interfaces to query statistics data.
|
|
Use
|
|
.Xr kvm_geterr 3
|
|
to retrieve the error.
|
|
.It Dv MEMSTAT_ERROR_KVM_NOSYMBOL
|
|
Returned if
|
|
.Nm
|
|
is unable to read a required symbol from the kernel being operated on.
|
|
.It Dv MEMSTAT_ERROR_KVM_SHORTREAD
|
|
Returned if
|
|
.Nm
|
|
attempts to read data from a live memory image or kernel core dump and
|
|
insufficient data is returned.
|
|
.El
|
|
.Pp
|
|
Finally, functions returning data from a
|
|
.Vt "struct memory_type"
|
|
pointer are not permitted to fail, and directly return either a statistic
|
|
or pointer to a string.
|
|
.Sh EXAMPLES
|
|
Create a memory type list, query the
|
|
.Xr uma 9
|
|
memory allocator for available statistics, and print out the number of
|
|
allocations performed by the
|
|
.Dv mbuf
|
|
zone.
|
|
.Bd -literal -offset indent
|
|
struct memory_type_list *mtlp;
|
|
struct memory_type *mtp;
|
|
uint64_t mbuf_count;
|
|
|
|
mtlp = memstat_mtl_alloc();
|
|
if (mtlp == NULL)
|
|
err(-1, "memstat_mtl_alloc");
|
|
if (memstat_sysctl_uma(mtlp, 0) < 0)
|
|
err(-1, "memstat_sysctl_uma");
|
|
mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, "mbuf");
|
|
if (mtp == NULL)
|
|
errx(-1, "memstat_mtl_find: mbuf not found");
|
|
mbuf_count = memstat_get_count(mtp);
|
|
memstat_mtl_free(mtlp);
|
|
|
|
printf("mbufs: %llu\en", (unsigned long long)mbuf_count);
|
|
.Ed
|
|
.Sh SEE ALSO
|
|
.Xr malloc 9 ,
|
|
.Xr uma 9
|
|
.Sh HISTORY
|
|
The
|
|
.Nm
|
|
library appeared in
|
|
.Fx 6.0 .
|
|
.Sh AUTHORS
|
|
The kernel memory allocator changes necessary to support a general purpose
|
|
monitoring library, along with the library, were written by
|
|
.An Robert Watson Aq rwatson@FreeBSD.org .
|
|
.Sh BUGS
|
|
There are memory allocators in the kernel, such as the VM page allocator
|
|
and
|
|
.Nm sf_buf
|
|
allocator, which are not currently supported by
|
|
.Nm .
|
|
.Pp
|
|
Once a memory type is present on a memory type list, it will not be removed
|
|
even if the kernel no longer presents information on the type via its
|
|
monitoring interfaces.
|
|
In order to flush removed memory types, it is necessary to free the entire
|
|
list and allocate a new one.
|