1.\" Copyright (c) 2005 Robert N. M. Watson 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd June 27, 2005 28.Os 29.Dt LIBMEMSTAT 3 30.Sh NAME 31.Nm libmemstat 32.Nd "library interface to retrieve kernel memory allocator statistics" 33.Sh LIBRARY 34.Lb libmemstat 35.Sh SYNOPSIS 36.In sys/types.h 37.In memstat.h 38.Ss General Functions 39.Ft const char * 40.Fn memstat_strerror "int error" 41.Ss Memory Type List Management Functions 42.Ft struct memory_type_list * 43.Fn memstat_mtl_alloc "void" 44.Ft struct memory_type * 45.Fn memstat_mtl_first "struct memory_type_list *list" 46.Ft struct memory_type * 47.Fn memstat_mtl_next "struct memory_type *mtp" 48.Ft struct memory_type * 49.Fn memstat_mtl_find "struct memory_type_list *list" "int allocator" "const char *name" 50.Ft void 51.Fn memstat_mtl_free "struct memory_type_list *list" 52.Ft int 53.Fn memstat_mtl_geterror "struct memory_type_list *list" 54.Ss Allocator Query Functions 55.Ft int 56.Fn memstat_sysctl_all "struct memory_type_list *list" "int flags" 57.Ft int 58.Fn memstat_sysctl_malloc "struct memory_type_list *list" "int flags" 59.Ft int 60.Fn memstat_sysctl_uma "struct memory_type_list *list" "int flags" 61.Ss Memory Type Accessor Methods 62.Ft const char * 63.Fn memstat_get_name "const struct memory_type *mtp" 64.Ft int 65.Fn memstat_get_allocator "const struct memory_type *mtp" 66.Ft uint64_t 67.Fn memstat_get_countlimit "const struct memory_type *mtp" 68.Ft uint64_t 69.Fn memstat_get_byteslimit "const struct memory_type *mtp" 70.Ft uint64_t 71.Fn memstat_get_sizemask "const struct memory_type *mtp" 72.Ft uint64_t 73.Fn memstat_get_size "const struct memory_type *mtp" 74.Ft uint64_t 75.Fn memstat_get_memalloced "const struct memory_type *mtp" 76.Ft uint64_t 77.Fn memstat_get_memfreed "const struct memory_type *mtp" 78.Ft uint64_t 79.Fn memstat_get_numallocs "const struct memory_type *mtp" 80.Ft uint64_t 81.Fn memstat_get_numfrees "const struct memory_type *mtp" 82.Ft uint64_t 83.Fn memstat_get_bytes "const struct memory_type *mtp" 84.Ft uint64_t 85.Fn memstat_get_count "const struct memory_type *mtp" 86.Ft uint64_t 87.Fn memstat_get_free "const struct memory_type *mtp" 88.Ft uint64_t 89.Fn memstat_get_failures "const struct memory_type *mtp" 90.Ft void * 91.Fn memstat_get_caller_pointer "const struct memory_type *mtp" "int index" 92.Ft void 93.Fn memstat_set_caller_pointer "struct memory_type *mtp" "int index" "void *value" 94.Ft uint64_t 95.Fn memstat_get_caller_uint64 "const struct memory_type *mtp" "int index" 96.Ft void 97.Fn memstat_set_caller_uint64 "struct memory_type *mtp" "int index" "uint64_t value" 98.Ft uint64_t 99.Fn memstat_get_zonefree "const struct memory_type *mtp" 100.Ft uint64_t 101.Fn memstat_get_kegfree "const struct memory_type *mtp" 102.Ft uint64_t 103.Fn memstat_get_percpu_memalloced "const struct memory_type *mtp" "int cpu" 104.Ft uint64_t 105.Fn memstat_get_percpu_memfreed "const struct memory_type *mtp" "int cpu" 106.Ft uint64_t 107.Fn memstat_get_percpu_numallocs "const struct memory_type *mtp" "int cpu" 108.Ft uint64_t 109.Fn memstat_get_percpu_numfrees "const struct memory_type *mtp" "int cpu" 110.Ft uint64_t 111.Fn memstat_get_percpu_sizemask "const struct memory_type *mtp" "int cpu" 112.Ft void * 113.Fn memstat_get_percpu_caller_pointer "const struct memory_type *mtp" "int cpu" "int index" 114.Ft void 115.Fn memstat_set_percpu_caller_pointer "struct memory_type *mtp" "int cpu" "int index" "void *value" 116.Ft uint64_t 117.Fn memstat_get_percpu_caller_uint64 "const struct memory_type *mtp" "int cpu" "int index" 118.Ft void 119.Fn memstat_set_percpu_caller_uint64 "struct memory_type *mtp" "int cpu" "int index" "uint64_t value" 120.Ft uint64_t 121.Fn memstat_get_percpu_free "const struct memory_type *mtp" "int cpu" 122.Sh DESCRIPTION 123.Nm 124provides an interface to retrieve kernel memory allocator statistics, for 125the purposes of debugging and system monitoring, insulating applications 126from implementation details of the allocators, and allowing a tool to 127transparently support multiple allocators. 128.Nm 129supports both retrieving a single statistics snapshot, as well as 130incrementally updating statistics for long-term monitoring. 131.Pp 132.Nm 133describes each memory type using a 134.Vt struct memory_type , 135an opaque memory type accessed by the application using accessor functions 136in the library. 137.Nm 138returns and updates chains of 139.Vt struct memory_type 140via a 141.Vt struct memory_type_list , 142which will be allocated by calling 143.Fn memstat_mtl_alloc , 144and freed on completion using 145.Fn memstat_mtl_free . 146Lists of memory types are populated via calls that query the kernel for 147statistics information; currently: 148.Fn memstat_sysctl_all , 149.Fn memstat_sysctl_uma , 150and 151.Fn memstat_sysctl_malloc . 152Repeated calls will incrementally update the list of memory types, permitting 153tracking over time without recreating all list state. 154If an error is detected during a query call, error condition information may 155be retrieved using 156.Fn memstat_mtl_geterror , 157and converted to a user-readable string using 158.Fn memstat_strerror . 159.Pp 160Freeing the list will free all memory type data in the list, and so 161invalidates any outstanding pointers to entries in the list. 162.Vt struct memory_type 163entries in the list may be iterated over using 164.Fn memstat_mtl_first 165and 166.fn memstat_mtl_next , 167which respectively return the first entry in a list, and the next entry in a 168list. 169.Fn memstat_mtl_find , 170which will return a pointer to the first entry matching the passed 171parameters. 172.Pp 173A series of accessor methods is provided to access fields of the structure, 174including retrieving statistics and properties, as well as setting of caller 175owned fields. 176Direct application access to the data structure fields is not supported. 177.Ss Library memory_type Fields 178Each 179.Vt struct memory_type 180holds a description of the memory type, including its name and the allocator 181it is managed by, as well as current statistics on use. 182Some statistics are directly measured, others are derived from directly 183measured statistics. 184Certain high level statistics are present across all available allocators, 185such as the number of allocation and free operations; other measurements, 186such as the quantity of free items in per-CPU caches, or administrative 187limit on the number of allocations, is available only for specific 188allocators. 189.Ss Caller memory_type Fields 190.Vt struct memory_type 191includes fields to allow the application to store data, in the form of 192pointers and 64-bit integers, with memory types. 193For example, the application author might make use of one of the caller 194pointers to reference a more complex data structure tracking long-term 195behavior of the memory type, or a window system object that is used to 196render the state of the memory type. 197General and per-CPU storage is provided with each 198.Vt struct memory_type 199in the form of an array of pointers and integers. 200The array entries are accessed via the 201.Fa index 202argument to the get and set accessor methods. 203Possible values of 204.Fa index 205range between 206.Dv 0 207and 208.Dv MEMSTAT_MAXCALLER . 209.Pp 210Caller-owned fields are initialized to 211.Dv 0 212or 213.Dv NULL 214when a new 215.Vt struct memory_type 216is allocated and attached to a memory type list; these fields retain their 217values across queries that update library-owned fields. 218.Ss Allocator Types 219Currently, 220.Nm 221supports two kernel allocators: 222.Dv ALLOCATOR_UMA 223for 224.Xr uma 9 , 225and 226.Dv ALLOCATOR_MALLOC 227for 228.Xr malloc 9 . 229These values may be passed to 230.Fn memstat_mtl_find , 231and will be returned by 232.Fn memstat_get_allocator . 233Two additional constants in the allocator name space are defined: 234.Dv ALLOCATOR_UNKNOWN , 235which will only be returned as a result of a library error, and 236.Dv ALLOCATOR_ANY , 237which can be used to specify that returning types matching any allocator is 238permittible from 239.Fn memstat_mtl_find . 240.Ss Access Method List 241The following accessor methods are defined, of which some will be valid for 242a given memory type: 243.Pp 244.Bl -tag -width "memstat_get_name" -compact -offset wee 245.It memstat_get_name 246Return a pointer to the name of the memory type. 247Memory for the name is owned by 248.Nm 249and will be valid through a call to 250.Fn memstat_mtl_free . 251Note that names will be unique with respect to a single allocator, but that 252the same name might be used by different memory types owned by different 253memory allocators. 254.It memstat_get_allocator 255Return an integer identifier for the memory allocator that owns the memory 256type. 257.It memstat_get_countlimit 258If the memory type has an administrative limit on the number of simultaneous 259allocations, return it. 260.It memstat_get_byteslimit 261If the memory type has an administrative limit on the number of bytes of 262memory that may be simultaenously allocated for the memory type, return it. 263.It memstat_get_sizemask 264If the memory type supports variable allocation sizes, return a bitmask of 265sizes allocated for the memory type. 266.It memstat_get_size 267If the memory type supports a fixed allocation size, return that size. 268.It memstat_get_memalloced 269Return the total number of bytes allocated for the memory type over its 270lifetime. 271.It memstat_get_memfreed 272Return the total number of bytes freed for the memory type over its lifetime. 273.It memstat_get_numallocs 274Return the total number of allocations for the memory type over its lifetime. 275.It memstat_get_numfrees 276Return the total number of frees for the memory type over its lifetime. 277.It memstat_get_bytes 278Return the current number of bytes allocated to the memory type. 279.It memstat_get_count 280Return the current number of allocations for the memory type. 281.It memstat_get_free 282If the memory allocator supports a cache, return the number of items in the 283cache. 284.It memstat_get_failures 285If the memory allocator and type permit allocation failures, return the 286number of allocation failures measured. 287.It memstat_get_caller_pointer 288Return a caller-owned pointer for the memory type. 289.It memstat_set_caller_pointer 290Set a caller-owned pointer for the memory type. 291.It memstat_get_caller_uint64 292Return a caller-owned integer for the memory type. 293.It memstat_set_caller_uint64 294Set a caller-owned integer for the memory type. 295.It memstat_get_zonefree 296If the memory allocator supports a multi-level allocation structure, return 297the number of cached items in the zone. 298These items will be in a fully constructed state available for immediate 299use. 300.It memstat_get_kegfree 301If the memory allocator supports a multi-level allocation structure, return 302the number of cached items in the keg. 303These items may be in a partially constructed state, and may require further 304processing before they can be made available for use. 305.It memstat_get_percpu_memalloced 306If the memory allocator supports per-CPU statistics, return the number of 307bytes of memory allocated for the memory type on the CPU over its lifetime. 308.It memstat_get_percpu_memfreed 309If the memory allocator supports per-CPU statistics, return the number of 310bytes of memory freed from the memory type on the CPU over its lifetime. 311.It memstat_get_percpu_numallocs 312If the memory allocator supports per-CPU statistics, return the number of 313allocations for the memory type on the CPU over its lifetime. 314.It memstat_get_percpu_numfrees 315If the memory allocator supports per-CPU statistics, return the number of 316frees for the memory type on the CPU over its lifetime. 317.It memstat_get_percpu_sizemask 318If the memory allocator supports variable size memory allocation and per-CPU 319statistics, return the size bitmask for the memory type on the CPU. 320.It memstat_get_percpu_caller_pointer 321Return a caller-owned per-CPU pointer for the memory type. 322.It memstat_set_percpu_caller_pointer 323Set a caller-owned per-CPU pointer for the memory type. 324.It memstat_get_percpu_caller_uint64 325Return a caller-owned per-CPU integer for the memory type. 326.It memsttat_set_percpu_caller_uint64 327Set a caller-owned per-CPU integer for the memory type. 328.It memstat_get_percpu_free 329If the memory allocator supports a per-CPU cache, return the number of free 330items in the per-CPU cache of the designated CPU. 331.El 332.Sh RETURN VALUES 333.Nm 334functions fall into three categories: functions returning a pointer to an 335object, functions returning an integer return value, and functions 336implementing accessor methods returning data from a 337.Vt struct memory_type . 338.Pp 339Functions returning a pointer to an object will generally return 340.Dv NULL 341on failure. 342.Fn memstat_mtl_alloc 343will return an error value via 344.Va errno , 345which will consist of the value 346.Dv ENOMEM . 347Functions 348.Fn memstat_mtl_first , 349.Fn memstat_mtl_next , 350and 351.Fn memstat_mtl_find 352will return 353.Dv NULL 354when there is no entry or match in the list; however, this is not considered 355a failure mode and no error value is available. 356.Pp 357Functions returning a integer success valuye will return 358.Dv 0 359on success, or 360.Dv -1 361on failure. 362If a failure is returned, the list error access method, 363.Fn memstat_mtl_geterror , 364may be used to retrieve the error state. 365The string representation of the error may be retrieved using 366.Fn memstat_strerror . 367Possible error values are: 368.Pp 369.Bl -tag -width "MEMSTAT_ERROR_TOOMANYCPUS" -compact -offset wee 370.It Dv MEMSTAT_ERROR_UNDEFINED 371Undefined error. Occurs if 372.Fn memstat_mtl_geterror 373is called on a list before an error associated with the list has occurred. 374.It Dv MEMSTAT_ERROR_NOMEMORY 375Insufficient memory. Occurs if library calls to 376.Xr malloc 3 377fail, or if a system call to retrieve kernel statistics fails with 378.Er ENOMEM . 379.It Dv MEMSTAT_ERROR_VERSION 380Returned if the current version of 381.Nm 382is unable to interpret the statistics data returned by the kernel due to an 383explicit version mismatch, or to differences in data structures that cannot 384be reconciled. 385.It Dv MEMSTAT_ERROR_PERMISSION 386Returned if a statistics source returns 387.Va errno 388values of 389.Dv EACCES 390or 391.Dv EPERM . 392.It Dv MEMSTAT_ERROR_TOOMANYCPUS 393Returned if the compile-time limit on the number of CPUs in 394.Nm 395is lower than the number of CPUs returned by a statistics data source. 396.It Dv MEMSTAT_ERROR_DATAERROR 397Returned if 398.Nm 399is unable to interpret statistics data returned by the data source, even 400though there does not appear to be a version problem. 401.El 402.Pp 403Finally, functions returning data from a 404.Dt struct memory_type 405pointer are not permitted to fail, and directly return either a statistic 406or pointer to a string. 407.Sh EXAMPLES 408Create a memory type list, query the 409.Xr uma 9 410memory allocator for available statistics, and print out the number of 411allocations performed by the 412.Dv Mbuf 413zone. 414.Bd -literal -offset indent 415struct memory_type_list *mtlp; 416struct memory_type *mtp; 417uint64_t mbuf_count; 418 419mtlp = memstat_mtl_alloc(); 420if (mtlp == NULL) 421 err(-1, "memstat_mtl_alloc"); 422if (memstat_sysctl_uma(mtlp, 0) < 0) 423 err(-1, "memstat_sysctl_uma"); 424mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, "Mbuf"); 425if (mtp == NULL) 426 errx(-1, "memstat_mtl_find: Mbuf not found"); 427mbuf_count = memstat_get_count(mtp); 428memstat_mtl_free(mtlp); 429 430printf("Mbufs: %llu\\n", (unsigned long long)mbuf_count); 431.Ed 432.Sh SEE ALSO 433.Xr malloc 9 , 434.Xr uma 9 435.Sh HISTORY 436The 437.Nm libmemstat 438library appeared in 439.Fx 6.0 . 440.Sh AUTHORS 441The kernel memory allocator changes necessary to support a general purpose 442monitoring library, along with the library, were written by 443.An Robert Watson Aq [email protected] 444.Sh BUGS 445.Nm 446cannot yet extract statistics from kernel core dumps, although this should be 447straight forward to implement. 448.Pp 449Once a memory type is present on a memory type list, it will not be removed 450even if the kernel no longer presents information on the type via its 451monitoring interfaces. 452In order to flush removed memory types, it is necessary to free the entire 453list and allocate a new one. 454