KMEM(9) | Kernel Developer's Manual | KMEM(9) |
kmem
—
#include <sys/kmem.h>
void *
kmem_alloc
(size_t
size, km_flag_t
kmflags);
void *
kmem_zalloc
(size_t
size, km_flag_t
kmflags);
void
kmem_free
(void
*p, size_t
size);
void *
kmem_intr_alloc
(size_t
size, km_flag_t
kmflags);
void *
kmem_intr_zalloc
(size_t
size, km_flag_t
kmflags);
void
kmem_intr_free
(void
*p, size_t
size);
char *
kmem_asprintf
(const
char *fmt,
...);
char *
kmem_strdupsize
(const
char *str, size_t
*size, km_flag_t
kmflags);
char *
kmem_strdup
(const
char *str, km_flag_t
kmflags);
char *
kmem_strndup
(const
char *str, size_t
manxlen, km_flag_t
kmflags);
void
kmem_strfree
(char
*str);
void *
kmem_tmpbuf_alloc
(size_t
size, void
*stackbuf, size_t
stackbufsize, km_flag_t
kmflags);
void
kmem_tmpbuf_free
(void
*p, size_t size,
void *stackbuf);
options KMEM_SIZE
kmem_alloc
() allocates kernel wired memory. It takes the
following arguments.
KM_SLEEP
KM_SLEEP
is specified,
then the allocation cannot fail.KM_NOSLEEP
NULL
if there
is not enough memory available. It should only be used when failure to
allocate will not have harmful, user-visible effects.
KM_NOSLEEP
is strongly
discouraged as it can create transient, hard to debug failures that
occur when the system is under memory pressure.In situations where it is not possible to sleep, for example because locks are held by the caller, the code path should be restructured to allow the allocation to be made in another place.
The contents of allocated memory are uninitialized.
Unlike Solaris, kmem_alloc(0, flags) is illegal.
kmem_zalloc
() is the equivalent of
kmem_alloc
(), except that it initializes the memory
to zero.
kmem_asprintf
() functions as the well
known asprintf
() function, but allocates memory
using kmem_alloc
(). This routine can sleep during
allocation. The size of the allocated area is the length of the returned
character string, plus one (for the NUL terminator). This must be taken into
consideration when freeing the returned area with
kmem_free
().
kmem_free
() frees kernel wired memory
allocated by kmem_alloc
() or
kmem_zalloc
() so that it can be used for other
purposes. It takes the following arguments.
kmem_alloc
() or
kmem_zalloc
().kmem_alloc
() or
kmem_zalloc
() when the memory was allocated.Freeing NULL
is illegal.
kmem_intr_alloc
(),
kmem_intr_zalloc
() and
kmem_intr_free
() are the equivalents of the above
kmem routines which can be called from the interrupt context. These routines
are for the special cases. Normally,
pool_cache(9) should be
used for memory allocation from interrupt context.
The kmem_strdupsize
() function is a
utility function that can be used to copy the string in the
str argument to a new buffer allocated using
kmem_alloc
() and optionally return the size of the
allocation (the length of the string plus the trailing
NUL
) in the size argument if
that is not NULL
.
The kmem_strdup
() function is a simplified
version of kmem_strdupsize
() that does not return
the size of the allocation.
The kmem_strndup
() function is variation
of kmem_strdup
() that copies at most
maxlen characters from the string
str always NUL terminating the copied string.
The kmem_strfree
() function can be used to
free a NUL
terminated string computing the length of
the string using strlen(3) and
adding one for the NUL
and then using
kmem_free
().
The kmem_tmpbuf_alloc
() function is a
utility function for allocating memory for temporary use, where allocation
on the stack is desirable, but only up to a certain size. If the requested
size fits within the specified stack buffer, the stack buffer is returned.
Otherwise, memory is allocated with kmem_alloc
().
The kmem_tmpbuf_free
() function compares the result
of a previous call to kmem_tmpbuf_alloc
() and frees
the memory using kmem_free
() if it is not the
specified stack buffer.
KM_SLEEP
allocations while holding mutexes or
reader/writer locks is discouraged, as the caller can sleep for an unbounded
amount of time in order to satisfy the allocation. This can in turn block
other threads that wish to acquire locks held by the caller. It should be
noted that kmem_free
() may also block.
For some locks this is permissible or even unavoidable. For others, particularly locks that may be taken from soft interrupt context, it is a serious problem. As a general rule it is better not to allow this type of situation to develop. One way to circumvent the problem is to make allocations speculative and part of a retryable sequence. For example:
retry: /* speculative unlocked check */ if (need to allocate) { new_item = kmem_alloc(sizeof(*new_item), KM_SLEEP); } else { new_item = NULL; } mutex_enter(lock); /* check while holding lock for true status */ if (need to allocate) { if (new_item == NULL) { mutex_exit(lock); goto retry; } consume(new_item); new_item = NULL; } mutex_exit(lock); if (new_item != NULL) { /* did not use it after all */ kmem_free(new_item, sizeof(*new_item)); }
KMEM_SIZE
option ensure the
size given in kmem_free
() matches the actual allocated
size. On kmem_alloc
(), the kernel will allocate an
additional contiguous kmem page of eight bytes in the buffer, will register
the allocated size in the first kmem page of that buffer, and will return a
pointer to the second kmem page in that same buffer. When freeing, the kernel
reads the first page, and compares the size registered with the one given in
kmem_free
(). Any mismatch triggers a panic.
KMEM_SIZE
is enabled by default on
DIAGNOSTIC
.
kmem_alloc
(),
kmem_asprintf
(),
kmem_intr_alloc
(),
kmem_intr_zalloc
(),
kmem_strdupsize
(), and
kmem_zalloc
() return a pointer to allocated memory.
Otherwise, NULL
is returned.
kmem
subsystem is implemented within the file
sys/kern/subr_kmem.c.
kmem_alloc
(),
kmem_asprintf
(), kmem_free
(),
kmem_strdupsize
(),
kmem_strfree
(), and
kmem_zalloc
() functions cannot be used from interrupt
context, from a soft interrupt, or from a callout. Use
pool_cache(9) in these
situations.
kmem_alloc
() is
uninitialized, it can contain security-sensitive data left by its previous
user. It is the caller's responsibility not to expose it to the world.
January 24, 2021 | NetBSD 10.1 |