|
|
#include <sys/types.h> #include <sys/param.h> #include <sys/kmem.h>void *kmem_alloc(size_t nbytes, int flags);
void *kmem_zalloc(size_t nbytes, int flags);
The actual size of the memory allocated may be larger than requested. Callers should act as if precisely nbytes were returned. The implementation reserves the right to change the underlying details of the allocator.
kmem_zalloc( ) is identical to kmem_alloc( ), with the additional feature of setting the contents of the allocated buffer to all zeros before returning. kmem_zalloc( ) is a special case of kmem_alloc( ); for the rest of this document, information about kmem_alloc( ) also applies to kmem_zalloc( ).
The KM_NOSLEEP flag must be used when kmem_alloc( ) is called from interrupt or initialization context.
In most cases, kmem_alloc( ) should pass the KM_NO_DMA flag so that the memory can be allocated above the 16MB boundary. Memory that is allocated without this flag comes from the ISA DMA-able memory pool of memory below 16MB. This is an extremely limited resource that should be consumed only when absolutely necessary, such as when you will be performing ISA DMA to or from the allocated memory. PCI DMA and other newer forms of DMA do not require memory allocation in the lower 16MB range.
The following implementation details are subject to change and are provided only to help developers understand current behavior.
kmem_alloc( ) allocates memory from pools of power-of-2 chunk sizes from 16 to 8192 bytes. The sizes of these pools are determined by the psz[] values in the /etc/conf/pack.d/kernel/space.c file. A kernel daemon, kmdaemon, runs periodically to replenish pools that are close to exhaustion. This asynchronous allocation reduces the probability that a specific caller of kmem_alloc( ) will have to wait for an underlying allocation.
When allocations are made quickly, it is possible for the pools to be exhausted before kmdaemon can run. In that case, kmem_alloc( ) calls the underlying allocator, sptalloc(D3oddi), directly. This happens only if the pool is completely empty and must be replenished to satisfy the call.
If a pool must be replenished from a kmem_alloc( ) call that was passed with the KM_NOSLEEP flag specified, The similar NOSLEEP flag is passed to sptalloc( ). As a result, allocation can fail, causing the overall kmem_alloc( ) to fail. In this event, a flag is set that causes kmdaemon to run as soon as possible, without waiting for its next periodic timer event.
A call to kmem_alloc( ) with the KM_SLEEP flag never returns NULL. If memory is not immediately available, it sleeps until the memory is available. If it returns at all, the returned pointer is a valid pointer to valid memory of the desired variety and does not need to be checked. The length of the sleep( ) is not bounded; under extreme and persistent shortages of memory, a caller could sleep ``forever'', meaning until the system is shutdown. This should not be a matter of great concern to a driver writer; it is a condition that can occur only when the memory allocation subsystem is so compromised that the system can only recover by being rebooted.
When kmem_alloc( ) is passed the KM_NOSLEEP flag, it will occasionally return a NULL pointer. The caller must check for this and behave correctly.
If an allocation fails, this implies that a pool was exhausted and the calling process was not allowed to sleep until memory was available. In order for a subsequent allocation to succeed, the allocator must be allowed to run in its own context. For example, if a caller is trying to allocate memory from an interrupt context, a failure will persist until the caller returns from its interrupt, allowing kmdaemon to run. Drivers should deal with this by (1) minimizing the need to allocate memory at interrupt time and (2) having a strategy that allows activity to be deferred until a later time (after returning from the interrupt and allowing kmdaemon to run).
If flag contains KM_NOSLEEP, any context.
To allocate ISA DMA-able memory in DDI 6/6mp and later, use the kmem_alloc_phys(D3), kmem_alloc_physreq(D3), or kmem_zalloc_physreq(D3) function. For DDI 5/5mp and earlier, memory allocated with kmem_alloc(D3) is always below the 16MB boundary and no mechanism is provided for allocating memory above the 16MB boundary.
``Memory allocation'' in HDK Technical Reference