Memory allocation
The
DDI
and
ODDI
interfaces each provide several functions
for allocating private memory for a driver.
The differences between the functions
concern the properties of the memory that is allocated
and when the memory is allocated.
Drivers allocate some memory that is only accessed by the kernel itself
and other memory that is accessed
by both the kernel and the device.
physical alignment-
Some operations require specific alignment properties,
such as needing to aligned on a page boundary.
zeroed out memory-
The memory that is allocated may have been used previously
and contain data.
Such memory can be zeroed out after it is allocated,
but it is more efficient to use a memory allocation function
that zeroes out the allocated memory as part of the allocation.
context for allocation-
Some restrictions apply to the context in which
memory is allocated.
This is a special concern when memory must be allocated
from initialization or interrupt context; see
``Context of a driver''.
device requirements-
Memory accessed directly by devices for I/O operations
may have special physical requirements
such as memory range, contiguity, and granularity.
These issues are discussed in the articles
about the specific I/O strategies:
``DMA'',
``Memory-mapped I/O'',
``Programmed I/O (PIO)''.
Kernel memory is a limited resource
and should be used judiciously.
The following guidelines apply
to memory allocation:
-
Drivers should free memory as soon as possible
after it is allocated,
using the memory deallocation function
that corresponds to the memory allocation function.
-
Drivers should not allocate memory
using schemes such as local freelists
that cause memory to be held for longer than necessary
because this can have an adverse effect
on overall memory usage and system performance.
-
When it is necessary to hold memory for long periods of time
(such as allocating memory at system startup
and never freeing it),
it is better to allocate the memory statically
in driver data or bss.
-
Physically-contiguous memory
should be allocated as early as possible,
preferably during system initialization.
This is because the free page list is randomized
and physically contiguous pages may not be available
after the system has run at load for some time.
See
``Allocating large chunks of memory''
for information about allocating
large chunks of memory,
especially if it must be physically contiguous.
-
Memory below the 16MB boundary
is especially valuable.
DMA buffers for ISA DMA cards
must be allocated below the 16MB range
but most other allocations can be in the higher ranges.
When porting drivers to SCO OpenServer 5 from other platforms,
be sure to specify the KM_NO_DMA flag for the
kmem_alloc(D3oddi)
functions unless you truly need
memory below the 16MB range.
DDI implementation
Three main structures are used with DDI functions
that allocate memory and need to specify
special properties for that memory:
bcb(D4)-
Breakup control block, passed to the
buf_breakup(D3)
function to control parceling the data
to be transferred through a scatter/gather scheme.
physreq(D4)-
Structure that defines physical address alignment
and contiguity constraints
for memory to be allocated.
scgth(D4) (DDI 8 and later only)-
Describes the scatter/gather list.
The following functions are supported
for allocating memory in DDI drivers.
Check the manual pages for version-specific information.
kmem_alloc(D3)-
Allocate memory in the physical address range
0,0x10000000 that is physically contiguous
only if the allocation size is
less than or equal to one page, given by
ptob(D3).
Physical alignment is to the next highest power of 2
from the allocation size,
but not greater than 1 page.
kmem_alloc_phys(D3) (DDI 8 and later)-
Allocate physical-contiguous memory
based on the properties specified in a
physreq(D4)
structure.
kmem_alloc_phys( )
returns a 32-bit physical address.
kmem_alloc_physreq(D3) (DDI 6 and later)-
Allocate physically-contiguous memory,
based on the properties specified in a
physreq(D4)
structure.
kmem_alloc_physreq( )
returns a virtual memory address
that is translated to a physical address with the
vtop(D3)
function.
kmem_free(D3)-
Free memory allocated with the
kmem_alloc( ),
kmem_alloc_phys( ),
kmem_alloc_physreq( ),
kmem_zalloc( ),
or
kmem_zalloc_physreq( )
functions.
kmem_alloc_physcontig(D3)-
Allocate physically contiguous memory
(DDI 5 and 6 only).
kmem_free_physcontig(D3)-
Free memory allocated with the
kmem_alloc_physcontig(D3)
function.
kmem_zalloc(D3)-
Similar to
kmem_alloc( ),
but the allocated memory is cleared
as part of the allocation.
kmem_zalloc_physreq(D3)-
Similar to
kmem_alloc_physreq( ),
but the allocated memory is cleared
as part of the allocation.
physreq_alloc(D3)-
Allocate a physreq structure.
physreq_prep(D3)-
Prepare a physreq structure for use.
This function must be called after
the physreq structure is allocated
and all necessary members have been set,
but before the structure is passed to any
I/O or memory allocation function.
physreq_free(D3)-
Free a physreq structure.
rmallocmap(D3)-
Allocate and initialize a private space management map.
rmalloc(D3)-
Allocate space from a private space management map.
rmalloc_wait(D3)-
Identical to
rmalloc( ),
except that the allocation will block to wait for resources
if necessary.
rmfree(D3)-
Return memory to the private space management map.
rmfreemap(D3)-
Free a private space management map.
rminit(D3) (DDI 1, 2, 4 only)-
Free a private space management map.
Use
rmallocmap(D3)
for current DDI versions.
rmsetwant(D3) (DDI 1, 2, 4 only)-
Set the map's wait flag for a wakeup.
Use
rmalloc_wait(D3)
for current DDI versions.
Note that DDI versions prior to version 5
do not support functions that use the
physreq(D4)
structure.
Non-DDI functions
such as
getcpages( )
and
freepages( )
were available for allocating physically contiguous memory
but these should not be used in current drivers.
ODDI implementation
ODDI
drivers on SCO OpenServer 5
use the following functions to allocate memory:
kmem_alloc(D3oddi)-
Allocate extents of kernel memory.
Flags specify whether or not the allocated memory
is DMA-able
and the contexts in which this function can be called.
kmem_zalloc(D3oddi)-
Similar to
kmem_alloc( ),
but the allocated memory is cleared
as part of the allocation.
kmem_free(D3oddi)-
Free memory allocated with the
kmem_alloc( )
or
kmem_zalloc( )
function.
memget(D3oddi)-
Allocate contiguous memory from an
init(D2oddi)
routine.
sptalloc(D3oddi)-
Allocate memory that can be used by any process
or for mapping in memory from a device.
sptfree(D3oddi)-
Free memory allocated with
sptalloc( ).
getcpages(D3oddi)-
Allocate contiguous pages of memory.
freecpages(D3oddi)-
Free memory allocated with
getcpages( ).
SCO OpenServer 5 also retains support for
older mechanisms for memory allocation.
These are not generally used in new drivers
but are used in some older drivers that are supported:
db_alloc(D3oddi)-
Allocate DMAable memory
that can be read from and written to with the
db_read(D3oddi)
and
db_write(D3oddi)
functions.
db_free(D3oddi)-
Free memory allocated with
db_alloc(D3oddi).
vasmalloc(D3oddi)-
Allocate virtual memory.
vasbind(D3oddi)-
Map non-DMA-able memory
that can be used only by a specific process.
vasmapped(D3oddi)-
Determine if mapping is already in place.
vasunbind(D3oddi)-
Undo a
vasbind( )
mapping.
Allocating STREAMS memory
STREAMS drivers use
the standard DDI and ODDI functions
to allocate memory for general purposes.
The following supplement these functions
to allocate message blocks
for STREAMS and MDI drivers:
allocb(D3str)-
allocate a STREAMS message block
allocb_physreq(D3str) (DDI 6 and later)-
allocate a STREAMS message block
that is DMA-able or satisfies
other physical requirements
such as starting address alignment
or physical address range.
esballoc(D3str)-
allocate a STREAMS message block
by using an externally-supplied buffer.
msgpullup_physreq(D3str)-
align bytes for a message
to satisfy physical DMA requirements.
msgscgth(D3str) (DDI 8 and later)-
construct a DMA scatter/gather list
for a message block.
See
``Messages, STREAMS''
for general information
about allocating STREAMS message blocks.
See
``Message block allocation''
for guidelines about allocating STREAMS message blocks.
SDI implementation
SDI drivers use the
sdi_kmem_alloc_phys(D3sdi)
function to allocate memory
that will be passed to the target device.
The memory allocated is defined with a
physreq(D4)
structure and can be
DMA addressable and device accessible memory.
All other memory allocation is done with
the standard DDI memory allocation functions
such as
kmem_alloc( ).
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 6 and UnixWare (SVR5) HDK - June 2005