unified: rename 'memory maps' to 'memory slabs'
This better aligns with the actual functionality of the object. Change-Id: I70abf54f994e92abd7367251089ea4f735d273fe Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
This commit is contained in:
parent
3c7dda3897
commit
7ef0f624a7
9 changed files with 242 additions and 236 deletions
|
@ -1,145 +0,0 @@
|
|||
.. _memory_maps_v2:
|
||||
|
||||
Memory Maps
|
||||
###########
|
||||
|
||||
A :dfn:`memory map` is a kernel object that allows memory blocks
|
||||
to be dynamically allocated from a designated memory region.
|
||||
All memory blocks in a memory map have a single fixed size,
|
||||
allowing them to be allocated and released efficiently
|
||||
and avoiding memory fragmentation concerns.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
Concepts
|
||||
********
|
||||
|
||||
Any number of memory maps can be defined. Each memory map is referenced
|
||||
by its memory address.
|
||||
|
||||
A memory map has the following key properties:
|
||||
|
||||
* The **block size** of each block, measured in bytes.
|
||||
It must be at least 4 bytes long.
|
||||
|
||||
* The **number of blocks** available for allocation.
|
||||
It must be greater than zero.
|
||||
|
||||
* A **buffer** that provides the memory for the memory map's blocks.
|
||||
It must be at least "block size" times "number of blocks" bytes long.
|
||||
|
||||
A thread that needs to use a memory block simply allocates it from a memory
|
||||
map. When the thread finishes with a memory block,
|
||||
it must release the block back to the memory map so the block can be reused.
|
||||
|
||||
If all the blocks are currently in use, a thread can optionally wait
|
||||
for one to become available.
|
||||
Any number of thread may wait on an empty memory map simultaneously;
|
||||
when a memory block becomes available, it is given to the highest-priority
|
||||
thread that has waited the longest.
|
||||
|
||||
Unlike a heap, more than one memory map can be defined, if needed. This
|
||||
allows for a memory map with smaller blocks and others with larger-sized
|
||||
blocks. Alternatively, a memory pool object may be used.
|
||||
|
||||
Internal Operation
|
||||
==================
|
||||
|
||||
A memory map's buffer is an array of fixed-size blocks,
|
||||
with no wasted space between the blocks.
|
||||
|
||||
The memory map keeps track of unallocated blocks using a linked list;
|
||||
the first 4 bytes of each unused block provide the necessary linkage.
|
||||
|
||||
Implementation
|
||||
**************
|
||||
|
||||
Defining a Memory Map
|
||||
=====================
|
||||
|
||||
A memory map is defined using a variable of type :c:type:`struct k_mem_map`.
|
||||
It must then be initialized by calling :cpp:func:`k_mem_map_init()`.
|
||||
|
||||
The following code defines and initializes a memory map that has 6 blocks
|
||||
of 400 bytes each and is aligned to a 4-byte boundary..
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct k_mem_map my_map;
|
||||
char __aligned(4) my_map_buffer[6 * 400];
|
||||
|
||||
k_mem_map_init(&my_map, my_map_buffer, 400, 6);
|
||||
|
||||
Alternatively, a memory map can be defined and initialized at compile time
|
||||
by calling :c:macro:`K_MEM_MAP_DEFINE()`.
|
||||
|
||||
The following code has the same effect as the code segment above. Observe
|
||||
that the macro defines both the memory map and its buffer.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
K_MEM_MAP_DEFINE(my_map, 400, 6, 4);
|
||||
|
||||
Allocating a Memory Block
|
||||
=========================
|
||||
|
||||
A memory block is allocated by calling :cpp:func:`k_mem_map_alloc()`.
|
||||
|
||||
The following code builds on the example above, and waits up to 100 milliseconds
|
||||
for a memory block to become available, then fills it with zeroes.
|
||||
A warning is printed if a suitable block is not obtained.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
char *block_ptr;
|
||||
|
||||
if (k_mem_map_alloc(&my_map, &block_ptr, 100) == 0)) {
|
||||
memset(block_ptr, 0, 400);
|
||||
...
|
||||
} else {
|
||||
printf("Memory allocation time-out");
|
||||
}
|
||||
|
||||
Releasing a Memory Block
|
||||
========================
|
||||
|
||||
A memory block is released by calling :cpp:func:`k_mem_map_free()`.
|
||||
|
||||
The following code builds on the example above, and allocates a memory block,
|
||||
then releases it once it is no longer needed.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
char *block_ptr;
|
||||
|
||||
k_mem_map_alloc(&my_map, &block_ptr, K_FOREVER);
|
||||
... /* use memory block pointed at by block_ptr */
|
||||
k_mem_map_free(&my_map, &block_ptr);
|
||||
|
||||
Suggested Uses
|
||||
**************
|
||||
|
||||
Use a memory map to allocate and free memory in fixed-size blocks.
|
||||
|
||||
Use memory map blocks when sending large amounts of data from one thread
|
||||
to another, to avoid unnecessary copying of the data.
|
||||
|
||||
Configuration Options
|
||||
*********************
|
||||
|
||||
Related configuration options:
|
||||
|
||||
* None.
|
||||
|
||||
APIs
|
||||
****
|
||||
|
||||
The following memory map APIs are provided by :file:`kernel.h`:
|
||||
|
||||
* :cpp:func:`k_mem_map_init()`
|
||||
* :cpp:func:`k_mem_map_alloc()`
|
||||
* :cpp:func:`k_mem_map_free()`
|
||||
* :cpp:func:`k_mem_map_num_used_get()`
|
||||
* :cpp:func:`k_mem_map_num_free_get()`
|
|
@ -9,6 +9,6 @@ allocate memory.
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
maps.rst
|
||||
slabs.rst
|
||||
pools.rst
|
||||
heap.rst
|
||||
|
|
145
doc/kernel_v2/memory/slabs.rst
Normal file
145
doc/kernel_v2/memory/slabs.rst
Normal file
|
@ -0,0 +1,145 @@
|
|||
.. _memory_slabs_v2:
|
||||
|
||||
Memory slabs
|
||||
############
|
||||
|
||||
A :dfn:`memory slab` is a kernel object that allows memory blocks
|
||||
to be dynamically allocated from a designated memory region.
|
||||
All memory blocks in a memory slab have a single fixed size,
|
||||
allowing them to be allocated and released efficiently
|
||||
and avoiding memory fragmentation concerns.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
Concepts
|
||||
********
|
||||
|
||||
Any number of memory slabs can be defined. Each memory slab is referenced
|
||||
by its memory address.
|
||||
|
||||
A memory slab has the following key properties:
|
||||
|
||||
* The **block size** of each block, measured in bytes.
|
||||
It must be at least 4 bytes long.
|
||||
|
||||
* The **number of blocks** available for allocation.
|
||||
It must be greater than zero.
|
||||
|
||||
* A **buffer** that provides the memory for the memory slab's blocks.
|
||||
It must be at least "block size" times "number of blocks" bytes long.
|
||||
|
||||
A thread that needs to use a memory block simply allocates it from a memory
|
||||
slab. When the thread finishes with a memory block,
|
||||
it must release the block back to the memory slab so the block can be reused.
|
||||
|
||||
If all the blocks are currently in use, a thread can optionally wait
|
||||
for one to become available.
|
||||
Any number of threads may wait on an empty memory slab simultaneously;
|
||||
when a memory block becomes available, it is given to the highest-priority
|
||||
thread that has waited the longest.
|
||||
|
||||
Unlike a heap, more than one memory slab can be defined, if needed. This
|
||||
allows for a memory slab with smaller blocks and others with larger-sized
|
||||
blocks. Alternatively, a memory pool object may be used.
|
||||
|
||||
Internal Operation
|
||||
==================
|
||||
|
||||
A memory slab's buffer is an array of fixed-size blocks,
|
||||
with no wasted space between the blocks.
|
||||
|
||||
The memory slab keeps track of unallocated blocks using a linked list;
|
||||
the first 4 bytes of each unused block provide the necessary linkage.
|
||||
|
||||
Implementation
|
||||
**************
|
||||
|
||||
Defining a Memory Slab
|
||||
======================
|
||||
|
||||
A memory slab is defined using a variable of type :c:type:`struct k_mem_slab`.
|
||||
It must then be initialized by calling :cpp:func:`k_mem_slab_init()`.
|
||||
|
||||
The following code defines and initializes a memory slab that has 6 blocks
|
||||
of 400 bytes each and is aligned to a 4-byte boundary..
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct k_mem_slab my_slab;
|
||||
char __aligned(4) my_slab_buffer[6 * 400];
|
||||
|
||||
k_mem_slab_init(&my_slab, my_slab_buffer, 400, 6);
|
||||
|
||||
Alternatively, a memory slab can be defined and initialized at compile time
|
||||
by calling :c:macro:`K_MEM_SLAB_DEFINE()`.
|
||||
|
||||
The following code has the same effect as the code segment above. Observe
|
||||
that the macro defines both the memory slab and its buffer.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
K_MEM_SLAB_DEFINE(my_slab, 400, 6, 4);
|
||||
|
||||
Allocating a Memory Block
|
||||
=========================
|
||||
|
||||
A memory block is allocated by calling :cpp:func:`k_mem_slab_alloc()`.
|
||||
|
||||
The following code builds on the example above, and waits up to 100 milliseconds
|
||||
for a memory block to become available, then fills it with zeroes.
|
||||
A warning is printed if a suitable block is not obtained.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
char *block_ptr;
|
||||
|
||||
if (k_mem_slab_alloc(&my_slab, &block_ptr, 100) == 0)) {
|
||||
memset(block_ptr, 0, 400);
|
||||
...
|
||||
} else {
|
||||
printf("Memory allocation time-out");
|
||||
}
|
||||
|
||||
Releasing a Memory Block
|
||||
========================
|
||||
|
||||
A memory block is released by calling :cpp:func:`k_mem_slab_free()`.
|
||||
|
||||
The following code builds on the example above, and allocates a memory block,
|
||||
then releases it once it is no longer needed.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
char *block_ptr;
|
||||
|
||||
k_mem_slab_alloc(&my_slab, &block_ptr, K_FOREVER);
|
||||
... /* use memory block pointed at by block_ptr */
|
||||
k_mem_slab_free(&my_slab, &block_ptr);
|
||||
|
||||
Suggested Uses
|
||||
**************
|
||||
|
||||
Use a memory slab to allocate and free memory in fixed-size blocks.
|
||||
|
||||
Use memory slab blocks when sending large amounts of data from one thread
|
||||
to another, to avoid unnecessary copying of the data.
|
||||
|
||||
Configuration Options
|
||||
*********************
|
||||
|
||||
Related configuration options:
|
||||
|
||||
* None.
|
||||
|
||||
APIs
|
||||
****
|
||||
|
||||
The following memory slab APIs are provided by :file:`kernel.h`:
|
||||
|
||||
* :cpp:func:`k_mem_slab_init()`
|
||||
* :cpp:func:`k_mem_slab_alloc()`
|
||||
* :cpp:func:`k_mem_slab_free()`
|
||||
* :cpp:func:`k_mem_slab_num_used_get()`
|
||||
* :cpp:func:`k_mem_slab_num_free_get()`
|
|
@ -120,6 +120,9 @@ The microkernel mailbox object type now supports the sending of asynchronous
|
|||
messages using a message buffer. (The version 1 kernel only supported
|
||||
asynchronous messages using a message block.)
|
||||
|
||||
The microkernel memory map object has been renamed to "memory slab", to better
|
||||
reflect its management of equal-size memory blocks.
|
||||
|
||||
Task Groups
|
||||
***********
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ struct k_pipe;
|
|||
struct k_fifo;
|
||||
struct k_lifo;
|
||||
struct k_stack;
|
||||
struct k_mem_map;
|
||||
struct k_mem_slab;
|
||||
struct k_mem_pool;
|
||||
struct k_timer;
|
||||
|
||||
|
@ -1395,9 +1395,9 @@ extern void k_pipe_block_put(struct k_pipe *pipe, struct k_mem_block *block,
|
|||
* memory management
|
||||
*/
|
||||
|
||||
/* memory maps */
|
||||
/* memory slabs */
|
||||
|
||||
struct k_mem_map {
|
||||
struct k_mem_slab {
|
||||
_wait_q_t wait_q;
|
||||
uint32_t num_blocks;
|
||||
size_t block_size;
|
||||
|
@ -1405,65 +1405,66 @@ struct k_mem_map {
|
|||
char *free_list;
|
||||
uint32_t num_used;
|
||||
|
||||
_DEBUG_TRACING_KERNEL_OBJECTS_NEXT_PTR(k_mem_map);
|
||||
_DEBUG_TRACING_KERNEL_OBJECTS_NEXT_PTR(k_mem_slab);
|
||||
};
|
||||
|
||||
#define K_MEM_MAP_INITIALIZER(obj, map_buffer, map_block_size, map_num_blocks) \
|
||||
#define K_MEM_SLAB_INITIALIZER(obj, slab_buffer, slab_block_size, \
|
||||
slab_num_blocks) \
|
||||
{ \
|
||||
.wait_q = SYS_DLIST_STATIC_INIT(&obj.wait_q), \
|
||||
.num_blocks = map_num_blocks, \
|
||||
.block_size = map_block_size, \
|
||||
.buffer = map_buffer, \
|
||||
.num_blocks = slab_num_blocks, \
|
||||
.block_size = slab_block_size, \
|
||||
.buffer = slab_buffer, \
|
||||
.free_list = NULL, \
|
||||
.num_used = 0, \
|
||||
_DEBUG_TRACING_KERNEL_OBJECTS_INIT \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Define a memory map
|
||||
* @brief Define a memory slab
|
||||
*
|
||||
* This declares and initializes a memory map whose buffer is aligned to
|
||||
* a @a map_align -byte boundary. The new memory map can be passed to the
|
||||
* kernel's memory map functions.
|
||||
* This declares and initializes a memory slab whose buffer is aligned to
|
||||
* a @a slab_align -byte boundary. The new memory slab can be passed to the
|
||||
* kernel's memory slab functions.
|
||||
*
|
||||
* Note that for each of the blocks in the memory map to be aligned to
|
||||
* @a map_align bytes, then @a map_block_size must be a multiple of
|
||||
* @a map_align.
|
||||
* Note that for each of the blocks in the memory slab to be aligned to
|
||||
* @a slab_align bytes, then @a slab_block_size must be a multiple of
|
||||
* @a slab_align.
|
||||
*
|
||||
* @param name Name of the memory map
|
||||
* @param map_block_size Size of each block in the buffer (in bytes)
|
||||
* @param map_num_blocks Number blocks in the buffer
|
||||
* @param map_align Alignment of the memory map's buffer (power of 2)
|
||||
* @param name Name of the memory slab
|
||||
* @param slab_block_size Size of each block in the buffer (in bytes)
|
||||
* @param slab_num_blocks Number blocks in the buffer
|
||||
* @param slab_align Alignment of the memory slab's buffer (power of 2)
|
||||
*/
|
||||
#define K_MEM_MAP_DEFINE(name, map_block_size, map_num_blocks, map_align) \
|
||||
char __noinit __aligned(map_align) \
|
||||
_k_mem_map_buf_##name[(map_num_blocks) * (map_block_size)]; \
|
||||
struct k_mem_map name \
|
||||
__in_section(_k_mem_map_ptr, private, mem_map) = \
|
||||
K_MEM_MAP_INITIALIZER(name, _k_mem_map_buf_##name, \
|
||||
map_block_size, map_num_blocks)
|
||||
#define K_MEM_SLAB_DEFINE(name, slab_block_size, slab_num_blocks, slab_align) \
|
||||
char __noinit __aligned(slab_align) \
|
||||
_k_mem_slab_buf_##name[(slab_num_blocks) * (slab_block_size)]; \
|
||||
struct k_mem_slab name \
|
||||
__in_section(_k_mem_map_ptr, private, mem_slab) = \
|
||||
K_MEM_SLAB_INITIALIZER(name, _k_mem_slab_buf_##name, \
|
||||
slab_block_size, slab_num_blocks)
|
||||
|
||||
/**
|
||||
* @brief Initialize a memory map.
|
||||
* @brief Initialize a memory slab.
|
||||
*
|
||||
* Initializes the memory map and creates its list of free blocks.
|
||||
* Initializes the memory slab and creates its list of free blocks.
|
||||
*
|
||||
* @param map Pointer to the memory map object
|
||||
* @param slab Pointer to the memory slab object
|
||||
* @param buffer Pointer to buffer used for the blocks.
|
||||
* @param block_size Size of each block, in bytes.
|
||||
* @param num_blocks Number of blocks.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
extern void k_mem_map_init(struct k_mem_map *map, void *buffer,
|
||||
extern void k_mem_slab_init(struct k_mem_slab *slab, void *buffer,
|
||||
size_t block_size, uint32_t num_blocks);
|
||||
|
||||
/**
|
||||
* @brief Allocate a memory map block.
|
||||
* @brief Allocate a memory slab block.
|
||||
*
|
||||
* Takes a block from the list of unused blocks.
|
||||
*
|
||||
* @param map Pointer to memory map object.
|
||||
* @param slab Pointer to memory slab object.
|
||||
* @param mem Pointer to area to receive block address.
|
||||
* @param timeout Maximum time (milliseconds) to wait for allocation to
|
||||
* complete. Use K_NO_WAIT to return immediately, or K_FOREVER to wait
|
||||
|
@ -1471,20 +1472,21 @@ extern void k_mem_map_init(struct k_mem_map *map, void *buffer,
|
|||
*
|
||||
* @return 0 if successful, -ENOMEM if failed immediately, -EAGAIN if timed out
|
||||
*/
|
||||
extern int k_mem_map_alloc(struct k_mem_map *map, void **mem, int32_t timeout);
|
||||
extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem,
|
||||
int32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Free a memory map block.
|
||||
* @brief Free a memory slab block.
|
||||
*
|
||||
* Gives block to a waiting thread if there is one, otherwise returns it to
|
||||
* the list of unused blocks.
|
||||
*
|
||||
* @param map Pointer to memory map object.
|
||||
* @param slab Pointer to memory slab object.
|
||||
* @param mem Pointer to area to containing block address.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
extern void k_mem_map_free(struct k_mem_map *map, void **mem);
|
||||
extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem);
|
||||
|
||||
/**
|
||||
* @brief Get the number of used memory blocks
|
||||
|
@ -1493,13 +1495,13 @@ extern void k_mem_map_free(struct k_mem_map *map, void **mem);
|
|||
* specified pool. It should be used for stats purposes only as that
|
||||
* value may potentially be out-of-date by the time it is used.
|
||||
*
|
||||
* @param map Memory map to query
|
||||
* @param slab Memory slab to query
|
||||
*
|
||||
* @return Number of used memory blocks
|
||||
*/
|
||||
static inline uint32_t k_mem_map_num_used_get(struct k_mem_map *map)
|
||||
static inline uint32_t k_mem_slab_num_used_get(struct k_mem_slab *slab)
|
||||
{
|
||||
return map->num_used;
|
||||
return slab->num_used;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1509,13 +1511,13 @@ static inline uint32_t k_mem_map_num_used_get(struct k_mem_map *map)
|
|||
* specified pool. It should be used for stats purposes only as that value
|
||||
* may potentially be out-of-date by the time it is used.
|
||||
*
|
||||
* @param map Memory map to query
|
||||
* @param slab Memory slab to query
|
||||
*
|
||||
* @return Number of unused memory blocks
|
||||
*/
|
||||
static inline uint32_t k_mem_map_num_free_get(struct k_mem_map *map)
|
||||
static inline uint32_t k_mem_slab_num_free_get(struct k_mem_slab *slab)
|
||||
{
|
||||
return map->num_blocks - map->num_used;
|
||||
return slab->num_blocks - slab->num_used;
|
||||
}
|
||||
|
||||
/* memory pools */
|
||||
|
|
|
@ -398,25 +398,26 @@ static inline int task_event_recv(kevent_t legacy_event, int32_t timeout)
|
|||
|
||||
/* memory maps */
|
||||
|
||||
#define kmemory_map_t struct k_mem_map *
|
||||
#define kmemory_map_t struct k_mem_slab *
|
||||
|
||||
static inline int task_mem_map_alloc(kmemory_map_t map, void **mptr,
|
||||
int32_t timeout)
|
||||
{
|
||||
return _error_to_rc(k_mem_map_alloc(map, mptr, _ticks_to_ms(timeout)));
|
||||
return _error_to_rc(k_mem_slab_alloc(map, mptr,
|
||||
_ticks_to_ms(timeout)));
|
||||
}
|
||||
|
||||
#define task_mem_map_free k_mem_map_free
|
||||
#define task_mem_map_free k_mem_slab_free
|
||||
|
||||
static inline int task_mem_map_used_get(kmemory_map_t map)
|
||||
{
|
||||
return (int)k_mem_map_num_used_get(map);
|
||||
return (int)k_mem_slab_num_used_get(map);
|
||||
}
|
||||
|
||||
#define DEFINE_MEM_MAP(name, map_num_blocks, map_block_size) \
|
||||
K_MEM_MAP_DEFINE(_k_mem_map_obj_##name, map_block_size, \
|
||||
map_num_blocks, 4); \
|
||||
struct k_mem_map *const name = &_k_mem_map_obj_##name
|
||||
K_MEM_SLAB_DEFINE(_k_mem_map_obj_##name, map_block_size, \
|
||||
map_num_blocks, 4); \
|
||||
struct k_mem_slab *const name = &_k_mem_map_obj_##name
|
||||
|
||||
|
||||
/* memory pools */
|
||||
|
|
|
@ -21,7 +21,7 @@ lib-y += $(strip \
|
|||
lifo.o \
|
||||
fifo.o \
|
||||
stack.o \
|
||||
mem_map.o \
|
||||
mem_slab.o \
|
||||
mem_pool.o \
|
||||
msg_q.o \
|
||||
mailbox.o \
|
||||
|
|
|
@ -24,73 +24,73 @@
|
|||
#include <ksched.h>
|
||||
#include <init.h>
|
||||
|
||||
extern struct k_mem_map _k_mem_map_ptr_start[];
|
||||
extern struct k_mem_map _k_mem_map_ptr_end[];
|
||||
extern struct k_mem_slab _k_mem_map_ptr_start[];
|
||||
extern struct k_mem_slab _k_mem_map_ptr_end[];
|
||||
|
||||
/**
|
||||
* @brief Initialize kernel memory map subsystem.
|
||||
* @brief Initialize kernel memory slab subsystem.
|
||||
*
|
||||
* Perform any initialization of memory maps that wasn't done at build time.
|
||||
* Currently this just involves creating the list of free blocks for each map.
|
||||
* Perform any initialization of memory slabs that wasn't done at build time.
|
||||
* Currently this just involves creating the list of free blocks for each slab.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static void create_free_list(struct k_mem_map *map)
|
||||
static void create_free_list(struct k_mem_slab *slab)
|
||||
{
|
||||
char *p;
|
||||
int j;
|
||||
|
||||
map->free_list = NULL;
|
||||
p = map->buffer;
|
||||
slab->free_list = NULL;
|
||||
p = slab->buffer;
|
||||
|
||||
for (j = 0; j < map->num_blocks; j++) {
|
||||
*(char **)p = map->free_list;
|
||||
map->free_list = p;
|
||||
p += map->block_size;
|
||||
for (j = 0; j < slab->num_blocks; j++) {
|
||||
*(char **)p = slab->free_list;
|
||||
slab->free_list = p;
|
||||
p += slab->block_size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Complete initialization of statically defined memory maps.
|
||||
* @brief Complete initialization of statically defined memory slabs.
|
||||
*
|
||||
* Perform any initialization that wasn't done at build time.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static int init_mem_map_module(struct device *dev)
|
||||
static int init_mem_slab_module(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
struct k_mem_map *map;
|
||||
struct k_mem_slab *slab;
|
||||
|
||||
for (map = _k_mem_map_ptr_start; map < _k_mem_map_ptr_end; map++) {
|
||||
create_free_list(map);
|
||||
for (slab = _k_mem_map_ptr_start; slab < _k_mem_map_ptr_end; slab++) {
|
||||
create_free_list(slab);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void k_mem_map_init(struct k_mem_map *map, void *buffer,
|
||||
void k_mem_slab_init(struct k_mem_slab *slab, void *buffer,
|
||||
size_t block_size, uint32_t num_blocks)
|
||||
{
|
||||
map->num_blocks = num_blocks;
|
||||
map->block_size = block_size;
|
||||
map->buffer = buffer;
|
||||
map->num_used = 0;
|
||||
create_free_list(map);
|
||||
sys_dlist_init(&map->wait_q);
|
||||
SYS_TRACING_OBJ_INIT(mem_map, map);
|
||||
slab->num_blocks = num_blocks;
|
||||
slab->block_size = block_size;
|
||||
slab->buffer = buffer;
|
||||
slab->num_used = 0;
|
||||
create_free_list(slab);
|
||||
sys_dlist_init(&slab->wait_q);
|
||||
SYS_TRACING_OBJ_INIT(micro_mem_map, slab);
|
||||
}
|
||||
|
||||
int k_mem_map_alloc(struct k_mem_map *map, void **mem, int32_t timeout)
|
||||
int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, int32_t timeout)
|
||||
{
|
||||
unsigned int key = irq_lock();
|
||||
int result;
|
||||
|
||||
if (map->free_list != NULL) {
|
||||
if (slab->free_list != NULL) {
|
||||
/* take a free block */
|
||||
*mem = map->free_list;
|
||||
map->free_list = *(char **)(map->free_list);
|
||||
map->num_used++;
|
||||
*mem = slab->free_list;
|
||||
slab->free_list = *(char **)(slab->free_list);
|
||||
slab->num_used++;
|
||||
result = 0;
|
||||
} else if (timeout == K_NO_WAIT) {
|
||||
/* don't wait for a free block to become available */
|
||||
|
@ -98,7 +98,7 @@ int k_mem_map_alloc(struct k_mem_map *map, void **mem, int32_t timeout)
|
|||
result = -ENOMEM;
|
||||
} else {
|
||||
/* wait for a free block or timeout */
|
||||
_pend_current_thread(&map->wait_q, timeout);
|
||||
_pend_current_thread(&slab->wait_q, timeout);
|
||||
result = _Swap(key);
|
||||
if (result == 0) {
|
||||
*mem = _current->swap_data;
|
||||
|
@ -111,10 +111,10 @@ int k_mem_map_alloc(struct k_mem_map *map, void **mem, int32_t timeout)
|
|||
return result;
|
||||
}
|
||||
|
||||
void k_mem_map_free(struct k_mem_map *map, void **mem)
|
||||
void k_mem_slab_free(struct k_mem_slab *slab, void **mem)
|
||||
{
|
||||
int key = irq_lock();
|
||||
struct k_thread *pending_thread = _unpend_first_thread(&map->wait_q);
|
||||
struct k_thread *pending_thread = _unpend_first_thread(&slab->wait_q);
|
||||
|
||||
if (pending_thread) {
|
||||
_set_thread_return_value_with_data(pending_thread, 0, *mem);
|
||||
|
@ -125,12 +125,12 @@ void k_mem_map_free(struct k_mem_map *map, void **mem)
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
**(char ***)mem = map->free_list;
|
||||
map->free_list = *(char **)mem;
|
||||
map->num_used--;
|
||||
**(char ***)mem = slab->free_list;
|
||||
slab->free_list = *(char **)mem;
|
||||
slab->num_used--;
|
||||
}
|
||||
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
SYS_INIT(init_mem_map_module, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
|
||||
SYS_INIT(init_mem_slab_module, PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
|
|
@ -788,7 +788,7 @@ def kernel_main_c_maps():
|
|||
name = map[0]
|
||||
blocks = map[1]
|
||||
block_size = map[2]
|
||||
kernel_main_c_out("K_MEM_MAP_DEFINE(_k_mem_map_obj_%s, %s, %s, 4);\n" %
|
||||
kernel_main_c_out("K_MEM_SLAB_DEFINE(_k_mem_map_obj_%s, %s, %s, 4);\n" %
|
||||
(name, block_size, blocks))
|
||||
|
||||
|
||||
|
@ -1126,8 +1126,8 @@ def generate_sysgen_h_obj_ids():
|
|||
sem_type = 'struct k_sem *'
|
||||
pipe_struct = 'k_pipe'
|
||||
pipe_type = 'struct k_pipe *'
|
||||
map_struct = 'k_mem_map'
|
||||
map_type = 'struct k_mem_map *'
|
||||
map_struct = 'k_mem_slab'
|
||||
map_type = 'struct k_mem_slab *'
|
||||
fifo_struct = 'k_msgq'
|
||||
fifo_type = 'struct k_msgq *'
|
||||
mbox_struct = 'k_mbox'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue